mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 08:15:37 +00:00
SoundManager: Completely rewrote the file management
This commit is contained in:
parent
03ea3bb62f
commit
54353794e5
4 changed files with 152 additions and 147 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
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();
|
||||
|
||||
|
|
|
@ -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…
Reference in a new issue