sprite.h \
sprite.cpp \
sprite_manager.cpp \
-sprite_manager.h
+sprite_manager.h \
+music_manager.cpp \
+music_manager.h \
+musicref.cpp \
+musicref.h
# EOF #
#include "tile.h"
#include "particlesystem.h"
#include "resources.h"
+#include "music_manager.h"
GameSession* GameSession::current_ = 0;
void
GameSession::levelintro(void)
{
+ music_manager->halt_music();
+
char str[60];
/* Level Intro: */
clearscreen(0, 0, 0);
{
end_sequenze = true;
last_x_pos = -1;
- halt_music();
+ music_manager->halt_music();
}
else
{
#include "scene.h"
#include "tile.h"
#include "lispreader.h"
+#include "resources.h"
+#include "music_manager.h"
using namespace std;
}
Level::Level()
- : img_bkgd(0), level_song(0), level_song_fast(0)
+ : img_bkgd(0)
{
}
Level::Level(const std::string& subset, int level)
- : img_bkgd(0), level_song(0), level_song_fast(0)
+ : img_bkgd(0)
{
load(subset, level);
}
Level::Level(const std::string& filename)
- : img_bkgd(0), level_song(0), level_song_fast(0)
+ : img_bkgd(0)
{
load(filename);
}
Level::~Level()
{
free_gfx();
- free_song();
}
void
}
}
-void
-Level::free_song(void)
-{
- if(level_song_fast != level_song) {
- free_music(level_song_fast);
- level_song_fast = 0;
- }
-
- free_music(level_song);
- level_song = 0;
-}
-
void
Level::load_song()
{
- free_song();
-
char* song_path;
char* song_subtitle;
- level_song = ::load_song(datadir + "/music/" + song_title);
- if(!level_song)
- st_abort("Couldn't load song: " , song_title.c_str());
+ level_song = music_manager->load_music(datadir + "/music/" + song_title);
song_path = (char *) malloc(sizeof(char) * datadir.length() +
strlen(song_title.c_str()) + 8 + 5);
strcpy(strstr(song_subtitle, "."), "\0");
sprintf(song_path, "%s/music/%s-fast%s", datadir.c_str(),
song_subtitle, strstr(song_title.c_str(), "."));
- level_song_fast = ::load_song(song_path);
- if(!level_song_fast) {
+ if(!music_manager->exists_music(song_path)) {
level_song_fast = level_song;
+ } else {
+ level_song_fast = music_manager->load_music(song_path);
}
free(song_subtitle);
free(song_path);
}
-Mix_Music*
+MusicRef
Level::get_level_music()
{
return level_song;
}
-Mix_Music*
+MusicRef
Level::get_level_music_fast()
{
return level_song_fast;
#include "texture.h"
#include "badguy.h"
#include "lispreader.h"
+#include "musicref.h"
class Tile;
{
public:
Surface* img_bkgd;
- Mix_Music* level_song;
- Mix_Music* level_song_fast;
+ MusicRef level_song;
+ MusicRef level_song_fast;
std::string name;
std::string author;
void load_song();
void free_song();
- Mix_Music* get_level_music();
- Mix_Music* get_level_music_fast();
+ MusicRef get_level_music();
+ MusicRef get_level_music_fast();
void save(const char* subset, int level);
--- /dev/null
+// $Id$
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//
+// 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; either version 2
+// of the License, or (at your option) any later version.
+//
+// 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.
+
+#include <assert.h>
+#include "music_manager.h"
+#include "musicref.h"
+#include "sound.h"
+#include "setup.h"
+
+MusicManager::MusicManager()
+ : music_enabled(true)
+{ }
+
+MusicManager::~MusicManager()
+{
+ if(audio_device)
+ Mix_HaltMusic();
+}
+
+MusicRef
+MusicManager::load_music(const std::string& file)
+{
+ if(!audio_device)
+ return MusicRef(0);
+
+ if(!exists_music(file))
+ st_abort("Couldn't load musicfile ", file.c_str());
+
+ std::map<std::string, MusicResource>::iterator i = musics.find(file);
+ assert(i != musics.end());
+ return MusicRef(& (i->second));
+}
+
+bool
+MusicManager::exists_music(const std::string& file)
+{
+ if(!audio_device)
+ return true;
+
+ // song already loaded?
+ std::map<std::string, MusicResource>::iterator i = musics.find(file);
+ if(i != musics.end()) {
+ return true;
+ }
+
+ Mix_Music* song = Mix_LoadMUS(file.c_str());
+ if(song == 0)
+ return false;
+
+ // insert into music list
+ std::pair<std::map<std::string, MusicResource>::iterator, bool> result =
+ musics.insert(
+ std::make_pair<std::string, MusicResource> (file, MusicResource()));
+ MusicResource& resource = result.first->second;
+ resource.manager = this;
+ resource.music = song;
+
+ return true;
+}
+
+void
+MusicManager::free_music(MusicResource* )
+{
+ // TODO free music, currently we can't do this since SDL_mixer seems to have
+ // some bugs if you load/free alot of mod files.
+}
+
+void
+MusicManager::play_music(const MusicRef& musicref)
+{
+ if(!audio_device)
+ return;
+
+ if(musicref.music == 0 || current_music == musicref.music)
+ return;
+
+ if(current_music)
+ current_music->refcount--;
+
+ current_music = musicref.music;
+ current_music->refcount++;
+
+ if(music_enabled)
+ Mix_PlayMusic(current_music->music, -1);
+}
+
+void
+MusicManager::halt_music()
+{
+ if(!audio_device)
+ return;
+
+ Mix_HaltMusic();
+
+ if(current_music) {
+ current_music->refcount--;
+ if(current_music->refcount == 0)
+ free_music(current_music);
+ current_music = 0;
+ }
+}
+
+void
+MusicManager::enable_music(bool enable)
+{
+ if(!audio_device)
+ return;
+
+ if(enable == music_enabled)
+ return;
+
+ music_enabled = enable;
+ if(music_enabled == false) {
+ Mix_HaltMusic();
+ } else {
+ Mix_PlayMusic(current_music->music, -1);
+ }
+}
+
+MusicManager::MusicResource::~MusicResource()
+{
+ // buggy SDL_mixer :-/
+ // Mix_FreeMusic(music);
+}
+
--- /dev/null
+// $Id$
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
+// Copyright (C) 2004 Duong-Khang NGUYEN <neoneurone@users.sf.net>
+//
+// 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; either version 2
+// of the License, or (at your option) any later version.
+//
+// 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.
+#ifndef HEADER_MUSIC_MANAGER_H
+#define HEADER_MUSIC_MANAGER_H
+
+#include <SDL_mixer.h>
+#include <string>
+#include <map>
+
+class MusicRef;
+
+/** This class manages a list of music resources and is responsible for playing
+ * the music.
+ */
+class MusicManager
+{
+public:
+ MusicManager();
+ ~MusicManager();
+
+ MusicRef load_music(const std::string& file);
+ bool exists_music(const std::string& filename);
+
+ void play_music(const MusicRef& music);
+ void halt_music();
+
+ void enable_music(bool enable);
+
+private:
+ friend class MusicRef;
+ class MusicResource
+ {
+ public:
+ ~MusicResource();
+
+ MusicManager* manager;
+ Mix_Music* music;
+ int refcount;
+ };
+
+ void free_music(MusicResource* music);
+
+ std::map<std::string, MusicResource> musics;
+ MusicResource* current_music;
+ bool music_enabled;
+};
+
+#endif
+
--- /dev/null
+// $Id$
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
+// Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//
+// 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; either version 2
+// of the License, or (at your option) any later version.
+//
+// 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.
+#include "musicref.h"
+
+MusicRef::MusicRef()
+ : music(0)
+{
+}
+
+MusicRef::MusicRef(MusicManager::MusicResource* newmusic)
+ : music(newmusic)
+{
+ if(music)
+ music->refcount++;
+}
+
+MusicRef::~MusicRef()
+{
+ if(music) {
+ music->refcount--;
+ if(music->refcount == 0)
+ music->manager->free_music(music);
+ }
+}
+
+MusicRef::MusicRef(const MusicRef& other)
+ : music(other.music)
+{
+ if(music)
+ music->refcount++;
+}
+
+MusicRef&
+MusicRef::operator =(const MusicRef& other)
+{
+ MusicManager::MusicResource* oldres = music;
+ music = other.music;
+ if(music)
+ music->refcount++;
+ if(oldres) {
+ oldres->refcount--;
+ if(oldres->refcount == 0)
+ music->manager->free_music(music);
+ }
+
+ return *this;
+}
+
--- /dev/null
+// $Id$
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//
+// 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; either version 2
+// of the License, or (at your option) any later version.
+//
+// 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.
+#ifndef HEADER_MUSIC_RESOURCE_H
+#define HEADER_MUSIC_RESOURCE_H
+
+#include "music_manager.h"
+
+/** This class holds a reference to a music file and maintains a correct
+ * refcount for that file.
+ */
+class MusicRef
+{
+public:
+ MusicRef();
+ MusicRef(const MusicRef& other);
+ ~MusicRef();
+
+ MusicRef& operator= (const MusicRef& other);
+
+private:
+ friend class MusicManager;
+ MusicRef(MusicManager::MusicResource* music);
+
+ MusicManager::MusicResource* music;
+};
+
+#endif
+
Surface* img_red_glow;
+MusicRef herring_song;
+
SpriteManager* sprite_manager = 0;
+MusicManager* music_manager = 0;
/* Load graphics/sounds shared between all levels: */
void loadshared()
int i;
sprite_manager = new SpriteManager(datadir + "/supertux.strf");
+ music_manager = new MusicManager();
/* Tuxes: */
smalltux_star = sprite_manager->load("smalltux-star");
sounds[i] = load_sound(datadir + soundfilenames[i]);
/* Herring song */
- herring_song = load_song(datadir + "/music/SALCON.MOD");
- if(!herring_song)
- st_abort("Couldn't load song ", "/music/SALCON.MOD");
+ herring_song = music_manager->load_music(datadir + "/music/SALCON.MOD");
}
/* Free shared data: */
void unloadshared(void)
{
- delete sprite_manager;
-
int i;
free_special_gfx();
for (i = 0; i < NUM_SOUNDS; i++)
free_chunk(sounds[i]);
- /* free the herring song */
- free_music( herring_song );
+ delete sprite_manager;
+ sprite_manager = 0;
+ delete music_manager;
+ music_manager = 0;
}
/* EOF */
#ifndef SUPERTUX_RESOURCES_H
#define SUPERTUX_RESOURCES_H
+#include "musicref.h"
+
class SpriteManager;
+class MusicManager;
extern Surface* img_waves[3];
extern Surface* img_water;
extern Surface* img_super_bkgd;
extern Surface* img_red_glow;
+extern MusicRef herring_song;
+
extern SpriteManager* sprite_manager;
+extern MusicManager* music_manager;
void loadshared();
void unloadshared();
#include "configfile.h"
#include "scene.h"
#include "worldmap.h"
+#include "resources.h"
#include "player.h"
use_sound = !use_sound;
break;
case MNID_MUSIC:
- if(use_music != options_menu->item[MNID_MUSIC].toggled)
- {
- enable_music(options_menu->item[MNID_MUSIC].toggled);
- }
+ music_manager->enable_music(options_menu->item[MNID_MUSIC].toggled);
break;
case MNID_SHOWFPS:
if(show_fps != options_menu->item[MNID_SHOWFPS].toggled)
#include "setup.h"
/*global variable*/
-bool use_sound; /* handle sound on/off menu and command-line option */
-bool use_music; /* handle music on/off menu and command-line option */
-bool audio_device; /* != 0: available and initialized */
+bool use_sound = true; /* handle sound on/off menu and command-line option */
+bool use_music = true; /* handle music on/off menu and command-line option */
+bool audio_device = true; /* != 0: available and initialized */
int current_music;
char * soundfilenames[NUM_SOUNDS] = {
#include <SDL_mixer.h>
Mix_Chunk * sounds[NUM_SOUNDS];
-Mix_Music * herring_song = 0;
-Mix_Music * current_song = 0;
/* --- OPEN THE AUDIO DEVICE --- */
}
}
-void halt_music(void)
-{
- if (!use_music || !audio_device)
- return;
-
- Mix_HaltMusic();
- current_song = 0;
-}
-
-
-void play_music(Mix_Music *music)
-{
- if (!audio_device)
- return;
- if(music == current_song)
- return;
-
- if (use_music && Mix_PlayMusic(music, -1) < 0)
- st_abort("Couldn't play music: ", Mix_GetError());
-
- current_song = music;
-}
-
-
-void free_music(Mix_Music *music)
-{
- if(!audio_device)
- return;
-
- Mix_FreeMusic( music );
-}
-
-void enable_music(bool enable)
-{
- if(!audio_device)
- return;
-
- use_music = enable;
- if(!use_music)
- Mix_HaltMusic();
- else
- Mix_PlayMusic(current_song, -1);
-}
-
/* variables for stocking the sound and music */
extern Mix_Chunk* sounds[NUM_SOUNDS];
-extern Mix_Music* herring_song;
/* functions handling the sound and music */
int open_audio(int frequency, Uint16 format, int channels, int chunksize);
void free_chunk(Mix_Chunk*chunk);
void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker);
-Mix_Music* load_song(const std::string& file);
-void free_music(Mix_Music* music);
-void halt_music(void);
-void enable_music(bool enable);
-void play_music(Mix_Music* music);
-
#endif /*SUPERTUX_SOUND_H*/
{
index -= 1; // FIXME: Hack
std::cout << "Sarting level: " << index << std::endl;
- halt_music();
GameSession session(current_contrib_subset, index, ST_GL_PLAY);
session.run();
Menu::set_current(main_menu);
generate_contrib_menu();
break;
case MNID_LEVELEDITOR:
- halt_music();
leveleditor(1);
Menu::set_current(main_menu);
break;
for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
delete *i;
- halt_music(); // just to be sure (because levelmusic is freed now)
delete level;
}
currentmusic = musictype;
switch(currentmusic) {
case HURRYUP_MUSIC:
- ::play_music(get_level()->get_level_music_fast());
+ music_manager->play_music(get_level()->get_level_music_fast());
break;
case LEVEL_MUSIC:
- ::play_music(get_level()->get_level_music());
+ music_manager->play_music(get_level()->get_level_music());
break;
case HERRING_MUSIC:
- ::play_music(herring_song);
+ music_manager->play_music(herring_song);
break;
default:
- ::halt_music();
+ music_manager->halt_music();
break;
}
}
#include "gameloop.h"
#include "setup.h"
#include "worldmap.h"
+#include "resources.h"
namespace WorldMapNS {
name = "<no file>";
music = "SALCON.MOD";
- song = 0;
load_map();
}
level->y == tux->get_tile_pos().y)
{
std::cout << "Enter the current level: " << level->name << std::endl;;
- halt_music();
-
GameSession session(datadir + "levels/" + level->name,
1, ST_GL_LOAD_LEVEL_FILE);
break;
}
- play_music(song);
+ music_manager->play_music(song);
Menu::set_current(0);
if (!savegame_file.empty())
savegame(savegame_file);
quit = false;
- song = load_song(datadir + "/music/" + music);
- if(!song)
- st_abort("Couldn't load song ", music.c_str());
-
- play_music(song);
+ song = music_manager->load_music(datadir + "/music/" + music);
+ music_manager->play_music(song);
while(!quit) {
Point tux_pos = tux->get_pos();
SDL_Delay(20);
}
-
- halt_music();
- free_music(song);
}
void
#include <vector>
#include <string>
-#include <SDL_mixer.h>
+#include "musicref.h"
namespace WorldMapNS {
typedef std::vector<Level> Levels;
Levels levels;
- Mix_Music* song;
+ MusicRef song;
Direction input_direction;
bool enter_level;