Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » switching stream files

This thread is locked; no one can reply to it. rss feed Print
switching stream files
ph03nix
Member #15,028
April 2013
avatar

This is probably straight forward, but no matter what I do I get crashes.

What I'm doing is stream audio using al_load_audio_stream_f, and I want to be able to switch the file it plays from, replacing the current one.

Here's what I tried. It causes the program to crash if I change to a file that was already playing:

ALLEGRO_STREAM *stream = NULL; //defined elsewhere

void streamAudio(ALLEGRO_FILE *file){
   if(stream){
      al_detach_audio_stream(stream);
   }
   stream = al_load_audio_stream_f(file, ".ogg", 2, 1024);
   al_set_audio_stream_playmode(stream,ALLEGRO_PLAYMODE_LOOP);
   al_attach_audio_stream_to_mixer(stream, mixer);
}

I feel like not calling al_destroy_audio_stream would cause a memory leak, but calling it causes a crash when I exit. What am I doing wrong? ???

beoran
Member #12,636
March 2011

Maybe al_load_audio_stream_f returns NULL? You could check that, as well as mixer. And yes, you are leaking memory too. Make your program corect and then try to find out where the crashes are coming from.

Asa nd isede, it it hard to drun the game in a debuggger? On Linux, I run my programs with the gdb debugger or valgrind the memory checker and I can often pinpoint the problem easily. Most difficult to find remains memory corruption where valid data is overwitten by a pointer or a stack problem somewhere else.

ph03nix
Member #15,028
April 2013
avatar

I've looked into it, and it seems that al_load_audio_stream_f closes the memfile. Can this be prevented?

EDIT: That was the problem. I changed my system to accommodate for the closing of the memfile after al_load_audio_stream_f is called. I don't think this behaviour is in the manual, maybe it should be added.

EDIT 2: Is it possible that al_load_audio_stream_f causes a memory leak since you can't call al_fclose on the same file after its called? Or does it close the memfile?

Thomas Fjellstrom
Member #476
June 2000
avatar

Yeah, I don't think its desired behavior for _f functions to close the file. I'd call that a bug.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Trent Gamblin
Member #261
April 2000
avatar

It depends. If it needs to hold onto the file, it has no choice. I think that's the case here. It's the same with load_ttf_f. TTFs have to be kept open and so do streams, otherwise you might as well load them into memory.

Thomas Fjellstrom
Member #476
June 2000
avatar

Why would it need to close the file handle you handed to it? The main purpose behind the _f functions is that you already have a handle open, and in some/many cases, its multiple actual files in a single file, so you're going to need to have that handle stay open across calls to _f functions.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Trent Gamblin
Member #261
April 2000
avatar

Think about this for a second. The main reason for the _f functions is mainly that you can use your own file access routines so you can have a file embedded in a whatever and Allegro can still use it. When you pass a file handle to a load_stream function, it has to keep that file open, seek around in it. When it's done, you may not know about it. So it makes the most sense for it to keep it itself. If you need another one, then open it again. Not all of the _f functions work like this, just the ones that need to. EDIT: And it's documented in the manual for at least some of them.

Thomas Fjellstrom
Member #476
June 2000
avatar

I dunno, I still don't think it should "own" your handle. You should know when you stop playing your own files. But, if there's no other way, I suppose the only solution is to always hand them file slices.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

beoran
Member #12,636
March 2011

Just throwing out an idea , but if it is the case hat it closes the file behind your back, a callback function or something similar would be useful to notify the rest of the program.

Anyway, the documentation needs to be updated for al_load_audio_stream_f so it's ore clear what is going on.

ph03nix
Member #15,028
April 2013
avatar

Does it have to close a memfile? After all the data is in the memory.
Also, this is what I do now. Could this cause a memory leak?

#SelectExpand
1//these are defined elsewhere 2ALLEGRO_FILE *file = NULL; 3ALLEGRO_AUDIO_STREAM *stream = NULL; 4 5//following code called when starting a stream 6if(stream){ 7 al_destroy_audio_stream(stream); 8} 9//this sets file to al_open_memfile 10openMemFile(); 11//I assume this calls al_fclose on file 12stream = al_load_audio_stream_f(file, ".ogg", 2, 1024); 13//file is now a bad pointer? 14file = NULL; 15al_set_audio_stream_playmode(stream,ALLEGRO_PLAYMODE_LOOP); 16al_attach_audio_stream_to_mixer(stream, mixer);

beoran
Member #12,636
March 2011

Well from this, it seems you have to close the memfile manually when you are done with it. Probably allegro allocates it's own memory amlso for the memfile struct that also needs to be freed. ou need to free the memory you alocated yourself, normally...

https://www.allegro.cc/manual/5/al_open_memfile

Thomas Fjellstrom
Member #476
June 2000
avatar

To allegro functions, a memfile isn't special. It treats them the same as a "normal" file. If a _f function is going to call al_close_file() on one, it'll call it on the other.

So at the very least the ALLEGRO_FILE gets freed, but you'll want to free up the memory you allocated for the memfile to use.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

ph03nix
Member #15,028
April 2013
avatar

Sorry, I forgot to mention that the memory the file is pointing to is defined in a header so it can't be freed. The memory leak I was concerned about is the lack of al_fclose

beoran
Member #12,636
March 2011

I looked in the memfile.c sources, and yes, you WILL leak a whole ALLEGRO_FILE_MEMFILE struct that gets al_malloc() ed on opening the file. So you should really call al_fclose at the right time. Why not keep the file pointer around? You don't need to free your own buffer itf it's statical, and memfile won't free your buffer either, but you have to free the memory that gets allocated for the ALLEGRO_FILE_MEMFILE itself.

ph03nix
Member #15,028
April 2013
avatar

I'm not sure that's the case. Because the pointer to the ALLEGRO_FILE becomes bad after calling al_load_audio_stream_f, that means al_load_audio_stream_f must call al_fclose at some point, right?

beoran
Member #12,636
March 2011

I checked the sources (in the GIT version of Allegro) of the acodec and audio plugins more, and from what I see

1) al_load_audio_stream DOES call al_flcose on the file it opens itself.
2) However, al_load_audio_stream_f does NOT call al_flcose on the file you pass to it.
3) However however, al_destroy_audio_stream should close that file for you, since it calls al_fclose.

So I'd think that you have to call al_close_audio_stream on the stream pointer, and then the file will also be deallocated. I don't know what will happen with the memfile's own buffer, though, but I suppose it will be unaffected.

ph03nix
Member #15,028
April 2013
avatar

after calling al_load_audio_stream_f, the file pointer becomes bad, meaning its pointing to free memory (which means al_load_audio_stream_f must have freed it). al_destroy_audio_sample does not close the file or else the program would crash.

beoran
Member #12,636
March 2011

Hmmm, and are you using the same version of Allegro or an older one? I don't know how what you describe could happen from the source code I saw.

Go to: