ALLEGRO_AUDIO_STREAM possible to add API to access the 'extra' ponter?
pkrcel

Yo Allegators!

As the thread title suggests, I was wondering why the 'extra' userdata pointer in the ALLEGRO_AUDIO_STREAM structure does not have an API to be accessed/used.

I've scoured through the current stream implementations and ALL and EACH of them use the extra pointer to pass a pointer to the file structure (being it WAV, OGG, IT, MOD, whatever), which comes in handy when usign the feeder thread.

I was looking into implementing a stream version for a WildMidi sample Loader, and of course I'd like to take advantage of threading in Allegro to have an automatic feeding mechanism, but unless I explicitly ADD a wildmidi loader to Allegro itself, I can't access the 'extra' pointer, thus I can't have the stream internally reference the filedata which would be useful to pass to a dedicated loader thread.

Premise: I do not want to add a wildmidi loader to Allegro due to:
- Wildmidi being LGPL and thus not very welcome into allegro dependency.
- being a softsynth, it depends on GUS compatible patches and an external cfg file...and as such not 'self contained' enough for this task (IMO).

So I'd like to do that "externally", but I do WANT to be able to al_register_audio_stream_loader my loading functions (just like my load_sample functions)

This forces me on (as far as I can tell right now) two possible paths:

  • explicitly pass around the wildmidi file data structure in my stream manager; problem: I drop the possibility to register my loader into Allegro interface (since it then has incompatible signature).


  • create a static container which holds the information for all the open streams and can thus be accessed both from the loader and the feeder thread; problem: an unwanted layer of management and check for data races and so on....

I was looking for some advice on which of these should be my choice...which can very well be 'neither of the two' ;D

...and maybe (!) a dev word about adding an API like al_set/get_audio_stream_userdata(ALLEGRO_AUDIO_STREAM* stream, void* extra) to the Allegro_Audio addon.

The latter seems to me that could be an easy addition and should cause no harm.

My very weakness here is that I do not know squat about proper threading and I'm sure I might be missing something obvious.

Thanks for any feedback.

SiegeLord

That seems like a reasonable addition. Without thinking too much of it, it might be nice to also specify a destructor alongside this pointer?

There is another, sort of related, thing I just want to put out there. One weakness of the current audio addon is that it conflates two meanings of the word 'stream'. The first, is streaming from a file: i.e. on-demand loading/generating audio. The second, is slowly feeding audio data to a mixer. The second is in principle supported, but the first is part of the internal API (every implementation of a file-backed audio stream has an implementation of reading from a file on demand). It'd be nice to make it user-accessible.

pkrcel

I didn't think about a destructor, which could come in handy after all when destroying the stream.

One question arises thou: internally the struct has a member void *extra, which is currently used and I assumed that IF allocated (i.e. != NULL ) would have al_free called on it upon destruction.

Were I wrong assuming it?

Right now I've added the two functions but I am merely adding the 'extra' as a pointer to a WM_FILE_DATA struct that very much resembles WAVFILE, FLACFILE, etc...so a dtor is not strictly needed. I'll try to experiment a bit, if you like I can make a PR to have the code availble for review, though it's DEAD SIMPLE.

About your observation, I tend to agree that exposing the common interface for on-demand load could be useful, along with being able to register new handlers just like the loader....but I admit I haben't yet tooled around with the addon enough to have a well-informed opinion; gut feeling is that's a sensible proposal.

EDIT: I just realized that I can't access also the stream mutex with the API...damn...

How should I go then for a proper feeder thread?

BUMP

SiegeLord said:

Without thinking too much of it, it might be nice to also specify a destructor alongside this pointer?

I've dabbled a bit with the two functions, could you please explain me how should I handle the destructor passign along and such?

Is there something like _al_register_destructor internal function? (I ask cause none is documented).

BUMP 2

I've succeeded into expanding the API with:

al_get_audio_stream_userdata
al_set_audio_stream_userdata
al_get_audio_stream_mutex

and implemented a WildMidi loader which can be registered into Allegro interface and auto-feeds the stream.

It can be found here for peer-review, even thou I fear I'll be an embarrassment to myself :P

Anyway I ran into some problems, that persist and that shed some light on what Siegelord wrote above (I didn't understand fully at the time, I guess).

The stream internal are quite elaborated and passing a userdata pointer to manage the extras seems inefficient and incomplete.

For example, I correctly register my functions into Allegro interface through al_load_audio_stream and it starts the auto-feed thread, BUT I don't have means to signal the thread itself to stop if I call al_destroy_audio_stream

In the test executable it's not a problem but I know this is unacceptable, I will have to find a way to register an *extra destructor that handles the signal for me (by the way, if anybody could suggest HOW, as I asked above, I'd appreciate ;D).

Seems a waste, since al_destroy_audio_stream ALREADY does that for the internals.

I think that the stream API might benefit from a larger exposition of the stream's structure, at least for the feed thread and such.

Thread #614984. Printed from Allegro.cc