SoundManager: Completely rewrote the file management

actorid
Michael Papageorgiou 13 years ago
parent 03ea3bb62f
commit 54353794e5

@ -64,28 +64,36 @@ namespace MWSound
SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera,
const Files::PathContainer& dataDirs,
bool useSound, bool fsstrict, MWWorld::Environment& environment)
: fsStrict(fsstrict)
: mFSStrict(fsstrict)
, mEnvironment(environment)
, mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY)))
, updater(mgr)
, cameraTracker(mgr)
{
for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
{
MP3Lookup((*it) / "Music/Explore/");
}
if(useSound)
{
Files::PathContainer soundDirs;;
// Make a list of all the sounds
Files::PathContainer soundDirs;
for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
{
soundDirs.push_back( *it / std::string("Sound"));
}
soundfiles = soundDirs;
strict = soundDirs;
musicpath = dataDirs;
musicpathStrict = dataDirs;
for (Files::PathContainer::const_iterator it = soundDirs.begin(); it != soundDirs.end(); ++it)
{
Files::FileLister(*it, mSoundFiles, true);
}
// Make a list of all the music tracks
Files::PathContainer musicDirs;
for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
{
musicDirs.push_back( *it / std::string("Music") / std::string("Explore"));
}
for (Files::PathContainer::const_iterator it = musicDirs.begin(); it != musicDirs.end(); ++it)
{
Files::FileLister(*it, mMusicFiles, true);
}
std::cout << "Sound output: " << SOUND_OUT << std::endl;
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
// Attach the camera to the camera tracker
@ -105,103 +113,6 @@ namespace MWSound
cameraTracker.unfollowCamera();
}
static std::string SoundManager::toMp3(std::string str)
{
std::string::size_type i = str.rfind('.');
if(str.find('/', i) == std::string::npos &&
str.find('\\', i) == std::string::npos)
str = str.substr(0, i) + ".mp3";
else
str += ".mp3";
return str;
}
bool SoundManager::hasFile(const std::string &str, bool music)
{
bool found = false;
if(!fsStrict)
{
if(music)
{
found = musicpath.has(str);
// Not found? Try with .mp3
if (!found)
{
found = musicpath.has(toMp3(str));
}
}
else
{
found = soundfiles.has(str);
if (!found)
{
found = soundfiles.has(toMp3(str));
}
}
}
else
{
if(music)
{
found = musicpathStrict.has(str);
// Not found? Try with .mp3
if (!found)
{
found = musicpathStrict.has(toMp3(str));
}
}
else
{
found = strict.has(str);
if (!found)
{
found = strict.has(toMp3(str));
}
}
}
return found;
}
// Convert a Morrowind sound path (eg. Fx\funny.wav) to full path
// with proper slash conversion (eg. datadir/Sound/Fx/funny.wav)
std::string SoundManager::convertPath(const std::string &str, bool music)
{
if(fsStrict == false)
{
// Search and return
if(music && musicpath.has(str))
return musicpath.lookup(str);
else if(soundfiles.has(str))
return soundfiles.lookup(str);
// Try mp3 if the wav wasn't found
std::string mp3 = toMp3(str);
if(music && musicpath.has(mp3))
return musicpath.lookup(mp3);
else if(soundfiles.has(mp3))
return soundfiles.lookup(mp3);
}
else
{
if(music && musicpathStrict.has(str))
return musicpathStrict.lookup(str);
else if(strict.has(str))
return strict.lookup(str);
// Try mp3 if the wav wasn't found
std::string mp3 = toMp3(str);
if(music && musicpathStrict.has(mp3))
return musicpathStrict.lookup(mp3);
else if(strict.has(str))
return strict.lookup(mp3);
}
// Give up
return "";
}
// Convert a soundId to file name, and modify the volume
// according to the sounds local volume setting, minRange and
// maxRange.
@ -229,7 +140,7 @@ namespace MWSound
max = std::max(min, max);
}
return convertPath(snd->sound);
return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict);
}
// Add a sound to the list and play it
@ -376,33 +287,20 @@ namespace MWSound
void SoundManager::streamMusic(const std::string& filename)
{
if(hasFile(filename, true))
{
streamMusicFull(convertPath(filename, true));
}
}
void SoundManager::MP3Lookup(const boost::filesystem::path& dir)
{
boost::filesystem::directory_iterator dir_iter(dir), dir_end;
std::string mp3extension = ".mp3";
for(;dir_iter != dir_end; dir_iter++)
{
if(boost::filesystem::extension(*dir_iter) == mp3extension)
std::string filePath = Files::FileListLocator(mMusicFiles, filename, mFSStrict);
if(!filePath.empty())
{
files.push_back(*dir_iter);
streamMusicFull(filePath);
}
}
}
void SoundManager::startRandomTitle()
{
if(!files.empty())
if(!mMusicFiles.empty())
{
Files::PathContainer::iterator fileIter = files.begin();
Files::PathContainer::iterator fileIter = mMusicFiles.begin();
srand( time(NULL) );
int r = rand() % files.size() + 1; //old random code
int r = rand() % mMusicFiles.size() + 1; //old random code
std::advance(fileIter, r - 1);
std::string music = fileIter->string();
@ -432,8 +330,9 @@ namespace MWSound
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
{
// The range values are not tested
if(hasFile(filename))
add(convertPath(filename), ptr, "_say_sound", 1, 1, 100, 20000, false);
std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict);
if(!filePath.empty())
add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false);
else
std::cout << "Sound file " << filename << " not found, skipping.\n";
}
@ -448,7 +347,7 @@ namespace MWSound
{
// Play and forget
float min, max;
const std::string &file = ookup(soundId, volume, min, max);
const std::string &file = lookup(soundId, volume, min, max);
if (file != "")
{
SoundPtr snd = mgr->load(file);

@ -10,7 +10,7 @@
#include <mangle/sound/clients/ogre_listener_mover.hpp>
#include <openengine/sound/sndmanager.hpp>
#include <components/files/multidircollection.hpp>
#include <components/files/fileops.hpp>
#include <components/file_finder/file_finder.hpp>
#include "../mwworld/ptr.hpp"
@ -47,8 +47,13 @@ namespace MWSound
{
class SoundManager
{
Files::PathContainer files;
bool fsStrict;
// This is used for case insensitive and slash-type agnostic file
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
// relative to the sound dir, and translates them into full paths
// of existing files in the filesystem, if they exist.
bool mFSStrict;
MWWorld::Environment& mEnvironment;
int total;
@ -79,19 +84,10 @@ namespace MWSound
typedef std::map<MWWorld::Ptr,IDMap> PtrMap;
PtrMap sounds;
// This is used for case insensitive and slash-type agnostic file
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
// relative to the sound dir, and translates them into full paths
// of existing files in the filesystem, if they exist.
bool FSstrict;
FileFinder::LessTreeFileFinder soundfiles;
FileFinder::StrictTreeFileFinder strict;
FileFinder::LessTreeFileFinder musicpath;
FileFinder::StrictTreeFileFinder musicpathStrict;
static std::string toMp3(std::string str);
bool hasFile(const std::string &str, bool music = false);
std::string convertPath(const std::string &str, bool music = false);
Files::PathContainer mSoundFiles;
Files::PathContainer mMusicFiles;
std::string lookup(const std::string &soundId,
float &volume, float &min, float &max);
void add(const std::string &file,
@ -116,7 +112,6 @@ namespace MWSound
/// \param filename name of a sound file in "Music/" in the data directory.
void startRandomTitle();
void MP3Lookup(const boost::filesystem::path& dir);
bool isMusicPlaying();

@ -1,5 +1,6 @@
#include "fileops.hpp"
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
namespace Files
{
@ -9,4 +10,90 @@ bool isFile(const char *name)
return boost::filesystem::exists(boost::filesystem::path(name));
}
// Makes a list of files from a directory
void FileLister( boost::filesystem::path currentPath, Files::PathContainer& list, bool recursive)
{
if (!boost::filesystem::exists(currentPath))
{
std::cout << "WARNING: " << currentPath.string() << " does not exist.\n";
return ;
}
if (recursive)
{
for ( boost::filesystem::recursive_directory_iterator end, itr(currentPath.string());
itr != end; ++itr )
{
if ( boost::filesystem::is_regular_file(*itr))
list.push_back(itr->path());
}
}
else
{
for ( boost::filesystem::directory_iterator end, itr(currentPath.string());
itr != end; ++itr )
{
if ( boost::filesystem::is_regular_file(*itr))
list.push_back(itr->path());
}
}
}
// Locates path in path container
boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind, bool strict)
{
boost::filesystem::path result("");
if (list.empty())
return result;
std::string toFindStr = toFind.string();
std::string fullPath;
// The filesystems slash sets the default slash
std::string slash;
std::string wrongslash;
if(list[0].string().find("\\") != std::string::npos)
{
slash = "\\";
wrongslash = "/";
}
else
{
slash = "/";
wrongslash = "\\";
}
// The file being looked for is converted to the new slash
if(toFindStr.find(wrongslash) != std::string::npos )
{
boost::replace_all(toFindStr, wrongslash, slash);
}
if (!strict)
{
boost::algorithm::to_lower(toFindStr);
}
for (Files::PathContainer::const_iterator it = list.begin(); it != list.end(); ++it)
{
fullPath = it->string();
if (!strict)
{
boost::algorithm::to_lower(fullPath);
}
if(fullPath.find(toFindStr) != std::string::npos)
{
result = *it;
break;
}
}
return result;
}
// Overloaded form of the locator that takes a string and returns a string
std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict)
{
return FileListLocator(list, boost::filesystem::path(toFind), strict).string();
}
}

@ -1,6 +1,12 @@
#ifndef COMPONENTS_FILES_FILEOPS_HPP
#define COMPONENTS_FILES_FILEOPS_HPP
#include <map>
#include <vector>
#include <string>
#include <boost/filesystem/path.hpp>
namespace Files
{
@ -8,6 +14,24 @@ namespace Files
///\param [in] name - filename
bool isFile(const char *name);
/// A vector of Boost Paths, very handy
typedef std::vector<boost::filesystem::path> PathContainer;
/// Makes a list of files from a directory by taking a boost
/// path and a Path Container and adds to the Path container
/// all files in the path. It has a recursive option.
void FileLister( boost::filesystem::path currentPath, Files::PathContainer& list, bool recursive);
/// Locates boost path in path container
/// returns the path from the container
/// that contains the searched path.
/// If it's not found it returns and empty path
/// Takes care of slashes, backslashes and it has a strict option.
boost::filesystem::path FileListLocator (const Files::PathContainer& list, const boost::filesystem::path& toFind, bool strict);
/// Overloaded form of the locator that takes a string and returns a string
std::string FileListLocator (const Files::PathContainer& list,const std::string& toFind, bool strict);
}
#endif /* COMPONENTS_FILES_FILEOPS_HPP */

Loading…
Cancel
Save