mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-25 16:43:33 +00:00
SoundManager: Completely rewrote the file management
This commit is contained in:
parent
03ea3bb62f
commit
54353794e5
@ -64,28 +64,36 @@ namespace MWSound
|
|||||||
SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera,
|
SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera,
|
||||||
const Files::PathContainer& dataDirs,
|
const Files::PathContainer& dataDirs,
|
||||||
bool useSound, bool fsstrict, MWWorld::Environment& environment)
|
bool useSound, bool fsstrict, MWWorld::Environment& environment)
|
||||||
: fsStrict(fsstrict)
|
: mFSStrict(fsstrict)
|
||||||
, mEnvironment(environment)
|
, mEnvironment(environment)
|
||||||
, mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY)))
|
, mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY)))
|
||||||
, updater(mgr)
|
, updater(mgr)
|
||||||
, cameraTracker(mgr)
|
, cameraTracker(mgr)
|
||||||
{
|
{
|
||||||
for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
|
|
||||||
{
|
|
||||||
MP3Lookup((*it) / "Music/Explore/");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(useSound)
|
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)
|
for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
|
||||||
{
|
{
|
||||||
soundDirs.push_back( *it / std::string("Sound"));
|
soundDirs.push_back( *it / std::string("Sound"));
|
||||||
}
|
}
|
||||||
soundfiles = soundDirs;
|
for (Files::PathContainer::const_iterator it = soundDirs.begin(); it != soundDirs.end(); ++it)
|
||||||
strict = soundDirs;
|
{
|
||||||
musicpath = dataDirs;
|
Files::FileLister(*it, mSoundFiles, true);
|
||||||
musicpathStrict = dataDirs;
|
}
|
||||||
|
|
||||||
|
// 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 output: " << SOUND_OUT << std::endl;
|
||||||
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
|
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
|
||||||
// Attach the camera to the camera tracker
|
// Attach the camera to the camera tracker
|
||||||
@ -105,103 +113,6 @@ namespace MWSound
|
|||||||
cameraTracker.unfollowCamera();
|
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
|
// Convert a soundId to file name, and modify the volume
|
||||||
// according to the sounds local volume setting, minRange and
|
// according to the sounds local volume setting, minRange and
|
||||||
// maxRange.
|
// maxRange.
|
||||||
@ -229,7 +140,7 @@ namespace MWSound
|
|||||||
max = std::max(min, max);
|
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
|
// Add a sound to the list and play it
|
||||||
@ -376,33 +287,20 @@ namespace MWSound
|
|||||||
|
|
||||||
void SoundManager::streamMusic(const std::string& filename)
|
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()
|
void SoundManager::startRandomTitle()
|
||||||
{
|
{
|
||||||
if(!files.empty())
|
if(!mMusicFiles.empty())
|
||||||
{
|
{
|
||||||
Files::PathContainer::iterator fileIter = files.begin();
|
Files::PathContainer::iterator fileIter = mMusicFiles.begin();
|
||||||
srand( time(NULL) );
|
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::advance(fileIter, r - 1);
|
||||||
std::string music = fileIter->string();
|
std::string music = fileIter->string();
|
||||||
@ -432,8 +330,9 @@ namespace MWSound
|
|||||||
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
|
void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename)
|
||||||
{
|
{
|
||||||
// The range values are not tested
|
// The range values are not tested
|
||||||
if(hasFile(filename))
|
std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict);
|
||||||
add(convertPath(filename), ptr, "_say_sound", 1, 1, 100, 20000, false);
|
if(!filePath.empty())
|
||||||
|
add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false);
|
||||||
else
|
else
|
||||||
std::cout << "Sound file " << filename << " not found, skipping.\n";
|
std::cout << "Sound file " << filename << " not found, skipping.\n";
|
||||||
}
|
}
|
||||||
@ -448,7 +347,7 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
// Play and forget
|
// Play and forget
|
||||||
float min, max;
|
float min, max;
|
||||||
const std::string &file = ookup(soundId, volume, min, max);
|
const std::string &file = lookup(soundId, volume, min, max);
|
||||||
if (file != "")
|
if (file != "")
|
||||||
{
|
{
|
||||||
SoundPtr snd = mgr->load(file);
|
SoundPtr snd = mgr->load(file);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <mangle/sound/clients/ogre_listener_mover.hpp>
|
#include <mangle/sound/clients/ogre_listener_mover.hpp>
|
||||||
|
|
||||||
#include <openengine/sound/sndmanager.hpp>
|
#include <openengine/sound/sndmanager.hpp>
|
||||||
#include <components/files/multidircollection.hpp>
|
#include <components/files/fileops.hpp>
|
||||||
#include <components/file_finder/file_finder.hpp>
|
#include <components/file_finder/file_finder.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
@ -47,8 +47,13 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
class SoundManager
|
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;
|
MWWorld::Environment& mEnvironment;
|
||||||
|
|
||||||
int total;
|
int total;
|
||||||
@ -79,19 +84,10 @@ namespace MWSound
|
|||||||
typedef std::map<MWWorld::Ptr,IDMap> PtrMap;
|
typedef std::map<MWWorld::Ptr,IDMap> PtrMap;
|
||||||
PtrMap sounds;
|
PtrMap sounds;
|
||||||
|
|
||||||
// This is used for case insensitive and slash-type agnostic file
|
Files::PathContainer mSoundFiles;
|
||||||
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
|
|
||||||
// relative to the sound dir, and translates them into full paths
|
Files::PathContainer mMusicFiles;
|
||||||
// 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);
|
|
||||||
std::string lookup(const std::string &soundId,
|
std::string lookup(const std::string &soundId,
|
||||||
float &volume, float &min, float &max);
|
float &volume, float &min, float &max);
|
||||||
void add(const std::string &file,
|
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.
|
/// \param filename name of a sound file in "Music/" in the data directory.
|
||||||
|
|
||||||
void startRandomTitle();
|
void startRandomTitle();
|
||||||
void MP3Lookup(const boost::filesystem::path& dir);
|
|
||||||
|
|
||||||
bool isMusicPlaying();
|
bool isMusicPlaying();
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "fileops.hpp"
|
#include "fileops.hpp"
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
namespace Files
|
namespace Files
|
||||||
{
|
{
|
||||||
@ -9,4 +10,90 @@ bool isFile(const char *name)
|
|||||||
return boost::filesystem::exists(boost::filesystem::path(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
|
#ifndef COMPONENTS_FILES_FILEOPS_HPP
|
||||||
#define COMPONENTS_FILES_FILEOPS_HPP
|
#define COMPONENTS_FILES_FILEOPS_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
namespace Files
|
namespace Files
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -8,6 +14,24 @@ namespace Files
|
|||||||
///\param [in] name - filename
|
///\param [in] name - filename
|
||||||
bool isFile(const char *name);
|
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 */
|
#endif /* COMPONENTS_FILES_FILEOPS_HPP */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user