SDL-Mixer-X icon indicating copy to clipboard operation
SDL-Mixer-X copied to clipboard

music->interface->GetAudio null dereference exception

Open mbpictures opened this issue 1 year ago • 7 comments

Hi!

First of all, thanks for this awesome project! When I try to play several multi-track songs after each other (like in a playlist), I'm getting a dereference exception in this line.

Do you know what causes this issue? I'm using this to load all the music as streams:

void multitrackplayer::loadFiles(std::vector<std::string> paths)
{
    multitrackplayer::stop();
    for (auto path : paths)
    {
        auto musicMix = Mix_LoadMUS(path.c_str());
        if (musicMix == NULL) {
        } else {
            _musicTracks.push_back(musicMix);
            _duration = std::max(_duration, Mix_MusicDuration(musicMix));
        }
    }
    _started = false;
}

void multitrackplayer::play()
{
    if (_musicTracks.size() == 0) {
        return;
    }
    for (auto music : _musicTracks)
    {
        if (_started) {
            Mix_ResumeMusicStream(music);
        } else {
            int result = Mix_PlayMusicStream(music, 0);
        }
        Mix_SetFreeOnStop(music, 0); // don't free the music automatically
    }
    _started = true;
    return void();
}

void multitrackplayer::stop()
{
    if (_musicTracks.size() == 0) {
        return void();
    }
    for (auto music : _musicTracks)
    {
        Mix_FreeMusic(music);
        music = NULL;
    }
    _musicTracks.clear();
    return void();
}

So I first free the music, when there is something currently playing, then load the new files and play them.

mbpictures avatar May 07 '24 20:05 mbpictures

Hi, this looks like an interesting use case! I see one problem here, in multitrackplayer::stop(). It is illegal to call Mix_FreeMusic(music) if music is currently playing. The null dereference is occurring when the internal mixer logic tries to keep playing a music stream that has been freed.

To fix this, you can add Mix_HaltMusicStream(music) prior to Mix_FreeMusic(music).

ds-sloth avatar May 07 '24 22:05 ds-sloth

Thanks for your answer, I will try this soon! However, if it actually fixes the issue, than the docs should be updated, as this is the current description of the Mix_FreeMusic function:

Free the loaded music. If music is playing it will be halted. If music is fading out, then this function will wait (blocking) until the fade out is complete.

mbpictures avatar May 08 '24 08:05 mbpictures

That's a good point; I wasn't aware of that part of the specification and have never personally relied on this behavior. It's good for the library to try its best to prevent problems, though, so it'll be good for us to try to meet the specification.

@Wohlstand, maybe the issue is that Mix_FreeMusic doesn't call _Mix_MultiMusic_Remove prior to calling music_internal_halt here (https://github.com/WohlSoft/SDL-Mixer-X/blob/master/src/music.c#L2069)?

ds-sloth avatar May 08 '24 14:05 ds-sloth

I'll try to check this.

Wohlstand avatar May 08 '24 14:05 Wohlstand

Maybe call Mix_HaltMusicStream in the beginning of the Mix_FreeMusic? Code currently looks like, that the music halted callback isn't called as well, when calling FreeMusic?

mbpictures avatar May 08 '24 22:05 mbpictures

Maybe call Mix_HaltMusicStream in the beginning of the Mix_FreeMusic? Code currently looks like, that the music halted callback isn't called as well, when calling FreeMusic?

There are already its parts called like music_internal_halt(). Anyway, I going to apply the fix now. Sorry for the delay, I was very busy.

Wohlstand avatar May 18 '24 11:05 Wohlstand

Done, I also added calling of individual music finish hooks in a case if they are presented. Please test out the thing and tell does this fixes your issue or not?

Wohlstand avatar May 18 '24 11:05 Wohlstand

@mbpictures, ping?

Wohlstand avatar Aug 05 '24 14:08 Wohlstand

Closed because of no reply for a long time when problem had been fixed a while ago.

Wohlstand avatar Sep 30 '24 14:09 Wohlstand