diff --git a/bin/windows/zmusic/include/zmusic.h b/bin/windows/zmusic/include/zmusic.h index 7422b58da2..90cb80e25c 100644 --- a/bin/windows/zmusic/include/zmusic.h +++ b/bin/windows/zmusic/include/zmusic.h @@ -151,6 +151,7 @@ typedef enum EIntConfigKey_ zmusic_snd_mididevice, zmusic_snd_outputrate, + zmusic_mod_preferredplayer, NUM_ZMUSIC_INT_CONFIGS } EIntConfigKey; diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 01b3a5da34..9664c54585 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -74,6 +74,7 @@ float relative_volume = 1.f; float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function MusicVolumeMap MusicVolumes; MidiDeviceMap MidiDevices; +TMap ModPlayers; static int DefaultFindMusic(const char* fn) { @@ -93,6 +94,7 @@ EXTERN_CVAR(Float, fluid_gain) CVAR(Bool, mus_calcgain, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song. CVAR(Bool, mus_usereplaygain, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song. +CVAR(Int, mod_preferred_player, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)// toggle between libXMP and Dumb. Unlike other sound CVARs this is not directly mapped to ZMusic's config. // CODE -------------------------------------------------------------------- @@ -769,6 +771,7 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) { int lumpnum = mus_cb.FindMusic(musicname); MidiDeviceSetting* devp = MidiDevices.CheckKey(lumpnum); + int* mplay = ModPlayers.CheckKey(lumpnum); auto volp = MusicVolumes.CheckKey(lumpnum); if (volp) @@ -781,6 +784,12 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); } auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper. + int mod_player = mplay? *mplay : *mod_preferred_player; + int scratch; + + // This config var is only effective when opening a music stream so there's no need for active synchronization. Setting it here is sufficient. + // Ideally this should have been a parameter to ZMusic_OpenSong, but that would have necessitated an API break. + ChangeMusicSettingInt(zmusic_mod_preferredplayer, mus_playing.handle, mod_player, &scratch); mus_playing.handle = ZMusic_OpenSong(mreader, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : ""); if (mus_playing.handle == nullptr) { diff --git a/src/common/audio/music/s_music.h b/src/common/audio/music/s_music.h index 629f6f95d4..3c5a092ccb 100644 --- a/src/common/audio/music/s_music.h +++ b/src/common/audio/music/s_music.h @@ -74,6 +74,7 @@ struct MidiDeviceSetting typedef TMap MidiDeviceMap; typedef TMap MusicVolumeMap; +extern TMap ModPlayers; extern MidiDeviceMap MidiDevices; extern MusicVolumeMap MusicVolumes; extern MusicCallbacks mus_cb; diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index f48e6855e4..8717c4b9eb 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -147,6 +147,7 @@ enum SICommands SI_EDFOverride, SI_Attenuation, SI_PitchSet, + SI_ModPlayer, }; // Blood was a cool game. If Monolith ever releases the source for it, @@ -236,7 +237,8 @@ static const char *SICommandStrings[] = "$edfoverride", "$attenuation", "$pitchset", - NULL + "$modplayer", + nullptr }; static TArray SavedPlayerSounds; @@ -571,6 +573,7 @@ void S_ClearSoundData() MusicAliases.Clear(); MidiDevices.Clear(); HexenMusic.Clear(); + ModPlayers.Clear(); } //========================================================================== @@ -1109,10 +1112,24 @@ static void S_AddSNDINFO (int lump) sc.RestorePos(save); sc.MustGetString(); } - if (lumpnum >= 0) MidiDevices[lumpnum] = devset; + if (lumpnum >= 0) MidiDevices.Insert(lumpnum, devset); } break; + case SI_ModPlayer: { + sc.MustGetString(); + int lumpnum = mus_cb.FindMusic(sc.String); + int player; + FScanner::SavedPos save = sc.SavePos(); + + sc.MustGetString(); + if (sc.Compare("XMP") || sc.Compare("libXMP")) player = 0; + else if (sc.Compare("dumb") || sc.Compare("libdumb")) player = 1; + else sc.ScriptError("Unknown Module player %s\n", sc.String); + if (lumpnum >= 0) ModPlayers.Insert(lumpnum, player); + } + break; + case SI_IfDoom: //also Chex case SI_IfStrife: case SI_IfHeretic: