Removed exception throwing from MusicInformation constructor, and
use a simple static function to create a MusicInformation object. This simplifies handling of errors in calling functions, and appears to have fixed a (minor) memory leak as well. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9973 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
a294b36ced
commit
9767765cb9
@ -29,7 +29,46 @@
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
MusicInformation::MusicInformation(const std::string& filename) throw (std::runtime_error)
|
||||
/** A simple factory to create music information files without raising
|
||||
* an exception on error, instead a NULL will be returned. This avoids
|
||||
* resource freeing problems if the exception is raised, and simplifies
|
||||
* calling code.
|
||||
* \param filename The name of a music file.
|
||||
* \return The MusicInformation object, or NULL in case of an error.
|
||||
*/
|
||||
MusicInformation *MusicInformation::create(const std::string &filename)
|
||||
{
|
||||
assert(filename.size() > 0);
|
||||
|
||||
XMLNode* root = file_manager->createXMLTree(filename);
|
||||
if (!root) return NULL;
|
||||
if(root->getName()!="music")
|
||||
{
|
||||
fprintf(stderr, "Music file '%s' does not contain music node.\n",
|
||||
filename.c_str());
|
||||
delete root;
|
||||
return NULL;
|
||||
}
|
||||
std::string s;
|
||||
if(!root->get("title", &s) ||
|
||||
!root->get("composer", &s) ||
|
||||
!root->get("file", &s) )
|
||||
|
||||
{
|
||||
fprintf(stderr, "One of 'title', 'composer' or 'file' attribute "
|
||||
"is missing in the music XML file '%s'!\n",
|
||||
filename.c_str());
|
||||
delete root;
|
||||
return NULL;
|
||||
}
|
||||
MusicInformation *mi = new MusicInformation(root, filename);
|
||||
delete root;
|
||||
return mi;
|
||||
} // create()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
MusicInformation::MusicInformation(const XMLNode *root,
|
||||
const std::string &filename)
|
||||
{
|
||||
m_title = "";
|
||||
m_mode = SOUND_NORMAL;
|
||||
@ -45,69 +84,19 @@ MusicInformation::MusicInformation(const std::string& filename) throw (std::runt
|
||||
m_gain = 1.0f;
|
||||
m_adjusted_gain = 1.0f;
|
||||
|
||||
assert(filename.size() > 0);
|
||||
|
||||
if (StringUtils::getExtension(filename) != "music")
|
||||
{
|
||||
// Create information just from ogg file
|
||||
// -------------------------------------
|
||||
m_title = core::stringw(StringUtils::removeExtension(StringUtils::getBasename(filename)).c_str());
|
||||
m_normal_filename = filename;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise read config file
|
||||
// --------------------------
|
||||
XMLNode* root = file_manager->createXMLTree(filename);
|
||||
if (!root)
|
||||
{
|
||||
// Don't print a message here - not finding a music file
|
||||
// is normal since the file is searched in several different
|
||||
// directories (e.g. in data/tracks/XX and data/music).
|
||||
throw std::runtime_error("Could not open music XML file");
|
||||
}
|
||||
if(root->getName()!="music")
|
||||
{
|
||||
std::ostringstream msg;
|
||||
fprintf(stderr, "Music XML file '%s' does not contain music node.",
|
||||
filename.c_str());
|
||||
throw std::runtime_error("No music node found");
|
||||
}
|
||||
std::string title;
|
||||
if(!root->get("title", &title))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"The 'title' attribute is missing in the music XML file '%s'!\n",
|
||||
filename.c_str());
|
||||
throw std::runtime_error("Incomplete or corrupt music XML file");
|
||||
return;
|
||||
}
|
||||
m_title = StringUtils::decodeFromHtmlEntities(title);
|
||||
|
||||
std::string composer;
|
||||
if(!root->get("composer", &composer))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"The 'composer' attribute is missing in the music XML file '%s'!\n",
|
||||
filename.c_str());
|
||||
throw std::runtime_error("Incomplete or corrupt music XML file");
|
||||
return;
|
||||
}
|
||||
m_composer = StringUtils::decodeFromHtmlEntities(composer);
|
||||
|
||||
if(!root->get("file", &m_normal_filename))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"The 'file' attribute is mandatory in the music XML file '%s'!\n",
|
||||
filename.c_str());
|
||||
throw std::runtime_error("Incomplete or corrupt music XML file");
|
||||
return;
|
||||
}
|
||||
root->get("gain", &m_adjusted_gain);
|
||||
root->get("tracks", &m_all_tracks );
|
||||
root->get("fast", &m_enable_fast );
|
||||
root->get("fast-filename", &m_fast_filename);
|
||||
delete root;
|
||||
std::string s;
|
||||
root->get("title", &s );
|
||||
m_title = StringUtils::decodeFromHtmlEntities(s);
|
||||
root->get("composer", &s );
|
||||
m_composer = StringUtils::decodeFromHtmlEntities(s);
|
||||
root->get("file", &m_normal_filename);
|
||||
root->get("gain", &m_adjusted_gain );
|
||||
root->get("tracks", &m_all_tracks );
|
||||
root->get("fast", &m_enable_fast );
|
||||
root->get("fast-filename", &m_fast_filename );
|
||||
|
||||
// Get the path from the filename and add it to the ogg filename
|
||||
std::string path = StringUtils::getPath(filename);
|
||||
|
@ -31,6 +31,7 @@
|
||||
using irr::core::stringw;
|
||||
|
||||
class Music;
|
||||
class XMLNode;
|
||||
|
||||
/**
|
||||
* \brief Wrapper around an instance of the Music interface
|
||||
@ -55,27 +56,31 @@ private:
|
||||
float m_gain;
|
||||
float m_adjusted_gain;
|
||||
|
||||
/** Either time for fading faster music in, or time to change pitch */
|
||||
/** Either time for fading faster music in, or time to change pitch. */
|
||||
float m_faster_time;
|
||||
float m_max_pitch; //!< maximum pitch for faster music
|
||||
/** Maximum pitch for faster music. */
|
||||
float m_max_pitch;
|
||||
static const int LOOP_FOREVER=-1;
|
||||
Music *m_normal_music,
|
||||
*m_fast_music;
|
||||
enum {SOUND_NORMAL, //!< normal music is played
|
||||
SOUND_FADING, //!< normal music fading out, faster fading in
|
||||
SOUND_FASTER, //!< change pitch of normal music
|
||||
SOUND_FAST} //!< playing faster music or max pitch reached
|
||||
enum {SOUND_NORMAL, //!< normal music is played
|
||||
SOUND_FADING, //!< normal music fading out, faster fading in
|
||||
SOUND_FASTER, //!< change pitch of normal music
|
||||
SOUND_FAST} //!< playing faster music or max pitch reached
|
||||
m_mode;
|
||||
float m_time_since_faster;
|
||||
|
||||
// The constructor is private so that the
|
||||
// static create function must be used.
|
||||
MusicInformation (const XMLNode *root, const std::string &filename);
|
||||
public:
|
||||
LEAK_CHECK()
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#pragma warning(disable:4290)
|
||||
#endif
|
||||
MusicInformation (const std::string& filename) throw (std::runtime_error);
|
||||
~MusicInformation ();
|
||||
static MusicInformation *create(const std::string &filename);
|
||||
const stringw& getComposer () const {return m_composer; }
|
||||
const stringw& getTitle () const {return m_title; }
|
||||
const std::string& getNormalFilename() const {return m_normal_filename; }
|
||||
|
@ -118,16 +118,11 @@ void MusicManager::loadMusicFromOneDir(const std::string& dir)
|
||||
for(std::set<std::string>::iterator i = files.begin(); i != files.end(); ++i)
|
||||
{
|
||||
if(StringUtils::getExtension(*i)!="music") continue;
|
||||
try
|
||||
{
|
||||
m_all_music[StringUtils::getBasename(*i)] = new MusicInformation(*i);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
(void)e; // avoid compiler warning
|
||||
continue;
|
||||
}
|
||||
MusicInformation *mi = MusicInformation::create(*i);
|
||||
if(mi)
|
||||
m_all_music[StringUtils::getBasename(*i)] = mi;
|
||||
} // for i
|
||||
|
||||
} // loadMusicFromOneDir
|
||||
|
||||
//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------
|
||||
@ -188,7 +183,8 @@ void MusicManager::setMasterMusicVolume(float gain)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*/
|
||||
MusicInformation* MusicManager::getMusicInformation(const std::string& filename)
|
||||
{
|
||||
if(filename=="")
|
||||
@ -196,15 +192,20 @@ MusicInformation* MusicManager::getMusicInformation(const std::string& filename)
|
||||
return NULL;
|
||||
}
|
||||
const std::string basename = StringUtils::getBasename(filename);
|
||||
MusicInformation* mi = m_all_music[basename];
|
||||
if(!mi)
|
||||
std::map<std::string, MusicInformation*>::iterator p;
|
||||
p = m_all_music.find(basename);
|
||||
if(p==m_all_music.end())
|
||||
{
|
||||
// Note that this might raise an exception
|
||||
mi = new MusicInformation(filename);
|
||||
m_all_music[basename] = mi;
|
||||
MusicInformation *mi = MusicInformation::create(filename);
|
||||
if(mi)
|
||||
{
|
||||
mi->volumeMusic(m_masterGain);
|
||||
m_all_music[basename] = mi;
|
||||
}
|
||||
return mi;
|
||||
}
|
||||
mi->volumeMusic(m_masterGain);
|
||||
return mi;
|
||||
return p->second;
|
||||
} // getMusicInformation
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -244,14 +244,10 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
music_node->get("title", &title_music);
|
||||
assert(title_music.size() > 0);
|
||||
|
||||
try
|
||||
{
|
||||
m_title_music = new MusicInformation(file_manager->getDataDir() + "/music/" + title_music);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
fprintf(stderr, "Cannot load title music : %s\n", e.what());
|
||||
}
|
||||
m_title_music = MusicInformation::create(file_manager->getDataDir()
|
||||
+ "/music/" + title_music );
|
||||
if(!m_title_music)
|
||||
fprintf(stderr, "Cannot load title music : %s\n", title_music);
|
||||
}
|
||||
|
||||
if(const XMLNode *history_node = root->getNode("history"))
|
||||
|
@ -97,6 +97,9 @@ Track::Track(const std::string &filename)
|
||||
/** Destructor, removes quad data structures etc. */
|
||||
Track::~Track()
|
||||
{
|
||||
// Note that the music information in m_music is globally managed
|
||||
// by the music_manager, and is freed there. So no need to free it
|
||||
// here (esp. since various track might share the same music).
|
||||
#ifdef DEBUG
|
||||
assert(m_magic_number == 0x17AC3802);
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
@ -333,47 +336,29 @@ void Track::getMusicInformation(std::vector<std::string>& filenames,
|
||||
for(int i=0; i<(int)filenames.size(); i++)
|
||||
{
|
||||
std::string full_path = m_root+"/"+filenames[i];
|
||||
MusicInformation* mi;
|
||||
try
|
||||
{
|
||||
mi = music_manager->getMusicInformation(full_path);
|
||||
}
|
||||
catch(std::runtime_error)
|
||||
{
|
||||
mi = NULL;
|
||||
}
|
||||
MusicInformation* mi = music_manager->getMusicInformation(full_path);
|
||||
if(!mi)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string shared_name = file_manager->getMusicFile(filenames[i]);
|
||||
if(shared_name!="")
|
||||
{
|
||||
try
|
||||
{
|
||||
mi = music_manager->getMusicInformation(shared_name);
|
||||
}
|
||||
catch(std::runtime_error)
|
||||
{
|
||||
mi = NULL;
|
||||
}
|
||||
} // shared_name!=""
|
||||
mi = music_manager->getMusicInformation(shared_name);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (...)
|
||||
{
|
||||
(void)e;
|
||||
mi = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
if(!mi)
|
||||
{
|
||||
fprintf(stderr, "Music information file '%s' not found - ignored.\n",
|
||||
if(mi)
|
||||
m_music.push_back(mi);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Music information file '%s' not found - ignored.\n",
|
||||
filenames[i].c_str());
|
||||
continue;
|
||||
}
|
||||
m_music.push_back(mi);
|
||||
|
||||
} // for i in filenames
|
||||
|
||||
} // getMusicInformation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user