diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index c269c02368..53da9040bc 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -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)) + std::string filePath = Files::FileListLocator(mMusicFiles, filename, mFSStrict); + if(!filePath.empty()) { - streamMusicFull(convertPath(filename, true)); + streamMusicFull(filePath); } } - 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) - { - files.push_back(*dir_iter); - } - } - } - 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); diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index cde8475e94..8f63cdb58a 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #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 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; + Files::PathContainer mSoundFiles; + + Files::PathContainer mMusicFiles; - 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); 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(); diff --git a/components/files/fileops.cpp b/components/files/fileops.cpp index 329e4eb05f..d6365e7534 100644 --- a/components/files/fileops.cpp +++ b/components/files/fileops.cpp @@ -1,5 +1,6 @@ #include "fileops.hpp" #include +#include 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(); + } + } diff --git a/components/files/fileops.hpp b/components/files/fileops.hpp index a541beffc2..49ef7b9472 100644 --- a/components/files/fileops.hpp +++ b/components/files/fileops.hpp @@ -1,6 +1,12 @@ #ifndef COMPONENTS_FILES_FILEOPS_HPP #define COMPONENTS_FILES_FILEOPS_HPP +#include +#include +#include + +#include + 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 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 */