diff --git a/src/i_sound.h b/src/i_sound.h index 2c4b35e4b..f6e9a18af 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -233,17 +233,11 @@ boolean I_SetSongTrack(INT32 track); /// ------------------------ void I_SetInternalMusicVolume(UINT8 volume); - void I_StopFadingSong(void); - -boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, boolean stopafterfade); - -boolean I_FadeSong(UINT8 target_volume, UINT32 ms); - +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeOutStopSong(UINT32 ms); - -boolean I_FadeInStartDigSong(const char *musicname, UINT16 track, boolean looping, UINT32 position, UINT32 fadeinms, boolean queuepostfade); -#define I_QueueDigSong(a,b,c,d,e) I_FadeInStartDigSong(a,b,c,d,e,1) +boolean I_FadeInPlaySong(UINT32 ms, boolean looping); /// ------------------------ // CD MUSIC I/O diff --git a/src/s_sound.c b/src/s_sound.c index def345b5e..0eec36398 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1354,6 +1354,12 @@ static char music_name[7]; // up to 6-character name static UINT16 music_flags; static boolean music_looping; +static char queue_name[7]; +static UINT16 queue_flags; +static boolean queue_looping; +static UINT32 queue_position; +static UINT32 queue_fadeinms; + /// ------------------------ /// Music Status /// ------------------------ @@ -1500,118 +1506,108 @@ static void S_UnloadMusic(void) music_looping = false; } -static boolean S_PlayMusic(boolean looping) +static boolean S_PlayMusic(boolean looping, UINT32 fadeinms) { if (S_MusicDisabled()) return false; - if (!I_PlaySong(looping)) + if ((!fadeinms && !I_PlaySong(looping)) || + (fadeinms && !I_FadeInPlaySong(fadeinms, looping))) { S_UnloadMusic(); return false; } + S_InitMusicVolume(); // switch between digi and sequence volume return true; } +static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 fadeinms) +{ + strncpy(queue_name, mmusic, 7); + queue_flags = mflags; + queue_looping = looping; + queue_position = position; + queue_fadeinms = fadeinms; +} + +static void S_ClearQueue(void) +{ + queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0; +} + +static void S_ChangeMusicToQueue(void) +{ + S_ChangeMusicAdvanced(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms); + S_ClearQueue(); +} + void S_ChangeMusicAdvanced(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms) { if (S_MusicDisabled()) return; char newmusic[7]; - boolean digiexists = S_DigExists(mmusic); - boolean midiexists = S_MIDIExists(mmusic); #if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS) - if(LUAh_MusicChange(music_name, mmusic, newmusic, &mflags, &looping)) + if(LUAh_MusicChange(music_name, mmusic, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) return; #else strncpy(newmusic, mmusic, 7); #endif + newmusic[6] = 0; + int i; + for (i = 0; newmusic[i]; i++) { + newmusic[i] = tolower(newmusic[i]); + } // No Music (empty string) if (newmusic[0] == 0) { - S_StopMusic(); + if (prefadems) + I_FadeSong(0, prefadems, &S_StopMusic); + else + S_StopMusic(); return; } - CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic); - - if (digiexists && !digital_disabled) // digmusic? + if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same { - if (prefadems && I_SongType() != MU_MID) //have to queue post-fade // allow even if the music is the same - { - I_FadeOutStopSong(prefadems); - I_QueueDigSong(newmusic, mflags & MUSIC_TRACKMASK, looping, position, fadeinms); - - // HACK: set the vars now and hope everything works out - strncpy(music_name, newmusic, 7); - music_name[6] = 0; - music_lumpnum = LUMPERROR; - music_data = NULL; - music_handle = 0; - return; - } - else if (strncmp(music_name, newmusic, 6)) - { - S_StopMusic(); - if (position || fadeinms) - { - if(!I_FadeInStartDigSong(newmusic, mflags & MUSIC_TRACKMASK, looping, position, fadeinms, false)) - { - CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic); - return; - } - else - { - strncpy(music_name, newmusic, 7); - music_name[6] = 0; - music_lumpnum = LUMPERROR; - music_data = NULL; - music_handle = 0; - return; - } - } - else if (!S_DigMusic(newmusic, looping)) - { - CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic); - return; - } - else - I_SetSongTrack(mflags & MUSIC_TRACKMASK); - } + CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name); + S_QueueMusic(newmusic, mflags, looping, position, fadeinms); + I_FadeSong(0, prefadems, S_ChangeMusicToQueue); + return; } - else if (strncmp(music_name, newmusic, 6) && midiexists && !midi_disabled) // midimusic? + else if (strncmp(music_name, newmusic, 6)) { - // HACK: We don't support fade for MIDI right now, so - // just fall to old behavior verbatim. This technically should be implemented in - // the interfaces, even as a stub. + CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic); - S_StopMusic(); // shutdown old music + S_StopMusic(); - if (!S_LoadMusic(mmusic)) + if (!S_LoadMusic(newmusic)) return; music_flags = mflags; music_looping = looping; - if (!S_PlayMusic(looping)) + if (!S_PlayMusic(looping, fadeinms)) { CONS_Alert(CONS_ERROR, "Music cannot be played!\n"); return; } - } - else if (!midiexists && !digiexists) - CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), newmusic); -} -musictype_t S_MusicType() -{ - return I_SongType(); + if (position) + I_SetSongPosition(position); + + I_SetSongTrack(mflags & MUSIC_TRACKMASK); + } + else if (fadeinms) // let fades happen with same music + { + I_SetSongPosition(position); + I_FadeSong(100, fadeinms, NULL); + } } void S_StopMusic(void) @@ -1713,14 +1709,14 @@ void S_StopFadingMusic(void) boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms) { if (source_volume < 0) - return I_FadeSong(target_volume, ms); + return I_FadeSong(target_volume, ms, NULL); else return I_FadeSongFromVolume(target_volume, source_volume, ms, false); } boolean S_FadeOutStopMusic(UINT32 ms) { - return I_FadeOutStopSong(ms); + return I_FadeSong(0, ms, &S_StopMusic); } /// ------------------------ diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index c03a8c62c..eca7c7b71 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -76,20 +76,27 @@ static UINT8 fading_target; static UINT32 fading_steps; static INT16 fading_volume_step; static INT32 fading_id; - -// queue -static char queue_music_name[7]; // up to 6-character name -static UINT16 queue_track; -static boolean queue_looping; -static UINT32 queue_position; -static UINT32 queue_fadeinms; -static boolean queue_stopafterfade; +static void (*fading_callback)(void); #ifdef HAVE_LIBGME static Music_Emu *gme; static INT32 current_track; #endif +static void var_cleanup(void) +{ + loop_point = song_length =\ + music_bytes = fading_target =\ + fading_steps = fading_volume_step = 0; + + songpaused = is_looping =\ + is_fading = false; + + fading_callback = NULL; + + internal_volume = 100; +} + /// ------------------------ /// Audio System /// ------------------------ @@ -109,7 +116,6 @@ void I_StartupSound(void) } var_cleanup(); - queue_cleanup(); music = NULL; music_volume = sfx_volume = 0; @@ -465,31 +471,18 @@ void I_SetSfxVolume(UINT8 volume) /// Music Utilities /// ------------------------ -static void var_cleanup(void) -{ - loop_point = song_length =\ - music_bytes = fading_target =\ - fading_steps = fading_volume_step = 0; - - songpaused = is_looping =\ - is_fading = false; - - internal_volume = 100; -} - -static void queue_cleanup(void) -{ - queue_track = queue_looping =\ - queue_position = queue_fadeinms =\ - queue_stopafterfade = 0; - queue_music_name[0] = 0; -} - static UINT32 get_real_volume(UINT8 volume) { - // convert volume to mixer's 128 scale - // then apply internal_volume as a percentage - return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100; +#ifdef _WIN32 + if (I_SongType() == MU_MID) + // HACK: Until we stop using native MIDI, + // disable volume changes + return ((UINT32)31*128/31); // volume = 31 + else +#endif + // convert volume to mixer's 128 scale + // then apply internal_volume as a percentage + return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100; } static UINT32 get_adjusted_position(UINT32 position) @@ -503,24 +496,11 @@ static UINT32 get_adjusted_position(UINT32 position) return position; } -static void run_queue() +static void do_fading_callback() { - if (queue_stopafterfade) - I_StopSong(); - else if (queue_music_name[0]) - { - I_StopSong(); - - if (I_StartDigSong(queue_music_name, queue_looping)) - { - I_SetSongTrack(queue_track); - if (queue_fadeinms) - I_FadeSongFromVolume(100, 0, queue_fadeinms, false); - if (queue_position) - I_SetSongPosition(queue_position); - } - } - queue_cleanup(); + if (fading_callback) + (*fading_callback)(); + fading_callback = NULL; } /// ------------------------ @@ -540,9 +520,7 @@ static void count_music_bytes(int chan, void *stream, int len, void *udata) static void music_loop(void) { - if (queue_music_name[0] && !is_fading && !is_looping) - run_queue(); - else if (is_looping) + if (is_looping) { Mix_PlayMusic(music, 0); Mix_SetMusicPosition(loop_point); @@ -555,13 +533,12 @@ static void music_loop(void) static UINT32 music_fade(UINT32 interval, void *param) { if (!is_fading || - I_SongType() == MU_MID || // stub out MIDI, see bug in I_SetMIDIMusicVolume internal_volume == fading_target || fading_steps == 0 || fading_volume_step == 0) { I_StopFadingSong(); - queue_cleanup(); + do_fading_callback(); return 0; } else if ( @@ -570,7 +547,8 @@ static UINT32 music_fade(UINT32 interval, void *param) { internal_volume = fading_target; Mix_VolumeMusic(get_real_volume(music_volume)); - run_queue(); + I_StopFadingSong(); + do_fading_callback(); return 0; } else @@ -628,7 +606,6 @@ void I_ShutdownMusic(void) if (!music) return; var_cleanup(); - queue_cleanup(); SDL_RemoveTimer(fading_id); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_HookMusicFinished(NULL); @@ -862,7 +839,7 @@ UINT32 I_GetSongPosition(void) if (info->length > 0) position %= info->length; else if (info->intro_length + info->loop_length > 0) - position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position + position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position; else position %= 150 * 1000; // 2.5 minutes } @@ -985,7 +962,6 @@ boolean I_LoadSong(char *data, size_t len) { gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; gme_set_equalizer(gme, &eq); - Mix_HookMusic(mix_gme, gme); return true; } #endif @@ -1120,19 +1096,21 @@ void I_UnloadSong(void) boolean I_PlaySong(boolean looping) { - if (!music) - return false; -#ifdef HAVE_GME +#ifdef HAVE_LIBGME if (gme) { gme_start_track(gme, 0); current_track = 0; + Mix_HookMusic(mix_gme, gme); return true; } + else #endif + if (!music) + return false; if (!song_length && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) - CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly."); + CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n"); if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1) { @@ -1179,10 +1157,8 @@ void I_StopSong(void) music = NULL; } -void I_PauseSong(INT32 handle) +void I_PauseSong() { - (void)handle; - if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? return; @@ -1197,10 +1173,8 @@ void I_PauseSong(INT32 handle) songpaused = true; } -void I_ResumeSong(INT32 handle) +void I_ResumeSong() { - (void)handle; - if (I_SongType() == MU_MID) return; @@ -1213,7 +1187,7 @@ void I_ResumeSong(INT32 handle) while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } // HACK: fixes issue of multiple effect callbacks being registered - if(music && I_GetSongType() != MU_MOD && I_GetSongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); } @@ -1235,7 +1209,7 @@ void I_SetMusicVolume(UINT8 volume) #endif music_volume = volume; - Mix_VolumeMusic((UINT32)music_volume*128/31); + Mix_VolumeMusic(get_real_volume(music_volume)); } boolean I_SetSongTrack(int track) @@ -1279,7 +1253,7 @@ boolean I_SetSongTrack(int track) void I_SetInternalMusicVolume(UINT8 volume) { internal_volume = volume; - if (!music || I_SongType() == MU_MID) // stub out MIDI, see bug in I_SetMIDIMusicVolume + if (!music) return; Mix_VolumeMusic(get_real_volume(music_volume)); } @@ -1292,7 +1266,7 @@ void I_StopFadingSong(void) fading_target = fading_steps = fading_volume_step = fading_id = 0; } -boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, boolean stopafterfade) +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) { UINT32 target_steps, ms_per_step; INT16 target_volume_step, volume_delta; @@ -1304,21 +1278,16 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms if (!ms && volume_delta) { - if (stopafterfade) - { - I_StopSong(); - return true; - } - else - { - I_SetInternalMusicVolume(target_volume); - return true; - } + I_SetInternalMusicVolume(target_volume); + if (callback) + (*callback)(); + return true; + } - else if (!volume_delta || I_SongType() == MU_MID) + else if (!volume_delta) { - if (stopafterfade) - I_StopSong(); + if (callback) + (*callback)(); return true; } @@ -1344,7 +1313,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms fading_target = target_volume; fading_steps = target_steps; fading_volume_step = target_volume_step; - queue_stopafterfade = stopafterfade; + fading_callback = callback; if (internal_volume != source_volume) I_SetInternalMusicVolume(source_volume); @@ -1354,47 +1323,21 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms return is_fading; } -boolean I_FadeSong(UINT8 target_volume, UINT32 ms) +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { - return I_FadeSongFromVolume(target_volume, internal_volume, ms, false); + return I_FadeSongFromVolume(target_volume, internal_volume, ms, callback); } boolean I_FadeOutStopSong(UINT32 ms) { - return I_FadeSongFromVolume(0, internal_volume, ms, true); + return I_FadeSongFromVolume(0, internal_volume, ms, &I_StopSong); } -boolean I_FadeInStartDigSong(const char *musicname, UINT16 track, boolean looping, UINT32 position, UINT32 fadeinms, boolean queuepostfade) +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) { - if (musicname[0] == 0) - return true; // nothing to play - else if (queuepostfade && is_fading && I_SongType() != MU_MID) - { - strncpy(queue_music_name, musicname, 7); - queue_music_name[6] = 0; - queue_track = track; - queue_looping = looping; - queue_position = position; - queue_fadeinms = fadeinms; - queue_stopafterfade = false; - - return true; - } + if (I_PlaySong(looping)) + return I_FadeSongFromVolume(100, 0, ms, NULL); else - { - if (I_StartDigSong(musicname, looping)) - { - I_SetSongTrack(track); - if (fadeinms) - I_FadeSongFromVolume(100, 0, fadeinms, false); - if (position) - I_SetSongPosition(position); - return true; - } - else - return false; - } - + return false; } - #endif