Added support for reading presentations and content via http, with support of the FileCache when available.

This commit is contained in:
Robert Osfield
2009-05-13 19:48:02 +00:00
parent 59ddcd08f4
commit 3c88e59496
3 changed files with 362 additions and 22 deletions

View File

@@ -1385,6 +1385,306 @@ void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& cons
#include <iostream>
struct MyFindFileCallback : public osgDB::FindFileCallback
{
virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
{
osg::notify(osg::NOTICE)<<std::endl<<std::endl<<"find file "<<filename<<std::endl;
const osgDB::FilePathList& paths = options ? options->getDatabasePathList() : osgDB::getDataFilePathList();
for(osgDB::FilePathList::const_iterator itr = paths.begin();
itr != paths.end();
++itr)
{
const std::string& path = *itr;
std::string newpath = osgDB::concatPaths(path, filename);
if (osgDB::containsServerAddress(path))
{
osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
osg::notify(osg::NOTICE)<<" file on server "<<*itr<<", try path "<<newpath<<std::endl;
osg::notify(osg::NOTICE)<<" we have curl rw= "<<rw<<std::endl;
if (rw && rw->fileExists(newpath, options))
{
osg::notify(osg::NOTICE)<<" FOUND on server "<<newpath<<std::endl;
return newpath;
}
}
else
{
if(osgDB::fileExists(newpath))
{
osg::notify(osg::NOTICE)<<" FOUND "<<newpath<<std::endl;
return newpath;
}
}
}
return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
}
};
class OSGDB_EXPORT MyReadFileCallback : public virtual osgDB::ReadFileCallback
{
public:
osgDB::FilePathList _paths;
typedef std::map< std::string, osg::ref_ptr<osg::Object> > ObjectCache;
enum ObjectType
{
OBJECT,
IMAGE,
HEIGHT_FIELD,
NODE,
SHADER
};
osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options)
{
osg::notify(osg::INFO)<<"Trying local file "<<filename<<std::endl;
switch(type)
{
case(OBJECT): return osgDB::Registry::instance()->readObjectImplementation(filename,options);
case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options);
case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options);
case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options);
}
return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
}
osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options)
{
osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
osg::notify(osg::INFO)<<"Trying fileCache "<<filename<<std::endl;
osgDB::ReaderWriter::ReadResult result;
if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
{
if (fileCache->existsInCache(filename))
{
switch(type)
{
case(OBJECT):
result = fileCache->readObject(filename, 0);
break;
case(IMAGE):
result = fileCache->readImage(filename, 0);
break;
case(HEIGHT_FIELD):
result = fileCache->readHeightField(filename, 0);
break;
case(NODE):
result = fileCache->readNode(filename,0);
break;
case(SHADER):
result = fileCache->readShader(filename, 0);
break;
}
if (result.success())
{
osg::notify(osg::INFO)<<" File read from FileCache."<<std::endl;
return result;
}
osg::notify(osg::NOTICE)<<" File in FileCache, but not successfully read"<<std::endl;
}
else
{
osg::notify(osg::INFO)<<" File does not exist in FileCache: "<<fileCache->createCacheFileName(filename)<<std::endl;
}
}
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
}
osgDB::ReaderWriter::ReadResult readServer(ObjectType type, const std::string& filename, const osgDB::Options* options)
{
osg::notify(osg::INFO)<<"Trying server file "<<filename<<std::endl;
osgDB::ReaderWriter::ReadResult result;
osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
switch(type)
{
case(OBJECT):
result = rw->readObject(filename,options);
break;
case(IMAGE):
result = rw->readImage(filename,options);
break;
case(HEIGHT_FIELD):
result = rw->readHeightField(filename,options);
break;
case(NODE):
result = rw->readNode(filename,options);
break;
case(SHADER):
result = rw->readShader(filename,options);
break;
}
if (result.success())
{
osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
{
switch(type)
{
case(OBJECT):
fileCache->writeObject(*result.getObject(),filename,options);
break;
case(IMAGE):
fileCache->writeImage(*result.getImage(),filename,options);
break;
case(HEIGHT_FIELD):
fileCache->writeHeightField(*result.getHeightField(),filename,options);
break;
case(NODE):
fileCache->writeNode(*result.getNode(),filename,options);
break;
case(SHADER):
fileCache->writeShader(*result.getShader(),filename,options);
break;
}
}
return result;
}
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
}
osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles)
{
// go look in http paths
for(osgDB::FilePathList::const_iterator itr = filePathList.begin();
itr != filePathList.end();
++itr)
{
const std::string& path = *itr;
std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename);
osgDB::ReaderWriter::ReadResult result;
if (osgDB::containsServerAddress(newpath))
{
if (checkLocalFiles) result = readFileCache(type, newpath, options);
else result = readServer(type, newpath, options);
}
else if (checkLocalFiles && osgDB::fileExists(newpath))
{
result = readLocal(type, newpath, options);
}
if (result.success())
{
osg::notify(osg::INFO)<<" inserting object into file cache "<<filename<<", "<<result.getObject()<<std::endl;
_objectCache[filename] = result.getObject();
options->setPluginStringData("filename",newpath);
return result;
}
}
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
}
osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options)
{
osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0;
osg::notify(osg::INFO)<<"reading file "<<filename<<std::endl;
ObjectCache::iterator itr = _objectCache.find(filename);
if (itr != _objectCache.end())
{
// object is in cache, just retrieve it.
if (itr->second.valid())
{
osg::notify(osg::INFO)<<"File retrieved from cache, filename="<<filename<<std::endl;
return itr->second.get();
}
else
{
osg::notify(osg::INFO)<<"File failed to load previously, won't attempt a second time "<<filename<<std::endl;
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
}
}
{
bool checkLocalFiles = true;
osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
if (result.success()) return result;
if (options && !(options->getDatabasePathList().empty()))
{
result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
if (result.success()) return result;
}
result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
if (result.success()) return result;
}
{
bool checkLocalFiles = false;
osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
if (result.success()) return result;
if (options && !(options->getDatabasePathList().empty()))
{
result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
if (result.success()) return result;
}
result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
if (result.success()) return result;
}
_objectCache[filename] = 0;
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
}
virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
{
return read(IMAGE, filename, options);
}
virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options)
{
return read(HEIGHT_FIELD, filename, options);
}
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
{
return read(NODE, filename, options);
}
virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options)
{
return read(SHADER, filename, options);
}
protected:
virtual ~MyReadFileCallback() {}
ObjectCache _objectCache;
};
osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file,
const osgDB::ReaderWriter::Options* options) const
{
@@ -1397,6 +1697,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string&
// code for setting up the database path so that internally referenced file are searched for on relative paths.
osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
//local_opt->setFindFileCallback(new MyFindFileCallback);
local_opt->setReadFileCallback(new MyReadFileCallback);
osgDB::XmlNode::Input input;
input.open(fileName);
@@ -1405,15 +1707,6 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string&
return readNode(input, local_opt);
}
struct MyFindFileCallback : public osgDB::FindFileCallback
{
virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
{
osg::notify(osg::NOTICE)<<"find file "<<filename<<std::endl;
return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
}
};
osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin, const Options* options) const
{
osgDB::XmlNode::Input input;
@@ -1421,7 +1714,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin,
input.readAllDataIntoBuffer();
osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->setFindFileCallback(new MyFindFileCallback);
//local_opt->setFindFileCallback(new MyFindFileCallback);
local_opt->setReadFileCallback(new MyReadFileCallback);
return readNode(input, local_opt);
}
@@ -1440,6 +1734,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
doc->read(input);
osg::notify(osg::NOTICE)<<"P3D parsing"<<std::endl;
// doc->write(std::cout);
if (doc == NULL )
@@ -1473,11 +1769,6 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
bool readSlide = false;
std::string pathToPresentation;
if (options && !(options->getDatabasePathList().empty()))
{
pathToPresentation = options->getDatabasePathList().front();
}
for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
itr != root->children.end();
@@ -1493,6 +1784,17 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
}
}
std::string pathToPresentation;
MyReadFileCallback* readFileCallback = options ? dynamic_cast<MyReadFileCallback*>(options->getReadFileCallback()) : 0;
if (options && !(options->getDatabasePathList().empty()))
{
pathToPresentation = options->getDatabasePathList().front();
if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation);
}
for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
itr != root->children.end();
++itr)
@@ -1510,7 +1812,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
bool relativePath = colonPos == std::string::npos &&
backslashPos != 0 &&
forwardslashPos != 0;
if (relativePath)
if (relativePath && !pathToPresentation.empty())
{
newpath = osgDB::concatPaths(pathToPresentation, newpath);
osg::notify(osg::NOTICE)<<"relative path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
@@ -1519,10 +1822,13 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
{
osg::notify(osg::NOTICE)<<"absolute path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
}
options->getDatabasePathList().push_front(newpath);
if (readFileCallback) readFileCallback->_paths.push_back(newpath);
else options->getDatabasePathList().push_back(newpath);
}
}
for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
itr != root->children.end();
++itr)

