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

Revision 10520, 72.4 kB (checked in by robert, 5 years ago)

Moved the updating and expiry of the Registry object cache from DatabasePager? into osgViewer::Viewer/CompositeViewer.

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