pyFMOD writing a callback function in Python

  • Thread starter =?ISO-8859-1?Q?Marian_Aldenh=F6vel?=
  • Start date
?

=?ISO-8859-1?Q?Marian_Aldenh=F6vel?=

Hi,

I am using the FMOD audio-library with the pyFMOD python bindings. pyFMOD uses
ctypes. It is possible to register callback functions with FMOD that are
called at certain points in the processing pipeline or when certain events
happen.

I am expecially interested in the one that fires when a currently playing
stream ends. This is what the declaration in pyFMOD looks like:

_FSOUND_Stream_SetEndCallback =
getattr(fmod,"_FSOUND_Stream_SetEndCallback@12")
_FSOUND_Stream_SetEndCallback.restype = c_byte
def FSOUND_Stream_SetEndCallback(stream, callback, userdata):
result = _FSOUND_Stream_SetEndCallback(c_int(stream), c_int(callback),
c_int(userdata))
if not result: raise fmod_exception()

I cannot make it work, however. I tried:

def _sound_end_callback(stream,buf,len,userdata):
print "_sound_end_callback(): Stream has reached the end."

as simplest possible callback function. I am registering it like this:

pyFMOD.FSOUND_Stream_SetEndCallback(_currenttrack,_sound_end_callback,0)

And this is how my program dies:

File "d:\projekte\eclipse\workspace\gettone\gettonesound.py", line 175, in
sound_tick
pyFMOD.FSOUND_Stream_SetEndCallback(_currenttrack,_sound_end_callback,0)
File "c:\programme\Python23\lib\site-packages\pyFMOD.py", line 690, in
FSOUND_Stream_SetEndCallback
result = _FSOUND_Stream_SetEndCallback(c_int(stream), c_int(callback),
c_int(userdata))
TypeError: int expected instead of function instance

I am very new to Python and have zero idea what the problem is nor how to
solve it. In some of my other languages I would have to explicitly make a
function pointer and possibly have to cast that to an int to pass it to
SetEndCallback, but that seems very inappropriate in Python...

Ciao, MM
 
T

Thomas Heller

Marian Aldenhövel said:
Hi,

I am using the FMOD audio-library with the pyFMOD python bindings. pyFMOD uses
ctypes.

I was looking into this recently, because another poster also asked
about pyFMOD: which FMOD version do you use? I was only able to find
fmodapi374.zip (for windows), and that version doesn't seem to work with
the pyFMOD release I found.
It is possible to register callback functions with FMOD that are
called at certain points in the processing pipeline or when certain events
happen.

I am expecially interested in the one that fires when a currently playing
stream ends. This is what the declaration in pyFMOD looks like:

_FSOUND_Stream_SetEndCallback =
getattr(fmod,"_FSOUND_Stream_SetEndCallback@12")
_FSOUND_Stream_SetEndCallback.restype = c_byte
def FSOUND_Stream_SetEndCallback(stream, callback, userdata):
result = _FSOUND_Stream_SetEndCallback(c_int(stream), c_int(callback),
c_int(userdata))
if not result: raise fmod_exception()

I cannot make it work, however. I tried:

def _sound_end_callback(stream,buf,len,userdata):
print "_sound_end_callback(): Stream has reached the end."

as simplest possible callback function. I am registering it like this:

pyFMOD.FSOUND_Stream_SetEndCallback(_currenttrack,_sound_end_callback,0)

And this is how my program dies:

File "d:\projekte\eclipse\workspace\gettone\gettonesound.py", line
175, in sound_tick
pyFMOD.FSOUND_Stream_SetEndCallback(_currenttrack,_sound_end_callback,0)
File "c:\programme\Python23\lib\site-packages\pyFMOD.py", line 690,
in FSOUND_Stream_SetEndCallback
result = _FSOUND_Stream_SetEndCallback(c_int(stream),
c_int(callback), c_int(userdata))
TypeError: int expected instead of function instance

The first problem is that the FSOUND_Stream_SetEndCallback function, as
given, converts all parameters to integers.
Second, you cannot pass a Python function directly as callback, you have
to create a function prototype first which specifies calling convention,
return type, and argument types.
Third, you instantiate the prototype with a Python callable, which
creates the C callable callback function, and use that in the
FSOUND_Stream_SetEndCallback call.
All in all, it should look similar (I can't test it!) to this code:

_FSOUND_Stream_SetEndCallback = getattr(fmod,"_FSOUND_Stream_SetEndCallback@12")
_FSOUND_Stream_SetEndCallback.restype = c_byte
def FSOUND_Stream_SetEndCallback(stream, callback, userdata):
result = _FSOUND_Stream_SetEndCallback(c_int(stream), callback,
c_int(userdata))
if not result: raise fmod_exception()

# from the FMOD header file:
##typedef signed char (F_CALLBACKAPI *FSOUND_STREAMCALLBACK)
## (FSOUND_STREAM *stream, void *buff, int len, void *userdata);

# funtion prototype
FSOUND_STREAMCALLBACK = WINFUNCTYPE(c_char, c_int, c_void_p, c_int, c_void_p)

# create callback function
callback_function = FSOUND_STREAMCALLBACK(_sound_end_callback)

# and then put it to work:

FSOUND_Stream_SetEndCallback(stream, callback_function, userdata)


You should also be aware that you have to keep the callback_function
object alive *as long as the FMOD library is using it*! If you don't,
it will probably crash.
I am very new to Python and have zero idea what the problem is nor how to
solve it. In some of my other languages I would have to explicitly make a
function pointer and possibly have to cast that to an int to pass it to
SetEndCallback, but that seems very inappropriate in Python...

Thomas
 
G

Gary Bishop

Check out pySonic, a new FMOD wrapper written with Pyrex. Much more Pythonic.

gb
 
?

=?ISO-8859-1?Q?Marian_Aldenh=F6vel?=

Hi,
I was only able to find fmodapi374.zip (for windows), and that version doesn't
> seem to work with the pyFMOD release I found.

I found that too. But I could easily fix pyFMOD to use the FMOD 374. A few of
the exports have been renamed and parameters have been added to others. As the
total size of all parameters are encoded in the exported names all of these
errors are caught when importing so you can fix them one by one by looking it
up in the FMOD-Docs.
All in all, it should look similar (I can't test it!) to this code:

I will try that when I get around to playing with the stuff again.
You should also be aware that you have to keep the callback_function
object alive *as long as the FMOD library is using it*!

While very obvious I am prone to forget that sometime :).

Ciao, MM
 
?

=?ISO-8859-1?Q?Marian_Aldenh=F6vel?=

Hi,
Check out pySonic, a new FMOD wrapper written with Pyrex. Much more Pythonic.

I have only found Win32-Downloads. The same is true for pyFMOD. What options
do I have to make it work on Linux?

Ciao, MM
 
G

Gary Bishop

I haven't tried it on Linux but I believe it should work. FMOD works on Linux as does Pyrex.
I don't think there is any win32 specific code. Grab the source and try building it. You'll
likely have to fool with the libraries and includes in setup.py.

gb
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,786
Messages
2,569,625
Members
45,322
Latest member
ClaritaMcI

Latest Threads

Top