View File

@@ -776,7 +776,8 @@ void SlideShowConstructor::addImage(const std::string& filename, const PositionD
if (!_currentLayer) addLayer();
osg::Image* image = osgDB::readImageFile(filename, _options.get());
if (image) recordOptionsFilePath(_options.get());
if (!image) return;
bool isImageTranslucent = false;
@@ -890,7 +891,10 @@ void SlideShowConstructor::addStereoImagePair(const std::string& filenameLeft, c
osg::ref_ptr<osg::Image> imageLeft = osgDB::readImageFile(filenameLeft, _options.get());
if (imageLeft.valid()) recordOptionsFilePath(_options.get());
osg::ref_ptr<osg::Image> imageRight = (filenameRight==filenameLeft) ? imageLeft.get() : osgDB::readImageFile(filenameRight, _options.get());
if (imageRight.valid()) recordOptionsFilePath(_options.get());
if (!imageLeft && !imageRight) return;
@@ -1225,6 +1229,8 @@ std::string SlideShowConstructor::findFileAndRecordPath(const std::string& filen
void SlideShowConstructor::addModel(const std::string& filename, const PositionData& positionData, const ModelData& modelData)
{
osg::notify(osg::NOTICE)<<"SlideShowConstructor::addModel("<<filename<<")"<<std::endl;
osg::Node* subgraph = 0;
if (filename=="sphere")
@@ -1243,15 +1249,16 @@ void SlideShowConstructor::addModel(const std::string& filename, const PositionD
}
else
{
std::string foundFile = findFileAndRecordPath(filename);
if (foundFile.empty()) return;
subgraph = osgDB::readNodeFile(foundFile, _options.get());
subgraph = osgDB::readNodeFile(filename, _options.get());
if (subgraph) recordOptionsFilePath(_options.get());
}
if (!subgraph) return;
addModel(subgraph, positionData, modelData);
osg::notify(osg::NOTICE)<<"end of SlideShowConstructor::addModel("<<filename<<")"<<std::endl<<std::endl;
}
void SlideShowConstructor::addModel(osg::Node* subgraph, const PositionData& positionData, const ModelData& modelData)
@@ -1445,6 +1452,12 @@ void SlideShowConstructor::addVolume(const std::string& filename, const Position
{
image = osgDB::readImageFile( foundFile, _options.get() );
}
else
{
// not found image, so fallback to plguins/callbacks to find the model.
image = osgDB::readImageFile( filename, _options.get() );
if (image) recordOptionsFilePath(_options.get() );
}
if (!image) return;
@@ -1852,3 +1865,22 @@ void SlideShowConstructor::updatePositionFromInModelCoords(const osg::Vec3& vert
positionData.position = vertex;
}
}
void SlideShowConstructor::recordOptionsFilePath(const osgDB::Options* options)
{
if (options)
{
std::string filename_used = _options->getPluginStringData("filename");
std::string path = osgDB::getFilePath(filename_used);
if (!path.empty() && _filePathData.valid())
{
osgDB::FilePathList::iterator itr = std::find(_filePathData->filePathList.begin(),_filePathData->filePathList.end(),path);
if (itr==_filePathData->filePathList.end())
{
osg::notify(osg::INFO)<<"SlideShowConstructor::recordOptionsFilePath(..) - new path to record path="<<path<<" filename_used="<<filename_used<<std::endl;
_filePathData->filePathList.push_front(path);
}
}
}
}

View File

@@ -413,6 +413,8 @@ protected:
std::string findFileAndRecordPath(const std::string& filename);
void recordOptionsFilePath(const osgDB::Options* options);
};
}