diff --git a/CMakeLists.txt b/CMakeLists.txt index d4c989d12..676d32fe7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,7 +269,6 @@ set(pathfinder_SRCS source_group(pathfinder FILES ${pathfinder_SRCS}) set(sound_SRCS - src/sound/music.cpp src/sound/script_sound.cpp src/sound/sound.cpp src/sound/sound_id.cpp diff --git a/src/include/sound_server.h b/src/include/sound_server.h index 0aab5e7f8..1978784be 100644 --- a/src/include/sound_server.h +++ b/src/include/sound_server.h @@ -68,7 +68,7 @@ extern bool UnitSoundIsPlaying(Origin *origin); /// Check, if this sample is already playing extern bool SampleIsPlaying(Mix_Chunk *sample); /// Load music -extern Mix_Music *LoadMusic(const std::string &name); +extern Mix_Chunk *LoadMusic(const std::string &name); /// Load a sample extern Mix_Chunk *LoadSample(const std::string &name); /// Play a sample @@ -85,10 +85,8 @@ extern void SetEffectsEnabled(bool enabled); /// Check if effects are enabled extern bool IsEffectsEnabled(); -/// Set the music finished callback -void SetMusicFinishedCallback(void (*callback)()); /// Play a music file -extern int PlayMusic(Mix_Music *sample); +extern int PlayMusic(Mix_Chunk *sample); /// Play a music file extern int PlayMusic(const std::string &file); /// Stop music playing diff --git a/src/sound/music.cpp b/src/sound/music.cpp deleted file mode 100644 index 95753bec2..000000000 --- a/src/sound/music.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// _________ __ __ -// / _____// |_____________ _/ |______ ____ __ __ ______ -// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/ -// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ | -// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ > -// \/ \/ \//_____/ \/ -// ______________________ ______________________ -// T H E W A R B E G I N S -// Stratagus - A free fantasy real time strategy game engine -// -/**@name music.cpp - Background music support */ -// -// (c) Copyright 2002-2006 by Lutz Sammer, Nehal Mistry, and Jimmy Salmon -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; only version 2 of the License. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -// 02111-1307, USA. -// - -//@{ - -/*---------------------------------------------------------------------------- --- Includes -----------------------------------------------------------------------------*/ - -#include "stratagus.h" - - -#include "SDL.h" - -#include "sound_server.h" -#include "script.h" - -/*---------------------------------------------------------------------------- --- Declaration -----------------------------------------------------------------------------*/ - -#define SoundFrequency 44100 // sample rate of dsp - -/*---------------------------------------------------------------------------- --- Variables -----------------------------------------------------------------------------*/ - -volatile bool MusicFinished; /// Music ended and we need a new file - -bool CallbackMusic; /// flag true callback ccl if stops - -/*---------------------------------------------------------------------------- --- Functions -----------------------------------------------------------------------------*/ - -/** -** Callback for when music has finished -** Note: we are in the sdl audio thread -*/ -static void MusicFinishedCallback() -{ - MusicFinished = true; -} - -/** -** Check if music is finished and play the next song -*/ -void CheckMusicFinished(bool force) -{ - // this races, but that's just fine, since we'll just miss a frame of we're unlucky - bool proceed = MusicFinished; - if (!(((proceed || force) && SoundEnabled() && IsMusicEnabled() && CallbackMusic))) { - return; - } - lua_getglobal(Lua, "MusicStopped"); - if (!lua_isfunction(Lua, -1)) { - fprintf(stderr, "No MusicStopped function in Lua\n"); - } else { - LuaCall(0, 1); - } - MusicFinished = false; -} - -/** -** Init music -*/ -void InitMusic() -{ - MusicFinished = false; - SetMusicFinishedCallback(MusicFinishedCallback); -#ifdef USE_FLUIDSYNTH - InitFluidSynth(); -#endif -} - -//@} diff --git a/src/sound/sound_server.cpp b/src/sound/sound_server.cpp index 409acfe4a..76235355f 100644 --- a/src/sound/sound_server.cpp +++ b/src/sound/sound_server.cpp @@ -39,13 +39,10 @@ #include "sound_server.h" -#ifdef USE_FLUIDSYNTH -#include "fluidsynth.h" -#endif - #include "iocompat.h" #include "iolib.h" #include "unit.h" +#include "script.h" #include "SDL.h" #include "SDL_mixer.h" @@ -57,10 +54,10 @@ static bool SoundInitialized; /// is sound initialized static bool MusicEnabled = true; static bool EffectsEnabled = true; -static double VolumeScale = 1.0; -static int MusicVolume = 0; +static int EffectsVolume = 255; +static int MusicVolume = 255; -extern volatile bool MusicFinished; +volatile bool MusicFinished; /// Channels for sound effects and unit speech struct SoundChannel { @@ -106,8 +103,10 @@ static void ChannelFinished(int channel) if (Channels[channel].FinishedCallback) { Channels[channel].FinishedCallback(channel); } - delete Channels[channel].Unit; - Channels[channel].Unit = NULL; + if (Channels[channel].Unit) { + delete Channels[channel].Unit; + Channels[channel].Unit = NULL; + } } /** @@ -120,7 +119,7 @@ static void ChannelFinished(int channel) */ int SetChannelVolume(int channel, int volume) { - return Mix_Volume(channel, volume * VolumeScale); + return Mix_Volume(channel, volume); } /** @@ -191,26 +190,19 @@ void StopAllChannels() Mix_HaltChannel(-1); } -static Mix_Music *currentMusic = NULL; +static Mix_Chunk *currentMusic = NULL; +static int currentMusicChannel = -1; -static Mix_Music *LoadMusic(const char *name) +static Mix_Chunk *LoadMusic(const char *name) { + if (currentMusicChannel >= 0) { + Mix_HaltChannel(currentMusicChannel); + } if (currentMusic) { - Mix_HaltMusic(); - Mix_FreeMusic(currentMusic); + Mix_FreeChunk(currentMusic); + currentMusic = NULL; } - currentMusic = Mix_LoadMUS(name); - if (currentMusic) { - return currentMusic; - } - - CFile *f = new CFile; - if (f->open(name, CL_OPEN_READ) == -1) { - printf("Can't open file '%s'\n", name); - delete f; - return NULL; - } - currentMusic = Mix_LoadMUS_RW(f->as_SDL_RWops(), 0); + currentMusic = LoadSample(name); return currentMusic; } @@ -236,10 +228,10 @@ static Mix_Chunk *LoadSample(const char *name) ** ** @return Mix_Music pointer */ -Mix_Music *LoadMusic(const std::string &name) +Mix_Chunk *LoadMusic(const std::string &name) { const std::string filename = LibraryFileName(name.c_str()); - Mix_Music *music = LoadMusic(filename.c_str()); + Mix_Chunk *music = LoadMusic(filename.c_str()); if (music == NULL) { fprintf(stderr, "Can't load the music '%s'\n", name.c_str()); @@ -280,6 +272,7 @@ int PlaySample(Mix_Chunk *sample, Origin *origin) DebugPrint("play sample %d\n" _C_ sample->volume); if (SoundEnabled() && EffectsEnabled && sample) { channel = Mix_PlayChannel(-1, sample, 0); + SetChannelVolume(channel, EffectsVolume); Channels[channel].FinishedCallback = NULL; if (origin && origin->Base) { Origin *source = new Origin; @@ -298,7 +291,7 @@ int PlaySample(Mix_Chunk *sample, Origin *origin) */ void SetEffectsVolume(int volume) { - VolumeScale = (volume * 1.0) / 255.0; + EffectsVolume = volume; } /** @@ -306,7 +299,7 @@ void SetEffectsVolume(int volume) */ int GetEffectsVolume() { - return VolumeScale * 255; + return EffectsVolume; } /** @@ -329,12 +322,40 @@ bool IsEffectsEnabled() -- Music ----------------------------------------------------------------------------*/ +bool CallbackMusic; /// flag true callback ccl if stops + +/*---------------------------------------------------------------------------- +-- Functions +----------------------------------------------------------------------------*/ + + /** -** Set the music finished callback +** Check if music is finished and play the next song */ -void SetMusicFinishedCallback(void (*callback)()) +void CheckMusicFinished(bool force) { - Mix_HookMusicFinished(callback); + // this races, but that's just fine, since we'll just miss a frame of we're unlucky + bool proceed = MusicFinished; + if (!(((proceed || force) && SoundEnabled() && IsMusicEnabled() && CallbackMusic))) { + return; + } + lua_getglobal(Lua, "MusicStopped"); + if (!lua_isfunction(Lua, -1)) { + fprintf(stderr, "No MusicStopped function in Lua\n"); + } else { + LuaCall(0, 1); + } + MusicFinished = false; +} + +/** +** Callback for when music has finished +** Note: we are in the sdl audio thread +*/ +static void MusicFinishedCallback(int channel) +{ + currentMusicChannel = -1; + MusicFinished = true; } /** @@ -344,13 +365,13 @@ void SetMusicFinishedCallback(void (*callback)()) ** ** @return 0 if music is playing, -1 if not. */ -int PlayMusic(Mix_Music *sample) +int PlayMusic(Mix_Chunk *sample) { if (sample) { - Mix_VolumeMusic(MusicVolume); MusicFinished = false; - Mix_PlayMusic(sample, 0); - Mix_VolumeMusic(MusicVolume / 4.0); + Mix_VolumeChunk(sample, MusicVolume); + int channel = Mix_FadeInChannel(-1, sample, 0, 500); + Channels[channel].FinishedCallback = MusicFinishedCallback; return 0; } else { DebugPrint("Could not play sample\n"); @@ -371,16 +392,8 @@ int PlayMusic(const std::string &file) return -1; } DebugPrint("play music %s\n" _C_ file.c_str()); - Mix_Music *music = LoadMusic(file); - - if (music) { - MusicFinished = false; - Mix_FadeInMusic(music, 0, 200); - return 0; - } else { - DebugPrint("Could not play %s\n" _C_ file.c_str()); - return -1; - } + Mix_Chunk *music = LoadMusic(file); + return PlayMusic(music); } /** @@ -388,7 +401,9 @@ int PlayMusic(const std::string &file) */ void StopMusic() { - Mix_FadeOutMusic(200); + if (currentMusicChannel) { + Mix_FadeOutChannel(currentMusicChannel, 500); + } } /** @@ -398,10 +413,10 @@ void StopMusic() */ void SetMusicVolume(int volume) { - // due to left-right separation, sound effect volume is effectively halfed, - // so we adjust the music MusicVolume = volume; - Mix_VolumeMusic(volume / 4.0); + if (currentMusicChannel) { + Mix_Volume(currentMusicChannel, volume); + } } /** @@ -438,7 +453,7 @@ bool IsMusicEnabled() */ bool IsMusicPlaying() { - return Mix_PlayingMusic(); + return !MusicFinished; } /*---------------------------------------------------------------------------- @@ -496,12 +511,12 @@ int InitSound() SoundInitialized = false; return 1; } + MusicFinished = false; SoundInitialized = true; Mix_AllocateChannels(MaxChannels); Mix_ChannelFinished(ChannelFinished); // Now we're ready for the callback to run - Mix_ResumeMusic(); Mix_Resume(-1); return 0; } diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp index 621451745..649ee2485 100644 --- a/src/stratagus/stratagus.cpp +++ b/src/stratagus/stratagus.cpp @@ -720,9 +720,7 @@ int stratagusMain(int argc, char **argv) // Setup sound card, must be done before loading sounds, so that // SDL_mixer can auto-convert to the target format - if (!InitSound()) { - InitMusic(); - } + InitSound(); LoadCcl(parameters.luaStartFilename, parameters.luaScriptArguments); diff --git a/src/video/movie.cpp b/src/video/movie.cpp index bf89def97..4dc063715 100644 --- a/src/video/movie.cpp +++ b/src/video/movie.cpp @@ -361,7 +361,7 @@ int PlayMovie(const std::string &name) } StopMusic(); - Mix_Music *sample = LoadMusic(filename); + Mix_Chunk *sample = LoadMusic(filename); if (sample) { PlayMusic(sample); }