Tryig to use SDL_audio in a class structure

Hello All,

I am using the SDL library for sound in my QT application (since somehow my
native platform does not suppot sound using QT). I have created a seperate
class for sound and am trying to compile my project but I keep getting the
following errors:

Error 1: argument of type 'void MyClass::)(void*, Uint8*, int) does not
match ‘void ()(void , Uint8, int)'
Error 2: argument of type 'void (MyProgram::)(int) does not match void (
)
(int)’

My program structure looks like this:-----------------------------------------------------------------
myclass.h

struct {
SDL_AudioSpec spec;
Uint8 *sound;
Uint32 soundlen;
int soundpos;
} wave;

static int done = 0;

class MyClass
{

void fillerup(void *, Uint8 *, int);
void poked(int);
void play (char *);
};


myclass.cpp

void MyClass::poked(int sig)
{
done = 1;
}

void MyClass:: fillerup(void *unused, Uint8 *stream, int len)
{
//code here
}

void MyClass::play(char *file)
{
//some code

wave.spec.callback = fillerup; error is here for error 1

//some code

signal(SIGHUP, poked); //error is here for error 2
}

I guess it is because of somekind of callback issue. How do I resolve this?
Please help me define a class structure for the above program that works. I
have reference loopwave.c for the audio code.

Regards

Dhruv

Dhruv Thukral wrote:

Hello All,

I am using the SDL library for sound in my QT application (since somehow my
native platform does not suppot sound using QT). I have created a seperate
class for sound and am trying to compile my project but I keep getting the
following errors:

Error 1: argument of type 'void MyClass::)(void*, Uint8*, int) does not
match ‘void ()(void , Uint8, int)'
Error 2: argument of type 'void (MyProgram::)(int) does not match void (
)
(int)’

My program structure looks like this:

You can’t use C++ class member functions as callbacks, at least not
directly.

If the callback prototype has a “User data” pointer, you can do it with
some trickery. This rules out signal handlers as there is no such
pointer passed. You can however do it with the SDL audio callback as
there is such a field. You would do something like this

class MyClass
{
SDL_AudioSpec spec;

void callback(Uint8 *, int);
void play (char *);

};

void MixCallback(void *class, Uint8 *stream, int len)
{
MyClass *ptr = (MyClass *) class;

ptr->callback(stream, len);

}

void MyClass::callback(Uint8 *stream, int len)
{
// whatever here
}

void MyClass::play(char *file)
{
//some code

spec.userdata = (void *) this;
spec.callback = MixCallback;

}

What happens here is that the C function MixCallback() is called by SDL,
and then the user data field is used to retrieve the “this” pointer of
the class. This is then used to call the real callback function inside
the class.

Bear in mind that you will only be able to have ONE instance of this class.

Pete.

Can you not take the Windows tactic of declaring the callback function
as a static member? That leaves one “shared” instance of the function
for all objects of the class.

Please excuse me if this is a bit naive. I’d been out of programming
for years before I finally got back into learning programming Windows
and in the rush I haven’t had much time to dwell on the more minute
mechanics of it.–
Lilith

On 7/22/2006 at 12:45 AM, in message <44C1BB64.6010205 at freeuk.com>, darkmatter at freeuk.com wrote:
Dhruv Thukral wrote:
Hello All,

I am using the SDL library for sound in my QT application (since
somehow my

native platform does not suppot sound using QT). I have created a
seperate

class for sound and am trying to compile my project but I keep
getting the

following errors:

Error 1: argument of type 'void MyClass::)(void*, Uint8*, int) does
not

match 'void ()(void , Uint8, int)'
Error 2: argument of type 'void (MyProgram::)(int) does not match
void (
)

(int)’

My program structure looks like this:

You can’t use C++ class member functions as callbacks, at least not
directly.

If the callback prototype has a “User data” pointer, you can do it
with
some trickery. This rules out signal handlers as there is no such
pointer passed. You can however do it with the SDL audio callback as

there is such a field. You would do something like this

class MyClass
{
SDL_AudioSpec spec;

void callback(Uint8 *, int);
void play (char *);
};

void MixCallback(void *class, Uint8 *stream, int len)
{
MyClass *ptr = (MyClass *) class;

ptr->callback(stream, len);
}

