SDL_mixer: loop support in mod file is broken

Hi list,

When playing a mod file using Mix_PlayMusic, the loops of the mod file
are ignored, resulting in the music being played incorrectly.

This has been discussed in this forum entry (there is a workaround provided):
http://forums.libsdl.org/viewtopic.php?t=7160

This is due to the ‘Jump to order’ command being ignored while the
file is being played.
http://www.milkytracker.org/docs/MilkyTracker.html#fxBxx

In my particular case, my game uses a mod file containing multiple music loops.
Music loops are switched dynamically by the game using
Mix_SetMusicPosition(position), which has the particular behaviour of
setting the pattern being played in the case of a mod file.
Having SDL_mixer ignoring the ‘Jump’ commands totally breaks the
playback of the music in my case.

The reason for mod playback not supporting loops is that this has been
explicitely disabled in the MOD_new_RW() function of the music_mod.c
file, with the line:
module->loop = 0; (see source code below)

Is there any reason for this? I cannot imagine why anyone would have
loop commands in mod files ignored by default.
(I didn’t notice this problem earlier, because before ubuntu 12.04,
the binary SDL packages provided with ubuntu didn’t exhibit this
behaviour… Maybe someone had patched it downstream?)

Thanks,
Florent

/* Load a MOD stream from an SDL_RWops object */
MODULE *MOD_new_RW(SDL_RWops *rw, int freerw)
{
MODULE *module;

/* Make sure the mikmod library is loaded */
if ( !Mix_Init(MIX_INIT_MOD) ) {
	if ( freerw ) {
		SDL_RWclose(rw);
	}
	return NULL;
}

module = MikMod_LoadSongRW(rw,64);
if (!module) {
	Mix_SetError("%s", mikmod.MikMod_strerror(*mikmod.MikMod_errno));
	if ( freerw ) {
		SDL_RWclose(rw);
	}
	return NULL;
}

/* Stop implicit looping, fade out and other flags. */
module->extspd  = 1;
module->panflag = 1;
module->wrap    = 0;
module->loop    = 0;

#if 0 /* Don’t set fade out by default - unfortunately there’s no real way
to query the status of the song or set trigger actions. Hum. */
module->fadeout = 1;
#endif

if ( freerw ) {
	SDL_RWclose(rw);
}
return module;

}

Hi,

I may only be like the third person who actually needs this, but to this day, it’s still been left broken.
All the tricks like overriding the ModPlugSettings from the application didn’t work for me.

I’m not super familiar with how SDL_mixer does its stuff, so this is just guesswork:
MODPLUG_GetSome treats a fully read module file as finished playback, ignoring any possibilities of loop commands being handled internally.
Looping also explicitly disabled in the ModPlugSettings for some reason.

Overriding ModPlugSettings didn’t work for me either. Nor did changing the settings internally and re-compiling as per these instructions.

This looping behaviour is the whole point of MOD files, they were pretty much invented for video games. You have the intro of the song, then the main part of the song, and then it loops back to a neat loop point in the song some time after the intro.

Ignoring the looping by default is only useful for media player type software, and that’s it. It completely breaks their intended functionality for games. A function to enable/disable it would be best…