root/OpenSceneGraph/trunk/src/osgDB/Registry.cpp @ 10356

Revision 10356, 72.1 kB (checked in by robert, 6 years ago)

Added ".added", ".modified" and ".removed" alias to .revisions plugin

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[1529]2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
[8]13
[7994]14#include <stdio.h>
15#include <string.h>
16
[120]17#include <osg/Notify>
18#include <osg/Object>
19#include <osg/Image>
[7908]20#include <osg/Shader>
[120]21#include <osg/Node>
22#include <osg/Group>
23#include <osg/Geode>
[1610]24#include <osg/ApplicationUsage>
[7216]25#include <osg/Version>
[9024]26#include <osg/Timer>
[8]27
[120]28#include <osgDB/Registry>
29#include <osgDB/FileUtils>
30#include <osgDB/FileNameUtils>
[9124]31#include <osgDB/fstream>
[3580]32#include <osgDB/Archive>
[8]33
34#include <algorithm>
35#include <set>
36
[9475]37#include <stdlib.h>
38
[7243]39#if defined(__sgi)
40    #include <ctype.h>
41#elif defined(__GNUC__) || !defined(WIN32) || defined(__MWERKS__)
42    #include <cctype>
43    using std::tolower;
44#endif
45
[8913]46#ifdef OSG_DEBUG_POSTFIX
47    #define OSG_DEBUG_POSTFIX_WITH_QUOTES ADDQUOTES(OSG_DEBUG_POSTFIX)
48#else
49    #define OSG_DEBUG_POSTFIX_WITH_QUOTES "d"
[8375]50#endif
[7243]51
[8]52using namespace osg;
53using namespace osgDB;
54
[7544]55#if !defined(WIN32) || defined(__CYGWIN__)
56static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[:path]..","Paths for locating datafiles");
57static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[:path]..","Paths for locating libraries/ plugins");
58#else
59static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
60static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[;path]..","Paths for locating libraries/ plugins");
61#endif
62
[8541]63static osg::ApplicationUsageProxy Registry_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_BUILD_KDTREES on/off","Enable/disable the automatic building of KdTrees for each loaded Geometry.");
[7544]64
[8541]65
[10000]66// from MimeTypes.cpp
67extern const char* builtinMimeTypeExtMappings[];
68
69
[3598]70class Registry::AvailableReaderWriterIterator
[2522]71{
72public:
[8929]73    AvailableReaderWriterIterator(Registry::ReaderWriterList& rwList, OpenThreads::ReentrantMutex& pluginMutex):
74        _rwList(rwList),
75        _pluginMutex(pluginMutex) {}
[2522]76
77
78    ReaderWriter& operator * () { return *get(); }
79    ReaderWriter* operator -> () { return get(); }
80   
81    bool valid() { return get()!=0; }
82   
83    void operator ++()
84    {
85        _rwUsed.insert(get());
86    }
87   
88
89protected:
90
[9460]91    AvailableReaderWriterIterator& operator = (const AvailableReaderWriterIterator&) { return *this; }
92
[2522]93    Registry::ReaderWriterList&     _rwList;
[8929]94    OpenThreads::ReentrantMutex&    _pluginMutex;
95   
[2522]96    std::set<ReaderWriter*>         _rwUsed;
97
98    ReaderWriter* get()
99    {
[8929]100        OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[2522]101        Registry::ReaderWriterList::iterator itr=_rwList.begin();
102        for(;itr!=_rwList.end();++itr)
103        {
104            if (_rwUsed.find(itr->get())==_rwUsed.end())
105            {
106                return itr->get();
107            }
108        }
109        return 0;
110    }
111
112};
113
[2007]114#if 0
115    // temporary test of autoregistering, not compiled by default.
116    enum Methods
117    {
118        SET_1,
119        SET_2,
120        END
121    };
122
123
124    typedef std::pair<Methods,std::string> MethodPair;
125
126    class Proxy
127    {
128    public:
129        Proxy(MethodPair* methods)
130        {
131            std::cout<<"methods "<<methods<<std::endl;
132            for(int i=0;methods[i].first!=END;++i)
133            {
134                std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
135            }
136        }
137    };
138
139
140    static MethodPair methods[] =
141    {
142        MethodPair(SET_1,"SET_1"),
143        MethodPair(SET_2,"SET_2"),
144        MethodPair(END,"")
145    };
146
147    Proxy myproxy(methods);
148
149#endif
150
[775]151void PrintFilePathList(std::ostream& stream,const FilePathList& filepath)
[773]152{
153    for(FilePathList::const_iterator itr=filepath.begin();
154        itr!=filepath.end();
155        ++itr)
156    {
157        stream << "    "<< *itr<<std::endl;
158    }
159}
[8]160
[2534]161Registry* Registry::instance(bool erase)
[434]162{
[4881]163    static ref_ptr<Registry> s_registry = new Registry;
[2534]164    if (erase)
[6881]165    {   
166        s_registry->destruct();
[4881]167        s_registry = 0;
[2534]168    }
[4881]169    return s_registry.get(); // will return NULL on erase
[434]170}
171
172
[8]173// definition of the Registry
174Registry::Registry()
175{
[7648]176    // comment out because it was causing problems under OSX - causing it to crash osgconv when constructing ostream in osg::notify().
[1983]177    // notify(INFO) << "Constructing osg::Registry"<<std::endl;
[8]178
[10171]179    _buildKdTreesHint = Options::NO_PREFERENCE;
[8535]180    _kdTreeBuilder = new osg::KdTreeBuilder;
181   
182    const char* kdtree_str = getenv("OSG_BUILD_KDTREES");
183    if (kdtree_str)
184    {
185        bool switchOff = (strcmp(kdtree_str, "off")==0 || strcmp(kdtree_str, "OFF")==0 || strcmp(kdtree_str, "Off")==0 );
[10171]186        if (switchOff) _buildKdTreesHint = Options::DO_NOT_BUILD_KDTREES;
187        else _buildKdTreesHint = Options::BUILD_KDTREES;
[8535]188    }
189
[9038]190    const char* fileCachePath = getenv("OSG_FILE_CACHE");
191    if (fileCachePath)
192    {
193        _fileCache = new FileCache(fileCachePath);   
194    }
195
[2408]196    _createNodeFromImage = false;
[8]197    _openingLibrary = false;
[6628]198
199    // add default osga archive extension
200    _archiveExtList.push_back("osga");
[2340]201   
[773]202    initFilePathLists();
[8]203
[8535]204
205
[8]206    // register file extension alias.
[5038]207    const char* flt_str = getenv("OSG_OPEN_FLIGHT_PLUGIN");
208    if (flt_str)
209    {
210        if (strcmp(flt_str, "new")==0)
211        {
212            addFileExtensionAlias("flt", "OpenFlight");
213        }
214    }
[5196]215    else
216    {
217    #ifndef COMPILE_WITH_OLD_OPENFLIGHT_PLUGIN_AS_DEFAULT
218        addFileExtensionAlias("flt", "OpenFlight");
219    #endif
220    }
[5038]221
[7292]222    addFileExtensionAlias("osgs", "osg");
[6212]223    addFileExtensionAlias("shadow""osgShadow");
[7215]224    addFileExtensionAlias("terrain", "osgTerrain");
[6275]225    addFileExtensionAlias("view""osgViewer");
226
[919]227    addFileExtensionAlias("sgi""rgb");
[8]228    addFileExtensionAlias("rgba", "rgb");
229    addFileExtensionAlias("int""rgb");
230    addFileExtensionAlias("inta", "rgb");
231    addFileExtensionAlias("bw",   "rgb");
[2387]232
233    addFileExtensionAlias("ivz",   "gz");
234    addFileExtensionAlias("ozg",   "gz");
[8]235   
[8964]236    addFileExtensionAlias("mag",   "dicom");
237    addFileExtensionAlias("ph",   "dicom");
238    addFileExtensionAlias("ima",   "dicom");
[8782]239    addFileExtensionAlias("dcm",   "dicom");
240    addFileExtensionAlias("dic",   "dicom");
241
[8935]242    addFileExtensionAlias("gl",   "glsl");
243    addFileExtensionAlias("vert",   "glsl");
244    addFileExtensionAlias("frag",   "glsl");
245
[9880]246
247#if defined(DARWIN_IMAGEIO)
248    addFileExtensionAlias("jpg""imageio");
249    addFileExtensionAlias("jpe""imageio");
250    addFileExtensionAlias("jpeg", "imageio");
251    addFileExtensionAlias("tif""imageio");
252    addFileExtensionAlias("tiff", "imageio");
253    addFileExtensionAlias("gif""imageio");
254    addFileExtensionAlias("png""imageio");
255    addFileExtensionAlias("psd""imageio");
256    addFileExtensionAlias("tga""imageio");
257#endif
258
[2718]259#if defined(DARWIN_QUICKTIME)
[1632]260    addFileExtensionAlias("jpg""qt");
261    addFileExtensionAlias("jpe""qt");
262    addFileExtensionAlias("jpeg", "qt");
263    addFileExtensionAlias("tif""qt");
264    addFileExtensionAlias("tiff", "qt");
[1696]265    addFileExtensionAlias("gif""qt");
266    addFileExtensionAlias("png""qt");
[4002]267    addFileExtensionAlias("psd""qt");
268    addFileExtensionAlias("tga""qt");
[2815]269    addFileExtensionAlias("mov""qt");
[3869]270    addFileExtensionAlias("avi""qt");
[2815]271    addFileExtensionAlias("mpg""qt");
[7572]272    addFileExtensionAlias("flv""qt");
[2815]273    addFileExtensionAlias("mpv""qt");
274    addFileExtensionAlias("dv",   "qt");
[8213]275    addFileExtensionAlias("mp4""qt");
276    addFileExtensionAlias("m4v""qt");
[8932]277    addFileExtensionAlias("3gp""qt");
[8213]278    // Add QuickTime live support for OSX
279    addFileExtensionAlias("live", "qt");
[1632]280#else
[8]281    addFileExtensionAlias("jpg""jpeg");
282    addFileExtensionAlias("jpe""jpeg");
283    addFileExtensionAlias("tif""tiff");
[3869]284
285    // really need to decide this at runtime...
286    #if defined(USE_XINE)
287        addFileExtensionAlias("mov""xine");
288        addFileExtensionAlias("mpg""xine");
[8828]289        addFileExtensionAlias("ogv""xine");
[3869]290        addFileExtensionAlias("mpv""xine");
291        addFileExtensionAlias("dv",   "xine");
292        addFileExtensionAlias("avi""xine");
[4076]293        addFileExtensionAlias("wmv""xine");
[7572]294        addFileExtensionAlias("flv""xine");
[3869]295    #endif
296
[8213]297    // support QuickTime for Windows
298    #if defined(USE_QUICKTIME)
299        addFileExtensionAlias("mov", "qt");
300        addFileExtensionAlias("live", "qt");
[8466]301        addFileExtensionAlias("mpg", "qt");
302        addFileExtensionAlias("avi", "qt");
[8213]303    #endif
[2815]304#endif
[2798]305
[1244]306    // remove geo to lwo alias as the new Carbon Graphics GEO format
307    // also uses the .geo. It is still possible to load light wave .geo
308    // files via loading the lwo plugin explicitly and then doing a readNodeFile.
309    //addFileExtensionAlias("geo",  "lwo");
[8]310    addFileExtensionAlias("lw",   "lwo");
[773]311
[6541]312    #if defined(USE_VRML)
313        addFileExtensionAlias("wrl",   "vrml");   
314    #elif defined(USE_INVENTOR)
315        addFileExtensionAlias("wrl",   "iv");
316    #endif
[1629]317   
318    // add alias for the text/freetype plugin.
319    addFileExtensionAlias("ttf",   "freetype");  // true type
320    addFileExtensionAlias("ttc",   "freetype");  // true type
321    addFileExtensionAlias("cid",   "freetype");  // Postscript CID-Fonts
322    addFileExtensionAlias("cff",   "freetype");  // OpenType
323    addFileExtensionAlias("cef",   "freetype");  // OpenType
324    addFileExtensionAlias("fon",   "freetype");  // Windows bitmap fonts
[9881]325    addFileExtensionAlias("fnt",   "freetype");  // Windows bitmap fonts
326    addFileExtensionAlias("text3d", "freetype"); // use 3D Font instead of 2D Font
327
[7648]328    // wont't add type1 and type2 until resolve extension collision with Performer binary and ascii files.
[1629]329    // addFileExtensionAlias("pfb",   "freetype");  // type1 binary
330    // addFileExtensionAlias("pfa",   "freetype");  // type2 ascii
[1930]331
332
333    // portable bitmap, greyscale and colour/pixmap image formats
334    addFileExtensionAlias("pbm", "pnm");
335    addFileExtensionAlias("pgm", "pnm");
336    addFileExtensionAlias("ppm", "pnm");
[2340]337   
[10356]338
339    // add revision file mappings
340    addFileExtensionAlias("added", "revisions");
341    addFileExtensionAlias("removed", "revisions");
342    addFileExtensionAlias("modified", "revisions");
343
344
345
346
[10000]347    // add built-in mime-type extension mappings
348    for( int i=0; ; i+=2 )
349    {
350        std::string mimeType = builtinMimeTypeExtMappings[i];
351        if ( mimeType.length() == 0 )
352            break;
353        addMimeTypeExtensionMapping( mimeType, builtinMimeTypeExtMappings[i+1] );
354    }
355   
[9884]356    // register http-protocol, so the curl can handle it, if necessary
357    registerProtocol("http");
[8]358}
359
360
361Registry::~Registry()
362{
[6881]363    destruct();
364}
365
366void Registry::destruct()
367{
[8325]368    // osg::notify(osg::NOTICE)<<"Registry::destruct()"<<std::endl;
369
[2631]370    // clean up the SharedStateManager
371    _sharedStateManager = 0;
372   
[3384]373
[9038]374    // clean up the FileCache
375    _fileCache = 0;
376   
377
[2631]378    // object cache clear needed here to prevent crash in unref() of
379    // the objects it contains when running the TXP plugin.
380    // Not sure why, but perhaps there is is something in a TXP plugin
[7648]381    // which deletes the data before its ref count hits zero, perhaps
[2631]382    // even some issue with objects be allocated by a plugin that is
[7648]383    // maintained after that plugin is deleted...  Robert Osfield, Jan 2004.
[3384]384    clearObjectCache();
[3598]385    clearArchiveCache();
386   
[2631]387
[2614]388    // unload all the plugin before we finally destruct.
[2534]389    closeAllLibraries();
[8]390}
391
[4420]392#include <iostream>
[4002]393
[773]394void Registry::initDataFilePathList()
395{
[4419]396    FilePathList filepath;
397    //
398    // set up data file paths
399    //
400    char *ptr;
[4007]401 
[4419]402    if( (ptr = getenv( "OSG_FILE_PATH" )) )
403    {
404        //notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
405        convertStringPathIntoFilePathList(ptr, filepath);
406    }
407    else if( (ptr = getenv( "OSGFILEPATH" )) )
408    {
409        //notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
410        convertStringPathIntoFilePathList(ptr, filepath);
411    }
[4002]412
[4420]413    osgDB::appendPlatformSpecificResourceFilePaths(filepath);
[4419]414    setDataFilePathList(filepath);
[4420]415   
[4002]416}
417
[3330]418void Registry::setDataFilePathList(const std::string& paths)
419{
420    _dataFilePath.clear();
421    convertStringPathIntoFilePathList(paths,_dataFilePath);
422}
423
424void Registry::setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); }
425
[1610]426
[3330]427
[773]428void Registry::initLibraryFilePathList()
429{
430    //
431    // set up library paths
432    //
433    char* ptr;
434    if( (ptr = getenv( "OSG_LIBRARY_PATH")) )
435    {
[1983]436        //notify(DEBUG_INFO) << "OSG_LIBRARY_PATH("<<ptr<<")"<<std::endl;
[773]437        setLibraryFilePathList(ptr);
438    }
439    else if( (ptr = getenv( "OSG_LD_LIBRARY_PATH")) )
440    {
[1983]441        //notify(DEBUG_INFO) << "OSG_LD_LIBRARY_PATH("<<ptr<<")"<<std::endl;
[773]442        setLibraryFilePathList(ptr);
443    }
444   
[3330]445    appendPlatformSpecificLibraryFilePaths(_libraryFilePath);
[773]446
447}
448
[3330]449
[1613]450void Registry::readCommandLine(osg::ArgumentParser& arguments)
[1610]451{
[1613]452    // report the usage options.
453    if (arguments.getApplicationUsage())
454    {
455        arguments.getApplicationUsage()->addCommandLineOption("-l <library>","Load the plugin");
456        arguments.getApplicationUsage()->addCommandLineOption("-e <extension>","Load the plugin associated with handling files with specified extension");
457        arguments.getApplicationUsage()->addCommandLineOption("-O <option_string>","Provide an option string to reader/writers used to load databases");
458    }
[1610]459
460    std::string value;
[1613]461    while(arguments.read("-l",value))
[1610]462    {
463        loadLibrary(value);
464    }
465       
[1613]466    while(arguments.read("-e",value))
[1610]467    {
[2016]468        std::string libName = createLibraryNameForExtension(value);
[1610]469        loadLibrary(libName);
470    }
471
[1613]472    while(arguments.read("-O",value))
[1610]473    {
[10171]474        setOptions(new Options(value));
[1610]475    }
476}
477
[8]478void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper)
479{
480    if (wrapper==0L) return;
481
[2268]482    //notify(INFO) << "osg::Registry::addDotOsgWrapper("<<wrapper->getName()<<")"<< std::endl;
[8]483    const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
484   
485    for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin();
486                                                  itr!=assoc.end();
487                                                  ++itr)
488    {
[2268]489        //notify(INFO) << "    ("<<*itr<<")"<< std::endl;
[8]490    }
491
492    const std::string& name = wrapper->getName();
493    const osg::Object* proto = wrapper->getPrototype();
494
495    _objectWrapperMap[name] = wrapper;
[2501]496    if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[name] = wrapper;
[2174]497   
[8]498    if (proto)
499    {
[742]500        std::string libraryName = proto->libraryName();
501        std::string compositeName = libraryName + "::" + name;
502
[743]503        _objectWrapperMap[compositeName] = wrapper;
[2238]504        if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[compositeName] = wrapper;
[743]505
[742]506        if (dynamic_cast<const Image*>(proto))
507        {
508            _imageWrapperMap[name] = wrapper;
509            _imageWrapperMap[compositeName] = wrapper;
510        }
511        if (dynamic_cast<const Drawable*>(proto))
512        {
513              _drawableWrapperMap[name] = wrapper;
514              _drawableWrapperMap[compositeName] = wrapper;
515        }
516        if (dynamic_cast<const StateAttribute*>(proto))
517        {
518            _stateAttrWrapperMap[name] = wrapper;
519            _stateAttrWrapperMap[compositeName] = wrapper;
520        }
[4061]521        if (dynamic_cast<const Uniform*>(proto))
522        {
523            _uniformWrapperMap[name] = wrapper;
524            _uniformWrapperMap[compositeName] = wrapper;
525        }
[742]526        if (dynamic_cast<const Node*>(proto))
527        {
528            _nodeWrapperMap[name] = wrapper;
529            _nodeWrapperMap[compositeName] = wrapper;
530        }
[7908]531        if (dynamic_cast<const Shader*>(proto))
532        {
533            _shaderWrapperMap[name] = wrapper;
534            _shaderWrapperMap[compositeName] = wrapper;
535        }
[742]536
537
[8]538    }
539}
540
[742]541// need to change to delete all instances of wrapper, since we
542// now can have a wrapper entered twice with the addition of the
543// library::class composite name.
544void Registry::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper)
545{
546    typedef std::vector<DotOsgWrapperMap::iterator> EraseList;
547    EraseList eraseList;
548    for(DotOsgWrapperMap::iterator witr=wrappermap.begin();
549        witr!=wrappermap.end();
550        ++witr)
551    {
552        if (witr->second==wrapper) eraseList.push_back(witr);
553    }
554    for(EraseList::iterator eitr=eraseList.begin();
555        eitr!=eraseList.end();
556        ++eitr)
557    {
558        wrappermap.erase(*eitr);
559    }
[8]560}
[742]561
[8]562void Registry::removeDotOsgWrapper(DotOsgWrapper* wrapper)
563{
564    if (wrapper==0L) return;
565
[742]566    eraseWrapper(_objectWrapperMap,wrapper);
567    eraseWrapper(_classNameWrapperMap,wrapper);
568    eraseWrapper(_imageWrapperMap,wrapper);
569    eraseWrapper(_drawableWrapperMap,wrapper);
[4061]570    eraseWrapper(_uniformWrapperMap,wrapper);
[742]571    eraseWrapper(_stateAttrWrapperMap,wrapper);
572    eraseWrapper(_nodeWrapperMap,wrapper);
[7908]573    eraseWrapper(_shaderWrapperMap,wrapper);
[8]574}
575
576void Registry::addReaderWriter(ReaderWriter* rw)
577{
578    if (rw==0L) return;
579
[2268]580    // notify(INFO) << "osg::Registry::addReaderWriter("<<rw->className()<<")"<< std::endl;
[8]581
[8929]582    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
583
[8]584    _rwList.push_back(rw);
585
586}
587
588
589void Registry::removeReaderWriter(ReaderWriter* rw)
590{
591    if (rw==0L) return;
592
[211]593//    notify(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl;
[8]594
[8929]595    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
596
[8]597    ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw);
598    if (rwitr!=_rwList.end())
599    {
600        _rwList.erase(rwitr);
601    }
602
603}
604
605
606void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt)
607{
[4948]608    _extAliasMap[mapExt] = toExt;
[8]609}
610
[10000]611void Registry::addMimeTypeExtensionMapping(const std::string fromMimeType, const std::string toExt)
612{
613    _mimeTypeExtMap[fromMimeType] = toExt;
614}
615
[6089]616bool Registry::readPluginAliasConfigurationFile( const std::string& file )
617{
618    std::string fileName = osgDB::findDataFile( file );
619    if (fileName.empty())
620    {
621        osg::notify( osg::WARN) << "Can't find plugin alias config file \"" << file << "\"." << std::endl;
622        return false;
623    }
624
[9124]625    osgDB::ifstream ifs;
[6089]626    ifs.open( fileName.c_str() );
627    if (!ifs.good())
628    {
629        osg::notify( osg::WARN) << "Can't open plugin alias config file \"" << fileName << "\"." << std::endl;
630        return false;
631    }
632
633    int lineNum( 0 );
634    while (ifs.good())
635    {
636        std::string raw;
637        ++lineNum;
638        std::getline( ifs, raw );
639        std::string ln = trim( raw );
640        if (ln.empty()) continue;
641        if (ln[0] == '#') continue;
642
643        std::string::size_type spIdx = ln.find_first_of( " \t" );
644        if (spIdx == ln.npos)
645        {
646            // mapExt and toExt must be on the same line, separated by a space.
647            osg::notify( osg::WARN) << file << ", line " << lineNum << ": Syntax error: missing space in \"" << raw << "\"." << std::endl;
648            continue;
649        }
650
651        const std::string mapExt = trim( ln.substr( 0, spIdx ) );
652        const std::string toExt = trim( ln.substr( spIdx+1 ) );
653        addFileExtensionAlias( mapExt, toExt );
654    }
655    return true;
656}
657
658std::string Registry::trim( const std::string& str )
659{
660    if (!str.size()) return str;
661    std::string::size_type first = str.find_first_not_of( " \t" );
662    std::string::size_type last = str.find_last_not_of( "  \t\r\n" );
663    if ((first==str.npos) || (last==str.npos)) return std::string( "" );
664    return str.substr( first, last-first+1 );
665}
666
667
[8]668std::string Registry::createLibraryNameForFile(const std::string& fileName)
669{
[7243]670    return createLibraryNameForExtension(getFileExtension(fileName));
[8]671}
672
[2016]673std::string Registry::createLibraryNameForExtension(const std::string& ext)
[8]674{
[7243]675    std::string lowercase_ext;
[7459]676    for(std::string::const_iterator sitr=ext.begin();
677        sitr!=ext.end();
678        ++sitr)
[7243]679    {
[7459]680        lowercase_ext.push_back(tolower(*sitr));
[7243]681    }
[8]682
[7243]683    ExtensionAliasMap::iterator itr=_extAliasMap.find(lowercase_ext);
[5035]684    if (itr!=_extAliasMap.end() && ext != itr->second) return createLibraryNameForExtension(itr->second);
[8]685
[10150]686#if defined(OSG_JAVA_BUILD)
[7216]687    static std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/java");
[3767]688#else
[7216]689    static std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/");
[3767]690#endif
691
[7544]692#if defined(__CYGWIN__)
[8875]693    #ifdef _DEBUG
[8913]694        return prepend+"cygwin_"+"osgdb_"+lowercase_ext+OSG_DEBUG_POSTFIX_WITH_QUOTES+".dll";
[8875]695    #else
696        return prepend+"cygwin_"+"osgdb_"+lowercase_ext+".dll";
697    #endif
[7544]698#elif defined(__MINGW32__)
699    return prepend+"mingw_"+"osgdb_"+lowercase_ext+".dll";
700#elif defined(WIN32)
701    #ifdef _DEBUG
[8913]702        return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES +".dll";
[796]703    #else
[7544]704        return prepend+"osgdb_"+lowercase_ext+".dll";
[796]705    #endif
706#elif macintosh
[9954]707    #ifdef _DEBUG
708        return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES;
709    #else
710        return prepend+"osgdb_"+lowercase_ext;
711    #endif
[959]712#elif defined(__hpux__)
713    // why don't we use PLUGIN_EXT from the makefiles here?
[7243]714    return prepend+"osgdb_"+lowercase_ext+".sl";
[796]715#else
[8375]716    #ifdef _DEBUG
[8913]717         return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES + ".so";
[8375]718    #else
719         return prepend+"osgdb_"+lowercase_ext+".so";
720    #endif
[796]721#endif
[8]722
723}
724
[742]725std::string Registry::createLibraryNameForNodeKit(const std::string& name)
726{
[7544]727#if defined(__CYGWIN__)
[2501]728    return "cyg"+name+".dll";
[7544]729#elif defined(__MINGW32__)
730    return "lib"+name+".dll";
731#elif defined(WIN32)
732    #ifdef _DEBUG
[8913]733        return name+OSG_DEBUG_POSTFIX_WITH_QUOTES +".dll";
[796]734    #else
[7548]735        return name+".dll";
[796]736    #endif
737#elif macintosh
[9954]738    #ifdef _DEBUG
739        return name+OSGDEBUG_POSTFIX_WITH_QUOTES;
740    #else
741        return name;
742    #endif
[959]743#elif defined(__hpux__)
744    // why don't we use PLUGIN_EXT from the makefiles here?
745    return "lib"+name+".sl";
[796]746#else
[8375]747    #ifdef _DEBUG
[8913]748        return "lib"+name+OSG_DEBUG_POSTFIX_WITH_QUOTES +".so";
[8375]749    #else
750        return "lib"+name+".so";
751    #endif
[796]752#endif
[742]753}
[8]754
[8947]755Registry::LoadStatus Registry::loadLibrary(const std::string& fileName)
[8]756{
[8929]757    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[8]758
[8929]759    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
[8947]760    if (ditr!=_dlList.end()) return PREVIOUSLY_LOADED;
[8929]761
[8]762    _openingLibrary=true;
763
[8929]764    DynamicLibrary* dl = DynamicLibrary::loadLibrary(fileName);
[8]765    _openingLibrary=false;
766
767    if (dl)
768    {
769        _dlList.push_back(dl);
[8947]770        return LOADED;
[8]771    }
[8947]772    return NOT_LOADED;
[8]773}
774
775
776bool Registry::closeLibrary(const std::string& fileName)
777{
[8929]778    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[8]779    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
780    if (ditr!=_dlList.end())
781    {
782        _dlList.erase(ditr);
783        return true;
784    }
785    return false;
786}
787
[2534]788void Registry::closeAllLibraries()
789{
[8325]790    // osg::notify(osg::NOTICE)<<"Registry::closeAllLibraries()"<<std::endl;
[8929]791    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[2534]792    _dlList.clear();
793}
[8]794
795Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName)
796{
797    DynamicLibraryList::iterator ditr = _dlList.begin();
798    for(;ditr!=_dlList.end();++ditr)
799    {
800        if ((*ditr)->getName()==fileName) return ditr;
801    }
802    return _dlList.end();
803}
804
805DynamicLibrary* Registry::getLibrary(const std::string& fileName)
806{
[8929]807    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[8]808    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
809    if (ditr!=_dlList.end()) return ditr->get();
810    else return NULL;
811}
812
[2016]813ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext)
814{
815    // record the existing reader writer.
816    std::set<ReaderWriter*> rwOriginal;
817
[8929]818    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
819
[2016]820    // first attemt one of the installed loaders
821    for(ReaderWriterList::iterator itr=_rwList.begin();
822        itr!=_rwList.end();
823        ++itr)
824    {
825        rwOriginal.insert(itr->get());
826        if((*itr)->acceptsExtension(ext)) return (*itr).get();
827    }
[8929]828   
[2016]829    // now look for a plug-in to load the file.
830    std::string libraryName = createLibraryNameForExtension(ext);
831    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
[8947]832    if (loadLibrary(libraryName)==LOADED)
[2016]833    {
834        for(ReaderWriterList::iterator itr=_rwList.begin();
835            itr!=_rwList.end();
836            ++itr)
837        {
838            if (rwOriginal.find(itr->get())==rwOriginal.end())
[8955]839            {
840                if((*itr)->acceptsExtension(ext)) return (*itr).get();
841            }
[2016]842        }
843    }
844
845    return NULL;
846
847}
848
[10000]849ReaderWriter* Registry::getReaderWriterForMimeType(const std::string& mimeType)
850{
851    MimeTypeExtensionMap::const_iterator i = _mimeTypeExtMap.find( mimeType );
852    return i != _mimeTypeExtMap.end()?
853        getReaderWriterForExtension( i->second ) :
854        NULL;
855}
856
[2123]857struct concrete_wrapper: basic_type_wrapper
858{
[4461]859    virtual ~concrete_wrapper() {}
[2501]860    concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {}
861    bool matches(const osg::Object *proto) const
862    {
863        return myobj_->isSameKindAs(proto);
864    }
865    const osg::Object *myobj_;
[2123]866};
[2016]867
[8]868osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr)
869{
[2501]870    return readObjectOfType(concrete_wrapper(&compObj), fr);
[2057]871}
872
873osg::Object* Registry::readObjectOfType(const basic_type_wrapper &btw,Input& fr)
874{
[8]875    const char *str = fr[0].getStr();
876    if (str==NULL) return NULL;
877
878    if (fr[0].matchWord("Use"))
879    {
880        if (fr[1].isString())
881        {
882            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
[2057]883            if (obj && btw.matches(obj))
[715]884            {
885                fr+=2;
886                return obj;
887            }
[8]888        }
889        else return NULL;
890
891    }
892
893    std::string name = str;
894    DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name);
[742]895    if (itr==_objectWrapperMap.end())
[8]896    {
[742]897        // not found so check if a library::class composite name.
898        std::string token = fr[0].getStr();
899        std::string::size_type posDoubleColon = token.rfind("::");
900        if (posDoubleColon != std::string::npos)
901        {
902            // we have a composite name so now strip off the library name
903            // are try to load it, and then retry the readObject to see
[7648]904            // if we can recognize the objects.
[742]905            std::string libraryName = std::string(token,0,posDoubleColon);
906
907            // first try the standard nodekit library.
908            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]909            if (loadLibrary(nodeKitLibraryName)==LOADED) return readObjectOfType(btw,fr);
[742]910           
911            // otherwise try the osgdb_ plugin library.
[2016]912            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]913            if (loadLibrary(pluginLibraryName)==LOADED) return readObjectOfType(btw,fr);
[742]914        }
915    }
916    else if (fr[1].isOpenBracket())
917    {
[8]918        DotOsgWrapper* wrapper = itr->second.get();
919        const osg::Object* proto = wrapper->getPrototype();
920        if (proto==NULL)
921        {
[211]922            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
[8]923            return NULL;
924        }
925       
[2057]926        if (!btw.matches(proto))
[8]927        {
928            return NULL;
929        }
930
931        // record the number of nested brackets move the input iterator
932        // over the name { tokens.
933        int entry = fr[0].getNoNestedBrackets();
934        fr+=2;
935
936        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
[327]937        osg::Object* obj = proto->cloneType();
[8]938
939        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
940        {
941            bool iteratorAdvanced = false;
942            if (fr[0].matchWord("UniqueID") && fr[1].isString())
943            {
[7038]944                fr.registerUniqueIDForObject(fr[1].getStr(),obj);
[8]945                fr += 2;
946                iteratorAdvanced = true;
947            }
948
949            // read the local data by iterating through the associate
950            // list, mapping the associate names to DotOsgWrapper's which
951            // in turn have the appropriate functions.
952            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
953                                                          aitr!=assoc.end();
954                                                          ++aitr)
955            {
956                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
[2174]957                if (mitr==_objectWrapperMap.end())
958                {
959                    // not found so check if a library::class composite name.
960                    std::string token = *aitr;
961                    std::string::size_type posDoubleColon = token.rfind("::");
962                    if (posDoubleColon != std::string::npos)
963                    {
964                        // we have a composite name so now strip off the library name
[8955]965                        // and try to load it, and then retry the find to see
[7648]966                        // if we can recognize the objects.
[2174]967                        std::string libraryName = std::string(token,0,posDoubleColon);
968
969                        // first try the standard nodekit library.
970                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8955]971                        if (loadLibrary(nodeKitLibraryName)==LOADED)
[2174]972                        {
973                            mitr = _objectWrapperMap.find(*aitr);
[8955]974                            if (mitr==_objectWrapperMap.end())
[2174]975                            {
[8955]976                                // otherwise try the osgdb_ plugin library.
977                                std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
978                                if (loadLibrary(pluginLibraryName)==LOADED)
979                                {
980                                    mitr = _objectWrapperMap.find(*aitr);
981                                }
[2174]982                            }
983                        }
984                    }
985                }
986
[8]987                if (mitr!=_objectWrapperMap.end())
988                {
989                    // get the function to read the data...
990                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
991                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
992                }
993
994            }
995
[741]996            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
[8]997        }
998        ++fr;                        // step over trailing '}'
999       
1000        return obj;
1001       
1002    }
1003    return 0L;
1004}
1005
1006//
1007// read object from input iterator.
1008//
1009osg::Object* Registry::readObject(DotOsgWrapperMap& dowMap,Input& fr)
1010{
1011    const char *str = fr[0].getStr();
1012    if (str==NULL) return NULL;
1013
1014    std::string name = str;
1015    DotOsgWrapperMap::iterator itr = dowMap.find(name);
[742]1016    if (itr==dowMap.end())
[8]1017    {
[742]1018        // not found so check if a library::class composite name.
1019        std::string token = fr[0].getStr();
1020        std::string::size_type posDoubleColon = token.rfind("::");
1021        if (posDoubleColon != std::string::npos)
1022        {
1023            // we have a composite name so now strip off the library name
1024            // are try to load it, and then retry the readObject to see
[7648]1025            // if we can recognize the objects.
[742]1026       
1027            std::string libraryName = std::string(token,0,posDoubleColon);
1028
1029            // first try the standard nodekit library.
1030            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1031            if (loadLibrary(nodeKitLibraryName)==LOADED) return readObject(dowMap,fr);
[742]1032           
1033            // otherwise try the osgdb_ plugin library.
[2016]1034            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1035            if (loadLibrary(pluginLibraryName)==LOADED) return readObject(dowMap,fr);
[742]1036        }
1037    }
1038    else if (fr[1].isOpenBracket())
1039    {
[8]1040   
1041        DotOsgWrapper* wrapper = itr->second.get();
1042        const osg::Object* proto = wrapper->getPrototype();
1043        if (proto==NULL)
1044        {
[211]1045            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
[8]1046            return NULL;
1047        }
1048
1049        // record the number of nested brackets move the input iterator
1050        // over the name { tokens.
1051        int entry = fr[0].getNoNestedBrackets();
1052        fr+=2;
1053
1054        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
[327]1055        osg::Object* obj = proto->cloneType();
[8]1056
1057        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
1058        {
1059            bool iteratorAdvanced = false;
1060            if (fr[0].matchWord("UniqueID") && fr[1].isString())
1061            {
[7038]1062                fr.registerUniqueIDForObject(fr[1].getStr(),obj);
[8]1063                fr += 2;
1064                iteratorAdvanced = true;
1065            }
1066
1067            // read the local data by iterating through the associate
1068            // list, mapping the associate names to DotOsgWrapper's which
1069            // in turn have the appropriate functions.
1070            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1071                                                          aitr!=assoc.end();
1072                                                          ++aitr)
1073            {
1074                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
[2174]1075                if (mitr==_objectWrapperMap.end())
1076                {
1077                    // not found so check if a library::class composite name.
1078                    std::string token = *aitr;
1079                    std::string::size_type posDoubleColon = token.rfind("::");
1080                    if (posDoubleColon != std::string::npos)
1081                    {
1082
1083                        // we have a composite name so now strip off the library name
1084                        // are try to load it, and then retry the find to see
[7648]1085                        // if we can recognize the objects.
[2174]1086
1087                        std::string libraryName = std::string(token,0,posDoubleColon);
1088
1089                        // first try the standard nodekit library.
1090                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1091                        if (loadLibrary(nodeKitLibraryName)==LOADED)
[2174]1092                        {
1093                            mitr = _objectWrapperMap.find(*aitr);
1094                        }
1095
1096                        if (mitr==_objectWrapperMap.end())
1097                        {
1098                            // otherwise try the osgdb_ plugin library.
1099                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1100                            if (loadLibrary(pluginLibraryName)==LOADED)
[2174]1101                            {
1102                                mitr = _objectWrapperMap.find(*aitr);
1103                            }
1104                        }
1105
1106                    }
1107                }
1108
[8]1109                if (mitr!=_objectWrapperMap.end())
1110                {
1111                    // get the function to read the data...
1112                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
1113                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
1114                }
1115
1116            }
1117
[741]1118            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
[8]1119        }
1120        ++fr;                        // step over trailing '}'
1121       
1122        return obj;
1123       
1124    }
1125
1126    return 0L;
1127}
1128
1129//
1130// read object from input iterator.
1131//
1132Object* Registry::readObject(Input& fr)
1133{
1134    if (fr[0].matchWord("Use"))
1135    {
1136        if (fr[1].isString())
1137        {
1138            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
1139            if (obj) fr+=2;
1140            return obj;
1141        }
1142        else return NULL;
1143
1144    }
1145
1146    return readObject(_objectWrapperMap,fr);
1147}
1148
1149
1150//
1151// read image from input iterator.
1152//
1153Image* Registry::readImage(Input& fr)
1154{
1155    if (fr[0].matchWord("Use"))
1156    {
1157        if (fr[1].isString())
1158        {
1159            Image* image = dynamic_cast<Image*>(fr.getObjectForUniqueID(fr[1].getStr()));
1160            if (image) fr+=2;
1161            return image;
1162        }
1163        else return NULL;
1164
1165    }
1166
[480]1167    osg::Object* obj = readObject(_imageWrapperMap,fr);
1168    osg::Image* image = dynamic_cast<Image*>(obj);
1169    if (image) return image;
1170    else if (obj) obj->unref();
1171   
1172    return NULL;
[8]1173}
1174
1175
1176//
1177// read drawable from input iterator.
1178//
1179Drawable* Registry::readDrawable(Input& fr)
1180{
1181    if (fr[0].matchWord("Use"))
1182    {
1183        if (fr[1].isString())
1184        {
1185            Drawable* drawable = dynamic_cast<Drawable*>(fr.getObjectForUniqueID(fr[1].getStr()));
1186            if (drawable) fr+=2;
1187            return drawable;
1188        }
1189        else return NULL;
1190
1191    }
1192
[480]1193    osg::Object* obj = readObject(_drawableWrapperMap,fr);
1194    osg::Drawable* drawable = dynamic_cast<Drawable*>(obj);
1195    if (drawable) return drawable;
1196    else if (obj) obj->unref();
1197   
1198    return NULL;
[8]1199}
1200
1201//
1202// read drawable from input iterator.
1203//
1204StateAttribute* Registry::readStateAttribute(Input& fr)
1205{
1206
1207    if (fr[0].matchWord("Use"))
1208    {
1209        if (fr[1].isString())
1210        {
1211            StateAttribute* attribute = dynamic_cast<StateAttribute*>(fr.getObjectForUniqueID(fr[1].getStr()));
1212            if (attribute) fr+=2;
1213            return attribute;
1214        }
1215        else return NULL;
1216
1217    }
1218
1219    return dynamic_cast<StateAttribute*>(readObject(_stateAttrWrapperMap,fr));
1220}
1221
1222//
[4061]1223// read drawable from input iterator.
1224//
1225Uniform* Registry::readUniform(Input& fr)
1226{
1227
1228    if (fr[0].matchWord("Use"))
1229    {
1230        if (fr[1].isString())
1231        {
1232            Uniform* attribute = dynamic_cast<Uniform*>(fr.getObjectForUniqueID(fr[1].getStr()));
1233            if (attribute) fr+=2;
1234            return attribute;
1235        }
1236        else return NULL;
1237
1238    }
1239
1240    return dynamic_cast<Uniform*>(readObject(_uniformWrapperMap,fr));
1241}
1242
1243//
[8]1244// read node from input iterator.
1245//
1246Node* Registry::readNode(Input& fr)
1247{
1248    if (fr[0].matchWord("Use"))
1249    {
1250        if (fr[1].isString())
1251        {
1252            Node* node = dynamic_cast<Node*>(fr.getObjectForUniqueID(fr[1].getStr()));
1253            if (node) fr+=2;
1254            return node;
1255        }
1256        else return NULL;
1257
1258    }
1259
[480]1260    osg::Object* obj = readObject(_nodeWrapperMap,fr);
1261    osg::Node* node = dynamic_cast<Node*>(obj);
1262    if (node) return node;
1263    else if (obj) obj->unref();
1264   
1265    return NULL;
[8]1266}
1267
1268//
[7908]1269// read image from input iterator.
1270//
1271Shader* Registry::readShader(Input& fr)
1272{
1273    if (fr[0].matchWord("Use"))
1274    {
1275        if (fr[1].isString())
1276        {
1277            Shader* shader = dynamic_cast<Shader*>(fr.getObjectForUniqueID(fr[1].getStr()));
1278            if (shader) fr+=2;
1279            return shader;
1280        }
1281        else return NULL;
1282
1283    }
1284
1285    osg::Object* obj = readObject(_shaderWrapperMap,fr);
1286    osg::Shader* shader = dynamic_cast<Shader*>(obj);
1287    if (shader) return shader;
1288    else if (obj) obj->unref();
1289   
1290    return NULL;
1291}
1292
1293//
[8]1294// Write object to output
1295//
1296bool Registry::writeObject(const osg::Object& obj,Output& fw)
1297{
1298
1299    if (obj.referenceCount()>1)
1300    {
1301        std::string uniqueID;
1302        if (fw.getUniqueIDForObject(&obj,uniqueID))
1303        {
[6629]1304            fw.writeUseID( uniqueID );
[8]1305            return true;
1306        }
1307    }
1308
[6629]1309    const std::string classname( obj.className() );
1310    const std::string libraryName( obj.libraryName() );
1311    const std::string compositeName( libraryName + "::" + classname );
[1061]1312
[2501]1313    // try composite name first
1314    DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(compositeName);
[1061]1315
1316    if (itr==_classNameWrapperMap.end())
[8]1317    {
[1061]1318        // first try the standard nodekit library.
[6629]1319        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1320        if (loadLibrary(nodeKitLibraryName)==LOADED) return writeObject(obj,fw);
[1061]1321
1322        // otherwise try the osgdb_ plugin library.
[6629]1323        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1324        if (loadLibrary(pluginLibraryName)==LOADED) return writeObject(obj,fw);
[4635]1325
1326        // otherwise try simple class name
1327        if (itr == _classNameWrapperMap.end())
1328            itr = _classNameWrapperMap.find(classname);
[1061]1329    }
[4635]1330
1331    if (itr!=_classNameWrapperMap.end())
1332    {
[8]1333        DotOsgWrapper* wrapper = itr->second.get();
1334        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
1335
[6629]1336        if (libraryName=="osg")
[742]1337        {
1338            // member of the core osg, so no need to have composite library::class name.
[6629]1339            fw.writeBeginObject( wrapper->getName() );
[742]1340        }
1341        else
1342        {
1343            // member of the node kit so must use composite library::class name.
[2180]1344            std::string::size_type posDoubleColon = wrapper->getName().find("::");
1345            if (posDoubleColon != std::string::npos)
1346            {
[6629]1347                fw.writeBeginObject( wrapper->getName() );
[2180]1348            }
1349            else
1350            {
[6629]1351                fw.writeBeginObject( libraryName + "::" + wrapper->getName() );
[2180]1352            }
[742]1353        }
[6629]1354        fw.moveIn();
[8]1355
1356
1357        // write out the unique ID if required.
1358        if (obj.referenceCount()>1)
1359        {
1360            std::string uniqueID;
1361            fw.createUniqueIDForObject(&obj,uniqueID);
1362            fw.registerUniqueIDForObject(&obj,uniqueID);
[6629]1363            fw.writeUniqueID( uniqueID );
[8]1364        }
1365
1366        // read the local data by iterating through the associate
1367        // list, mapping the associate names to DotOsgWrapper's which
1368        // in turn have the appropriate functions.
1369        for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1370                                                      aitr!=assoc.end();
1371                                                      ++aitr)
1372        {
1373            DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
[2238]1374            if (mitr==_objectWrapperMap.end())
1375            {
1376                // not found so check if a library::class composite name.
1377                std::string token = *aitr;
1378                std::string::size_type posDoubleColon = token.rfind("::");
1379                if (posDoubleColon != std::string::npos)
1380                {
1381
1382                    // we have a composite name so now strip off the library name
1383                    // are try to load it, and then retry the find to see
[7648]1384                    // if we can recognize the objects.
[2238]1385
1386                    std::string libraryName = std::string(token,0,posDoubleColon);
1387
1388                    // first try the standard nodekit library.
1389                    std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1390                    if (loadLibrary(nodeKitLibraryName)==LOADED)
[2238]1391                    {
1392                        mitr = _objectWrapperMap.find(*aitr);
1393                    }
1394
1395                    if (mitr==_objectWrapperMap.end())
1396                    {
1397                        // otherwise try the osgdb_ plugin library.
1398                        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1399                        if (loadLibrary(pluginLibraryName)==LOADED)
[2238]1400                        {
1401                            mitr = _objectWrapperMap.find(*aitr);
1402                        }
1403                    }
1404
1405                }
1406            }
[8]1407            if (mitr!=_objectWrapperMap.end())
1408            {
1409                // get the function to read the data...
1410                DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc();
1411                if (wf) (*wf)(obj,fw);
1412            }
1413
1414        }
1415
1416        fw.moveOut();
[6629]1417        fw.writeEndObject();
[8]1418
1419        return true;
1420    }
[1061]1421   
[8]1422    return false;
1423}
1424
[3580]1425
[3581]1426
[3596]1427struct Registry::ReadObjectFunctor : public Registry::ReadFunctor
[3580]1428{
[10171]1429    ReadObjectFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {}
[3580]1430
[3693]1431    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readObject(_filename, _options); }   
[3581]1432    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validObject(); }
1433    virtual bool isValid(osg::Object* object) const { return object!=0;  }
1434};
[3580]1435
[3596]1436struct Registry::ReadImageFunctor : public Registry::ReadFunctor
[3581]1437{
[10171]1438    ReadImageFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {}
[3580]1439
[3693]1440    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const  { return rw.readImage(_filename, _options); }   
[3581]1441    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validImage(); }
1442    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Image*>(object)!=0;  }
1443};
[3580]1444
[3596]1445struct Registry::ReadHeightFieldFunctor : public Registry::ReadFunctor
[3581]1446{
[10171]1447    ReadHeightFieldFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {}
[3580]1448
[3693]1449    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readHeightField(_filename, _options); }   
[3581]1450    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validHeightField(); }
1451    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::HeightField*>(object)!=0;  }
1452};
1453
[3596]1454struct Registry::ReadNodeFunctor : public Registry::ReadFunctor
[3581]1455{
[10171]1456    ReadNodeFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {}
[3581]1457
[3693]1458    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readNode(_filename, _options); }   
[3581]1459    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validNode(); }
1460    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Node*>(object)!=0;  }
1461
1462};
1463
[3596]1464struct Registry::ReadArchiveFunctor : public Registry::ReadFunctor
[3581]1465{
[10171]1466    ReadArchiveFunctor(const std::string& filename, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const Options* options):
[3581]1467        ReadFunctor(filename,options),
1468        _status(status),
1469        _indexBlockSizeHint(indexBlockSizeHint) {}
[3580]1470       
[3581]1471    ReaderWriter::ArchiveStatus _status;
1472    unsigned int _indexBlockSizeHint;
[3580]1473
[3693]1474    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.openArchive(_filename, _status, _indexBlockSizeHint, _options); }
[3581]1475    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validArchive(); }
1476    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osgDB::Archive*>(object)!=0;  }
[3580]1477
[3581]1478};
[3580]1479
[7908]1480struct Registry::ReadShaderFunctor : public Registry::ReadFunctor
1481{
[10171]1482    ReadShaderFunctor(const std::string& filename, const Options* options):ReadFunctor(filename,options) {}
[7908]1483
1484    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const  { return rw.readShader(_filename, _options); }   
1485    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validShader(); }
1486    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Shader*>(object)!=0;  }
1487};
1488
[6628]1489void Registry::addArchiveExtension(const std::string ext)
1490{
1491    for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin();
1492        aitr!=_archiveExtList.end();
1493        ++aitr)
1494    {
1495        if ( (*aitr) == ext)   // extension already in archive extension list
1496            return;
1497    }
1498    _archiveExtList.push_back(ext);
[7375]1499}
[6628]1500
[10171]1501std::string Registry::findDataFileImplementation(const std::string& filename, const Options* options, CaseSensitivity caseSensitivity)
1502{
1503    if (filename.empty()) return filename;
1504
[10319]1505    // if data file contains a server address then we can't find it in local directories so return empty string.
1506    if (containsServerAddress(filename)) return std::string();
1507
[10171]1508    if(fileExists(filename))
1509    {
1510        osg::notify(osg::DEBUG_INFO) << "FindFileInPath(" << filename << "): returning " << filename << std::endl;
1511        return filename;
1512    }
1513
1514    std::string fileFound;
1515
1516    if (options && !options->getDatabasePathList().empty())
1517    {
1518        fileFound = findFileInPath(filename, options->getDatabasePathList(), caseSensitivity);
1519        if (!fileFound.empty()) return fileFound;
1520    }
1521
1522    const FilePathList& filepath = Registry::instance()->getDataFilePathList();
1523    if (!filepath.empty())
1524    {
1525        fileFound = findFileInPath(filename, filepath,caseSensitivity);
1526        if (!fileFound.empty()) return fileFound;
1527    }
1528
1529
1530    // if a directory is included in the filename, get just the (simple) filename itself and try that
1531    std::string simpleFileName = getSimpleFileName(filename);
1532    if (simpleFileName!=filename)
1533    {
1534
1535        if(fileExists(simpleFileName))
1536        {
1537            osg::notify(osg::DEBUG_INFO) << "FindFileInPath(" << filename << "): returning " << filename << std::endl;
1538            return simpleFileName;
1539        }
1540
1541        if (options && !options->getDatabasePathList().empty())
1542        {
1543            fileFound = findFileInPath(simpleFileName, options->getDatabasePathList(), caseSensitivity);
1544            if (!fileFound.empty()) return fileFound;
1545        }
1546
1547        if (!filepath.empty())
1548        {
1549            fileFound = findFileInPath(simpleFileName, filepath,caseSensitivity);
1550            if (!fileFound.empty()) return fileFound;
1551        }
1552
1553    }
1554
1555    // return empty string.
1556    return std::string();
1557}
1558
1559std::string Registry::findLibraryFileImplementation(const std::string& filename, const Options* options, CaseSensitivity caseSensitivity)
1560{
1561    if (filename.empty())
1562        return filename;
1563
1564    const FilePathList& filepath = Registry::instance()->getLibraryFilePathList();
1565
1566    std::string fileFound = findFileInPath(filename, filepath,caseSensitivity);
1567    if (!fileFound.empty())
1568        return fileFound;
1569
1570    if(fileExists(filename))
1571    {
1572        osg::notify(osg::DEBUG_INFO) << "FindFileInPath(" << filename << "): returning " << filename << std::endl;
1573        return filename;
1574    }
1575
1576    // if a directory is included in the filename, get just the (simple) filename itself and try that
1577    std::string simpleFileName = getSimpleFileName(filename);
1578    if (simpleFileName!=filename)
1579    {
1580        std::string fileFound = findFileInPath(simpleFileName, filepath,caseSensitivity);
1581        if (!fileFound.empty()) return fileFound;
1582    }
1583
1584    // failed return empty string.
1585    return std::string();
1586}
1587
1588
1589
[3581]1590ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor)
[3580]1591{
[6628]1592    for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin();
1593        aitr!=_archiveExtList.end();
1594        ++aitr)
1595    {
[7607]1596        std::string archiveExtension = "." + (*aitr);
[3580]1597
[7607]1598        std::string::size_type positionArchive = readFunctor._filename.find(archiveExtension+'/');
1599        if (positionArchive==std::string::npos) positionArchive = readFunctor._filename.find(archiveExtension+'\\');
[6628]1600        if (positionArchive!=std::string::npos)
1601        {
[7607]1602            std::string::size_type endArchive = positionArchive + archiveExtension.length();
1603            std::string archiveName( readFunctor._filename.substr(0,endArchive));
1604            std::string fileName(readFunctor._filename.substr(endArchive+1,std::string::npos));
[6628]1605            osg::notify(osg::INFO)<<"Contains archive : "<<readFunctor._filename<<std::endl;
1606            osg::notify(osg::INFO)<<"         archive : "<<archiveName<<std::endl;
1607            osg::notify(osg::INFO)<<"         filename : "<<fileName<<std::endl;
[3580]1608       
[6628]1609            ReaderWriter::ReadResult result = openArchiveImplementation(archiveName,ReaderWriter::READ, 4096, readFunctor._options);
[3598]1610       
[6628]1611            if (!result.validArchive()) return result;
[3580]1612
[6628]1613            osgDB::Archive* archive = result.getArchive();
[3580]1614       
[10171]1615            osg::ref_ptr<Options> options = new Options;
[6628]1616            options->setDatabasePath(archiveName);
[3580]1617
[6628]1618            return archive->readObject(fileName,options.get());
1619        }
[3580]1620    }
[9443]1621 
[146]1622    // record the errors reported by readerwriters.
1623    typedef std::vector<ReaderWriter::ReadResult> Results;
1624    Results results;
[8]1625
1626    // first attempt to load the file from existing ReaderWriter's
[8929]1627    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1628    for(;itr.valid();++itr)
[8]1629    {
[3581]1630        ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
1631        if (readFunctor.isValid(rr)) return rr;
[2520]1632        else results.push_back(rr);
[8]1633    }
1634
[2520]1635    if (!results.empty())
1636    {
1637        unsigned int num_FILE_NOT_HANDLED = 0;
1638        unsigned int num_FILE_NOT_FOUND = 0;
1639        unsigned int num_ERROR_IN_READING_FILE = 0;
1640
[5397]1641        Results::iterator ritr;
1642        for(ritr=results.begin();
[2520]1643            ritr!=results.end();
1644            ++ritr)
1645        {
1646            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1647            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1648            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1649        }
1650       
1651        if (num_FILE_NOT_HANDLED!=results.size())
1652        {
[5397]1653            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[2520]1654            {
[5397]1655                if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE)
1656                {
[7694]1657                    // osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<readFunctor._filename<<"\""<<std::endl;
[5397]1658                    return *ritr;
1659                }
[2520]1660            }
[5397]1661
[9526]1662            //If the filename is a URL, don't return FILE_NOT_FOUND until the CURL plugin is given a chance
1663            if (!osgDB::containsServerAddress(readFunctor._filename))
[2520]1664            {
[9526]1665                for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[5397]1666                {
[9526]1667                    if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND)
1668                    {
1669                        //osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<readFunctor._filename<<"\""<<std::endl;
1670                        return *ritr;
1671                    }
[5397]1672                }
[2520]1673            }
1674        }
1675    }
1676
[5230]1677    results.clear();
1678
[8]1679    // now look for a plug-in to load the file.
[3581]1680    std::string libraryName = createLibraryNameForFile(readFunctor._filename);
[8947]1681    if (loadLibrary(libraryName)!=NOT_LOADED)
[8]1682    {
[2522]1683        for(;itr.valid();++itr)
[8]1684        {
[3581]1685            ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
1686            if (readFunctor.isValid(rr)) return rr;
[2522]1687            else results.push_back(rr);
[8]1688        }
1689    }
[9443]1690
1691    //If the filename contains a server address and wasn't loaded by any of the plugins, try to use the CURL plugin
1692    //to download the file and use the stream reading functionality of the plugins to load the file
1693    if (containsServerAddress(readFunctor._filename))
1694    {
1695        ReaderWriter* rw = getReaderWriterForExtension("curl");
1696        if (rw)
1697        {
1698            return readFunctor.doRead(*rw);
1699        }
1700        else
1701        {
1702            return  ReaderWriter::ReadResult("Warning: Could not find the .curl plugin to read from server.");
1703        }
1704    }
[146]1705   
[5230]1706    if (!results.empty())
[8]1707    {
[5230]1708        unsigned int num_FILE_NOT_HANDLED = 0;
1709        unsigned int num_FILE_NOT_FOUND = 0;
1710        unsigned int num_ERROR_IN_READING_FILE = 0;
1711
[5396]1712        Results::iterator ritr;
1713        for(ritr=results.begin();
[5230]1714            ritr!=results.end();
1715            ++ritr)
1716        {
1717            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1718            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1719            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1720        }
1721       
1722        if (num_FILE_NOT_HANDLED!=results.size())
1723        {
[5396]1724            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[5230]1725            {
[5396]1726                if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE)
1727                {
[7694]1728                    // osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<readFunctor._filename<<"\""<<std::endl;
[5396]1729                    return *ritr;
1730                }
[5230]1731            }
[5396]1732
1733            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[5230]1734            {
[5396]1735                if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND)
1736                {
[7694]1737                    // osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<readFunctor._filename<<"\""<<std::endl;
[5396]1738                    return *ritr;
1739                }
[5230]1740            }
1741        }
1742    }
1743    else
1744    {
[3581]1745        return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+readFunctor._filename+"\".");
[8]1746    }
[371]1747
1748    return results.front();
[8]1749}
1750
[10171]1751ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFunctor,Options::CacheHintOptions cacheHint)
[1708]1752{
[3581]1753    std::string file(readFunctor._filename);
[2877]1754
[9995]1755    bool useObjectCache=false;
1756    //Note CACHE_ARCHIVES has a different object that it caches to so it will never be used here
[10171]1757    if (cacheHint!=Options::CACHE_ARCHIVES)
[9995]1758    {
[10171]1759        const Options* options=readFunctor._options;
[9995]1760        useObjectCache=options ? (options->getObjectCacheHint()&cacheHint)!=0: false;
1761    }
[3598]1762    if (useObjectCache)
[1708]1763    {
1764        // search for entry in the object cache.
1765        {
[3384]1766            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1767            ObjectCache::iterator oitr=_objectCache.find(file);
1768            if (oitr!=_objectCache.end())
1769            {
1770                notify(INFO)<<"returning cached instanced of "<<file<<std::endl;
[3581]1771                if (readFunctor.isValid(oitr->second.first.get())) return ReaderWriter::ReadResult(oitr->second.first.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
[3384]1772                else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
1773            }
[1708]1774        }
[3384]1775       
[3581]1776        ReaderWriter::ReadResult rr = read(readFunctor);
[1708]1777        if (rr.validObject())
1778        {
1779            // update cache with new entry.
[3581]1780            notify(INFO)<<"Adding to object cache "<<file<<std::endl;
[2335]1781            addEntryToObjectCache(file,rr.getObject());
[1708]1782        }
[3598]1783        else
1784        {
1785            notify(INFO)<<"No valid object found for "<<file<<std::endl;
1786        }
1787
[1708]1788        return rr;
1789
1790    }
1791    else
1792    {
[3581]1793        ReaderWriter::ReadResult rr = read(readFunctor);
[1708]1794        return rr;
1795    }
1796}
1797
[3581]1798
[10171]1799ReaderWriter::ReadResult Registry::openArchiveImplementation(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const Options* options)
[3581]1800{
[6636]1801    osgDB::Archive* archive = getFromArchiveCache(fileName);
1802    if (archive) return archive;
[3707]1803
[10171]1804    ReaderWriter::ReadResult result = readImplementation(ReadArchiveFunctor(fileName, status, indexBlockSizeHint, options),Options::CACHE_ARCHIVES);
[6636]1805
[7648]1806    // default to using caching archive if no options structure provided, but if options are provided use archives
[3707]1807    // only if supplied.
[6636]1808    if (result.validArchive() &&
[10171]1809        (!options || (options->getObjectCacheHint() & Options::CACHE_ARCHIVES)) )
[3598]1810    {
[6636]1811        addToArchiveCache(fileName,result.getArchive());
[3598]1812    }
[6636]1813    return result;
[3581]1814}
1815
1816
[10171]1817ReaderWriter::ReadResult Registry::readObjectImplementation(const std::string& fileName,const Options* options)
[3581]1818{
[10171]1819    return readImplementation(ReadObjectFunctor(fileName, options),Options::CACHE_OBJECTS);
[3581]1820}
1821
[10171]1822ReaderWriter::WriteResult Registry::writeObjectImplementation(const Object& obj,const std::string& fileName,const Options* options)
[8]1823{
[146]1824    // record the errors reported by readerwriters.
1825    typedef std::vector<ReaderWriter::WriteResult> Results;
1826    Results results;
1827
[8]1828    // first attempt to load the file from existing ReaderWriter's
[8929]1829    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1830    for(;itr.valid();++itr)
[8]1831    {
[7518]1832        ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options);
[147]1833        if (rr.success()) return rr;
[2520]1834        else results.push_back(rr);
[8]1835    }
1836
1837    // now look for a plug-in to save the file.
1838    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1839    if (loadLibrary(libraryName)==LOADED)
[8]1840    {
[2522]1841        for(;itr.valid();++itr)
[8]1842        {
[7518]1843            ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options);
[2522]1844            if (rr.success()) return rr;
1845            else results.push_back(rr);
[8]1846        }
1847    }
[146]1848
1849    if (results.empty())
[8]1850    {
[147]1851        return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\".");
[8]1852    }
[371]1853
[5697]1854    if (results.front().message().empty())
1855    {
1856        switch(results.front().status())
1857        {
1858            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1859            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1860            default: break;
1861        }
1862    }
1863
[371]1864    return results.front();
[8]1865}
1866
[3477]1867
1868
[10171]1869ReaderWriter::ReadResult Registry::readImageImplementation(const std::string& fileName,const Options* options)
[1708]1870{
[10171]1871    return readImplementation(ReadImageFunctor(fileName, options),Options::CACHE_IMAGES);
[1708]1872}
1873
[10171]1874ReaderWriter::WriteResult Registry::writeImageImplementation(const Image& image,const std::string& fileName,const Options* options)
[8]1875{
[146]1876    // record the errors reported by readerwriters.
1877    typedef std::vector<ReaderWriter::WriteResult> Results;
1878    Results results;
1879
[8]1880    // first attempt to load the file from existing ReaderWriter's
[8929]1881    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1882    for(;itr.valid();++itr)
[8]1883    {
[7518]1884        ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options);
[147]1885        if (rr.success()) return rr;
[2520]1886        else results.push_back(rr);
[8]1887    }
1888
[5697]1889    results.clear();
1890
[8]1891    // now look for a plug-in to save the file.
1892    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1893    if (loadLibrary(libraryName)==LOADED)
[8]1894    {
[2522]1895        for(;itr.valid();++itr)
[8]1896        {
[7518]1897            ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options);
[2522]1898            if (rr.success()) return rr;
1899            else results.push_back(rr);
[8]1900        }
1901    }
[146]1902
1903    if (results.empty())
[8]1904    {
[147]1905        return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\".");
[8]1906    }
[371]1907   
[5697]1908    if (results.front().message().empty())
1909    {
1910        switch(results.front().status())
1911        {
1912            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1913            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1914            default: break;
1915        }
1916    }
1917
[371]1918    return results.front();
[8]1919}
1920
[3477]1921
[10171]1922ReaderWriter::ReadResult Registry::readHeightFieldImplementation(const std::string& fileName,const Options* options)
[2398]1923{
[10171]1924    return readImplementation(ReadHeightFieldFunctor(fileName, options),Options::CACHE_HEIGHTFIELDS);
[2398]1925}
1926
[10171]1927ReaderWriter::WriteResult Registry::writeHeightFieldImplementation(const HeightField& HeightField,const std::string& fileName,const Options* options)
[2398]1928{
1929    // record the errors reported by readerwriters.
1930    typedef std::vector<ReaderWriter::WriteResult> Results;
1931    Results results;
1932
1933    // first attempt to load the file from existing ReaderWriter's
[8929]1934    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1935    for(;itr.valid();++itr)
[2398]1936    {
[7518]1937        ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options);
[2398]1938        if (rr.success()) return rr;
[2520]1939        else results.push_back(rr);
[2398]1940    }
1941
[5697]1942    results.clear();
1943
[2398]1944    // now look for a plug-in to save the file.
1945    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1946    if (loadLibrary(libraryName)==LOADED)
[2398]1947    {
[2522]1948        for(;itr.valid();++itr)
[2398]1949        {
[7518]1950            ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options);
[2522]1951            if (rr.success()) return rr;
1952            else results.push_back(rr);
[2398]1953        }
1954    }
1955
1956    if (results.empty())
1957    {
1958        return ReaderWriter::WriteResult("Warning: Could not find plugin to write HeightField to file \""+fileName+"\".");
1959    }
[5697]1960
1961    if (results.front().message().empty())
1962    {
1963        switch(results.front().status())
1964        {
1965            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1966            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1967            default: break;
1968        }
1969    }
[2398]1970   
1971    return results.front();
1972}
1973
1974
[10171]1975ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& fileName,const Options* options)
[8]1976{
[9024]1977#if 0
1978
1979    osg::Timer_t startTick = osg::Timer::instance()->tick();
[10171]1980    ReaderWriter::ReadResult result = readImplementation(ReadNodeFunctor(fileName, options),Options::CACHE_NODES);
[9024]1981    osg::Timer_t endTick = osg::Timer::instance()->tick();
1982    osg::notify(osg::NOTICE)<<"time to load "<<fileName<<" "<<osg::Timer::instance()->delta_m(startTick, endTick)<<"ms"<<std::endl;
1983    return result;
1984
1985#else
1986
[10171]1987    return readImplementation(ReadNodeFunctor(fileName, options),Options::CACHE_NODES);
[9024]1988                             
1989#endif
[8]1990}
1991
[10171]1992ReaderWriter::WriteResult Registry::writeNodeImplementation(const Node& node,const std::string& fileName,const Options* options)
[8]1993{
[146]1994    // record the errors reported by readerwriters.
1995    typedef std::vector<ReaderWriter::WriteResult> Results;
1996    Results results;
1997
[8]1998    // first attempt to write the file from existing ReaderWriter's
[8929]1999    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]2000    for(;itr.valid();++itr)
[8]2001    {
[7518]2002        ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options);
[147]2003        if (rr.success()) return rr;
[2520]2004        else results.push_back(rr);
[8]2005    }
2006
[5697]2007    results.clear();
2008
[8]2009    // now look for a plug-in to save the file.
2010    std::string libraryName = createLibraryNameForFile(fileName);
[5697]2011
2012
[8947]2013    if (loadLibrary(libraryName)==LOADED)
[8]2014    {
[2522]2015        for(;itr.valid();++itr)
[8]2016        {
[7518]2017            ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options);
[5697]2018   
[2522]2019            if (rr.success()) return rr;
2020            else results.push_back(rr);
[8]2021        }
2022    }
[146]2023
2024    if (results.empty())
[8]2025    {
[147]2026        return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\".");
[8]2027    }
[371]2028
[5697]2029    if (results.front().message().empty())
2030    {
2031        switch(results.front().status())
2032        {
2033            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
2034            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
2035            default: break;
2036        }
2037    }
2038
[371]2039    return results.front();
[8]2040}
[773]2041
[10171]2042ReaderWriter::ReadResult Registry::readShaderImplementation(const std::string& fileName,const Options* options)
[7908]2043{
[10171]2044    return readImplementation(ReadShaderFunctor(fileName, options),Options::CACHE_SHADERS);
[7908]2045}
[773]2046
[10171]2047ReaderWriter::WriteResult Registry::writeShaderImplementation(const Shader& shader,const std::string& fileName,const Options* options)
[7908]2048{
2049    // record the errors reported by readerwriters.
2050    typedef std::vector<ReaderWriter::WriteResult> Results;
2051    Results results;
2052
2053    // first attempt to load the file from existing ReaderWriter's
[8929]2054    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[7908]2055    for(;itr.valid();++itr)
2056    {
2057        ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options);
2058        if (rr.success()) return rr;
2059        else results.push_back(rr);
2060    }
2061
2062    results.clear();
2063
2064    // now look for a plug-in to save the file.
2065    std::string libraryName = createLibraryNameForFile(fileName);
[8947]2066    if (loadLibrary(libraryName)==LOADED)
[7908]2067    {
2068        for(;itr.valid();++itr)
2069        {
2070            ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options);
2071            if (rr.success()) return rr;
2072            else results.push_back(rr);
2073        }
2074    }
2075
2076    if (results.empty())
2077    {
2078        return ReaderWriter::WriteResult("Warning: Could not find plugin to write shader to file \""+fileName+"\".");
2079    }
2080   
2081    if (results.front().message().empty())
2082    {
2083        switch(results.front().status())
2084        {
2085            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
2086            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
2087            default: break;
2088        }
2089    }
2090
2091    return results.front();
2092}
2093
[2335]2094void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
2095{
[3384]2096    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2097    _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
[2335]2098}
[3876]2099osg::Object* Registry::getFromObjectCache(const std::string& fileName)
2100{
2101    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2102    ObjectCache::iterator itr = _objectCache.find(fileName);
2103    if (itr!=_objectCache.end()) return itr->second.first.get();
2104    else return 0;
2105}
[2335]2106
[7038]2107void Registry::updateTimeStampOfObjectsInCacheWithExternalReferences(double currentTime)
[1708]2108{
[3384]2109    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
[1708]2110
2111    // look for objects with external references and update their time stamp.
2112    for(ObjectCache::iterator itr=_objectCache.begin();
2113        itr!=_objectCache.end();
2114        ++itr)
2115    {
2116        // if ref count is greater the 1 the object has an external reference.
2117        if (itr->second.first->referenceCount()>1)
2118        {
2119            // so update it time stamp.
2120            itr->second.second = currentTime;
2121        }
2122    }
2123}
2124
2125void Registry::removeExpiredObjectsInCache(double expiryTime)
2126{
[3384]2127    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2128
[1708]2129    typedef std::vector<std::string> ObjectsToRemove;
2130    ObjectsToRemove objectsToRemove;
2131
[7648]2132    // first collect all the expired entries in the ObjectToRemove list.
[1708]2133    for(ObjectCache::iterator oitr=_objectCache.begin();
2134        oitr!=_objectCache.end();
2135        ++oitr)
2136    {
[2611]2137        if (oitr->second.second<=expiryTime)
[1708]2138        {
2139            // record the filename of the entry to use as key for deleting
2140            // afterwards/
2141            objectsToRemove.push_back(oitr->first);
2142        }
2143    }
2144   
2145    // remove the entries from the _objectCaache.
2146    for(ObjectsToRemove::iterator ritr=objectsToRemove.begin();
2147        ritr!=objectsToRemove.end();
2148        ++ritr)
2149    {
[2631]2150        // std::cout<<"Removing from Registry object cache '"<<*ritr<<"'"<<std::endl;
[1708]2151        _objectCache.erase(*ritr);
2152    }
2153       
2154}
2155
2156void Registry::clearObjectCache()
2157{
[3384]2158    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
[1708]2159    _objectCache.clear();
2160}
[2614]2161
[3598]2162void Registry::addToArchiveCache(const std::string& fileName, osgDB::Archive* archive)
2163{
2164    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2165    _archiveCache[fileName] = archive;
2166}
2167
2168/** Remove archive from cache.*/
2169void Registry::removeFromArchiveCache(const std::string& fileName)
2170{
2171    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2172    ArchiveCache::iterator itr = _archiveCache.find(fileName);
2173    if (itr!=_archiveCache.end())
2174    {
2175        _archiveCache.erase(itr);
2176    }
2177}
2178
2179osgDB::Archive* Registry::getFromArchiveCache(const std::string& fileName)
2180{
2181    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2182    ArchiveCache::iterator itr = _archiveCache.find(fileName);
2183    if (itr!=_archiveCache.end()) return itr->second.get();
2184    else return 0;
2185}
2186
2187void Registry::clearArchiveCache()
2188{
2189    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2190    _archiveCache.clear();
2191}
2192
[4170]2193void Registry::releaseGLObjects(osg::State* state)
2194{
2195    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2196
2197    for(ObjectCache::iterator itr = _objectCache.begin();
2198        itr != _objectCache.end();
2199        ++itr)
2200    {
2201        osg::Object* object = itr->second.first.get();
2202        object->releaseGLObjects(state);
2203    }
2204}
2205
[2631]2206SharedStateManager* Registry::getOrCreateSharedStateManager()
2207{
2208    if (!_sharedStateManager) _sharedStateManager = new SharedStateManager;
2209   
2210    return _sharedStateManager.get();
2211}
[9884]2212
2213
2214void Registry::registerProtocol(const std::string& protocol)
2215
2216    _registeredProtocols.insert( convertToLowerCase(protocol) );
2217}
2218       
2219bool Registry::isProtocolRegistered(const std::string& protocol)
2220{
2221    return (_registeredProtocols.find( convertToLowerCase(protocol) ) != _registeredProtocols.end());
2222}
Note: See TracBrowser for help on using the browser.