void MyClass::callback(Uint8 *stream, int len)
{
// whatever here
}

void MyClass::play(char *file)
{
//some code

spec.userdata = (void *) this;
spec.callback = MixCallback;
}

What happens here is that the C function MixCallback() is called by
SDL,
and then the user data field is used to retrieve the “this” pointer
of
the class. This is then used to call the real callback function
inside
the class.

Bear in mind that you will only be able to have ONE instance of this
class.

Pete.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Lilith Calbridge wrote:

Can you not take the Windows tactic of declaring the callback function
as a static member? That leaves one “shared” instance of the function
for all objects of the class.

I think you can do this, but then you don’t get access to any class
member variables as there is no way to know which instance of the class
to use. That is why you have to do a redirect, storing the "this"
pointer for that class in some user-data pointer.

You can create a certain kind of class called a Singleton which
guarantees that all instances of a class refer to one single object, but
that still requires you to bounce callbacks as shown here.

In fact, this is one of the flaws I find in SDL_mixer, which has
callbacks for things like “Music finished” and “Channel finished”, but
no user data field, making them unusable from a C++ class. It’s one
thing I’d like to see added to SDL_mixer at some point.

Pete.

Hi everyone,

I think what Lilith meant was something like this, no?

class MyClass
{
MyClass()
{ setup_callback (value_changed_cb, this); }

static void value_changed_cb (MyClass *pThis)
{
pThis->whatever();
// you may access even private members of course
}
};

I am in a project where I use C++ and plain GTK+, and GTK+ use callbacks for
events, so the code would be quite a pain to read the way you deal with
callbacks.

Cheers,
RicardoEm S?bado, 22 de Julho de 2006 17:48, o Peter Mulholland escreveu:

Lilith Calbridge wrote:

Can you not take the Windows tactic of declaring the callback function
as a static member? That leaves one “shared” instance of the function
for all objects of the class.

I think you can do this, but then you don’t get access to any class
member variables as there is no way to know which instance of the class
to use. That is why you have to do a redirect, storing the "this"
pointer for that class in some user-data pointer.

You can create a certain kind of class called a Singleton which
guarantees that all instances of a class refer to one single object, but
that still requires you to bounce callbacks as shown here.

In fact, this is one of the flaws I find in SDL_mixer, which has
callbacks for things like “Music finished” and “Channel finished”, but
no user data field, making them unusable from a C++ class. It’s one
thing I’d like to see added to SDL_mixer at some point.

Pete.


Let He who taketh the Plunge Remember to return it by Tuesday.

Ricardo Cruz wrote:

Hi everyone,

I think what Lilith meant was something like this, no?

Hmm yes, I see that does clean some things up. However a) you still need
the User Data field in whatever is providing the callback and b) you
need to do a “bounce”, but using a static class member function is nicer
than having a seperate C function to do it.

Thanks for the tip :wink:

Pete.

Hello All,

Thank you for all your help. As you suggested I created static member
functions so the ‘this’ pointer is not passed and it is working now. However
the signal handlers are not working as already mentioned by Pete. As a
follow up I also could use help on the program loopwave.c since it keeps
looping the sound file and i want it to play the file only once. I have
attached the original source with the email. Any help would be appreciated.

Regards

Dhruv
-------------- next part --------------
A non-text attachment was scrubbed…
Name: SDL_PlaySound.zip
Type: application/zip
Size: 7590 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060724/f723d497/attachment.zip

Dhruv Thukral wrote:

Hello All,

Thank you for all your help. As you suggested I created static member
functions so the ‘this’ pointer is not passed and it is working now.
However
the signal handlers are not working as already mentioned by Pete. As a
follow up I also could use help on the program loopwave.c since it keeps
looping the sound file and i want it to play the file only once. I have
attached the original source with the email. Any help would be appreciated.

Are you intending to play more than one sound at once ?

It sounds like you really want to use SDL_mixer rather than SDL’s raw
audio functionality. SDL’s audio code basically expects you to
continually fill the buffer full of data, at the same speed and bit
depth as opened. To play one-shot sounds or a mix of sounds, extra
functionality is needed. SDL_mixer provides such functionality.

Pete.