diff --git a/include/osgDB/FileUtils b/include/osgDB/FileUtils index ef05cd73f..64ed55b85 100644 --- a/include/osgDB/FileUtils +++ b/include/osgDB/FileUtils @@ -96,14 +96,10 @@ inline FilePathList& getLibraryFilePathList() { return osgDB::Registry::instance extern OSGDB_EXPORT std::string findLibraryFile(const std::string& filename,CaseSensitivity caseSensitivity=CASE_SENSITIVE); -// -// -// /** Deprecated. */ -// inline std::string findFileInDirectory(const std::string& fileName,const std::string& dirName,bool caseInsensitive) -// { -// return findFileInDirectory(fileName,dirName,caseInsensitive?CASE_SENSITIVE:CASE_INSENSITIVE); -// } -// +/** convert a string containing a list of paths deliminated either with ';' (Windows) or ':' (All other platforms) into FilePath represetation.*/ +extern OSGDB_EXPORT void convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath); + +extern OSGDB_EXPORT void appendPlatformSpecificLibraryFilePaths(FilePathList& filepath); } diff --git a/include/osgDB/Registry b/include/osgDB/Registry index 02a5f8915..6839cbc63 100644 --- a/include/osgDB/Registry +++ b/include/osgDB/Registry @@ -298,7 +298,7 @@ class OSGDB_EXPORT Registry : public osg::Referenced void setDataFilePathList(const FilePathList& filepath) { _dataFilePath = filepath; } /** Set the data file path using a single string deliminated either with ';' (Windows) or ':' (All other platforms), which is used when search for data files.*/ - void setDataFilePathList(const std::string& paths) { _dataFilePath.clear(); convertStringPathIntoFilePathList(paths,_dataFilePath); } + void setDataFilePathList(const std::string& paths); /** get the data file path which is used when search for data files.*/ FilePathList& getDataFilePathList() { return _dataFilePath; } @@ -314,7 +314,7 @@ class OSGDB_EXPORT Registry : public osg::Referenced void setLibraryFilePathList(const FilePathList& filepath) { _libraryFilePath = filepath; } /** Set the library file path using a single string deliminated either with ';' (Windows) or ':' (All other platforms), which is used when search for data files.*/ - void setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); } + void setLibraryFilePathList(const std::string& paths); /** get the library file path which is used when search for library (dso/dll's) files.*/ FilePathList& getLibraryFilePathList() { return _libraryFilePath; } @@ -322,10 +322,6 @@ class OSGDB_EXPORT Registry : public osg::Referenced /** get the const library file path which is used when search for library (dso/dll's) files.*/ const FilePathList& getLibraryFilePathList() const { return _libraryFilePath; } - /** convert a string containing a list of paths deliminated either with ';' (Windows) or ':' (All other platforms) into FilePath represetation.*/ - static void convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath); - - /** For each object in the cache which has an reference count greater than 1 * (and therefore referenced by elsewhere in the application) set the time stamp * for that object in the cache to specified time. diff --git a/src/osgDB/FileUtils.cpp b/src/osgDB/FileUtils.cpp index 452f419f0..a93ad8b2a 100644 --- a/src/osgDB/FileUtils.cpp +++ b/src/osgDB/FileUtils.cpp @@ -39,6 +39,29 @@ #include +void osgDB::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath) +{ +#if defined(WIN32) && !defined(__CYGWIN__) + char delimitor = ';'; +#else + char delimitor = ':'; +#endif + + if (!paths.empty()) + { + std::string::size_type start = 0; + std::string::size_type end; + while ((end = paths.find_first_of(delimitor,start))!=std::string::npos) + { + filepath.push_back(std::string(paths,start,end-start)); + start = end+1; + } + + filepath.push_back(std::string(paths,start,std::string::npos)); + } + +} + bool osgDB::fileExists(const std::string& filename) { return access( filename.c_str(), F_OK ) == 0; @@ -271,3 +294,376 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st #endif // unix getDirectoryContexts #endif // ! target mac carbon + + + +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// Implementation of appendPlatformSpecificLibraryFilePaths(..) +// +#ifdef __sgi + + void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) + { + convertStringPathIntoFilePathList("/usr/lib32/:/usr/local/lib32/",filepath); + + // bloody mess see rld(1) man page + #if (_MIPS_SIM == _MIPS_SIM_ABI32) + + char* ptr; + if( (ptr = getenv( "LD_LIBRARY_PATH" ))) + { + convertStringPathIntoFilePathList(ptr,filepath); + } + + #elif (_MIPS_SIM == _MIPS_SIM_NABI32) + + if( !(ptr = getenv( "LD_LIBRARYN32_PATH" ))) + ptr = getenv( "LD_LIBRARY_PATH" ); + + if( ptr ) + { + convertStringPathIntoFilePathList(ptr,filepath); + } + + #elif (_MIPS_SIM == _MIPS_SIM_ABI64) + + if( !(ptr = getenv( "LD_LIBRARY64_PATH" ))) + ptr = getenv( "LD_LIBRARY_PATH" ); + + if( ptr ) + { + convertStringPathIntoFilePathList(ptr,filepath); + } + #endif + } + + +#elif defined(__CYGWIN__) + + void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) + { + char* ptr; + if ((ptr = getenv( "PATH" ))) + { + convertStringPathIntoFilePathList(ptr,filepath); + } + + convertStringPathIntoFilePathList("/usr/bin/:/usr/local/bin/",filepath); + + } + +#elif defined(WIN32) + + void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) + { + char* ptr; + if ((ptr = getenv( "PATH" ))) + { + convertStringPathIntoFilePathList(ptr,filepath); + } + + convertStringPathIntoFilePathList("C:/Windows/System/",filepath); + } + +#elif defined(__APPLE__) + + // The Cocoa version is about 10 lines of code. + // The Carbon version is noticably longer. + // Unfortunately, the Cocoa version requires -lobjc to be + // linked in when creating an executable. + // Rumor is that this will be done autmatically in gcc 3.5/Tiger, + // but for now, this will cause a lot of headaches for people + // who aren't familiar with this concept, so the Carbon version + // is preferable. + // But for the curious, both implementations are here. + // Note that if the Cocoa version is used, the file should be + // renamed to use the .mm extension to denote Objective-C++. + // And of course, you will need to link against Cocoa + + // #define COMPILE_COCOA_VERSION_WITH_OBJECT-C++ + #ifdef COMPILE_COCOA_VERSION_WITH_OBJECT-C++ + #include + // OS X has preferred locations for where PlugIns should be located. + // This function will set this as the order to search: + // YourProgram.app/Contents/PlugIns + // ~/Library/Application Support/OpenSceneGraph/PlugIns + // /Library/Application Support/OpenSceneGraph/PlugIns + // /Network/Library/Application Support/OpenSceneGraph/PlugIns + // + // As a side effect of this function, if the application is not a + // bundle, the first place searched becomes + // YourProgram/PlugIns + // + // In principle, these other directories should be searched: + // ~/Library/Application Support/YourProgram/PlugIns + // /Library/Application Support/YourProgram/PlugIns + // /Network/Library/Application Support/TheProgram/PlugIns + // But I'm not going to worry about it for now because the + // bundle's PlugIns directory is supposed to be the preferred + // place for this anyway. + // + // Another directory that might be worth considering is + // the directory the program resides in, + // but I'm worried about multiplatform distribution. + // Because .so is used by other platforms like Linux, we + // could end up loading the wrong binary. + // I'm not sure how robust the current code is for this case. + // Assuming the program doesn't crash, will OSG move on to the + // next search directory, or just give up? + void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) + { + char* ptr; + if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) ) + { + convertStringPathIntoFilePathList(ptr, filepath); + } + + // Since this is currently the only Objective-C code in the + // library, we need an autoreleasepool for obj-c memory management. + // If more Obj-C is added, we might move this pool to another + // location so it can be shared. Pools seem to be stackable, + // so I don't think there will be a problem if multiple pools + // exist at a time. + NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init]; + + NSString* myBundlePlugInPath; + NSString* userSupportDir; + + // This will grab the "official" bundle plug in path. + // It will be YourProgram.app/Contents/PlugIns (for App bundles) + // or YourProgram/PlugIns (for Unix executables) + myBundlePlugInPath = [[NSBundle mainBundle] builtInPlugInsPath]; + + // Now setup the other search paths + // Cocoa has a nice method for tilde expansion. + // There's probably a better way of getting this directory, but I + // can't find the call. + userSupportDir = [@"~/Library/Application Support/OpenSceneGraph/PlugIns" stringByExpandingTildeInPath]; + + // Can setup the remaining directories directly in C++ + + // Since Obj-C and C++ objects don't understand each other, + // the Obj-C strings must be converted down to C strings so + // C++ can make them into C++ strings. + filepath.push_back( [myBundlePlugInPath UTF8String] ); + filepath.push_back( [userSupportDir UTF8String] ); + + filepath.push_back( "/Library/Application Support/OpenSceneGraph/PlugIns" ); + filepath.push_back( "/Network/Library/Application Support/OpenSceneGraph/PlugIns" ); + + // Clean up the autorelease pool + [mypool release]; + } + + #else + + #include + // OS X has preferred locations for where PlugIns should be located. + // This function will set this as the order to search: + // YourProgram.app/Contents/PlugIns + // ~/Library/Application Support/OpenSceneGraph/PlugIns + // /Library/Application Support/OpenSceneGraph/PlugIns + // /Network/Library/Application Support/OpenSceneGraph/PlugIns + // + // As a side effect of this function, if the application is not a + // bundle, the first place searched becomes + // YourProgram/PlugIns + // + // In principle, these other directories should be searched: + // ~/Library/Application Support/YourProgram/PlugIns + // /Library/Application Support/YourProgram/PlugIns + // /Network/Library/Application Support/TheProgram/PlugIns + // But I'm not going to worry about it for now because the + // bundle's PlugIns directory is supposed to be the preferred + // place for this anyway. + // + // Another directory that might be worth considering is + // the directory the program resides in, + // but I'm worried about multiplatform distribution. + // Because .so is used by other platforms like Linux, we + // could end up loading the wrong binary. + // I'm not sure how robust the current code is for this case. + // Assuming the program doesn't crash, will OSG move on to the + // next search directory, or just give up? + void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) + { + char* ptr; + if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) ) + { + convertStringPathIntoFilePathList(ptr, filepath); + } + + const int MAX_OSX_PATH_SIZE = 1024; + const std::string OSG_PLUGIN_PATH("/OpenSceneGraph/PlugIns"); + char buffer[MAX_OSX_PATH_SIZE]; + char bundlePathBuffer[MAX_OSX_PATH_SIZE]; + CFURLRef url; + CFStringRef pathString; + CFBundleRef myBundle; + CFStringRef bundlePathString; + FSRef f; + OSErr errCode; + + // Start with the the Bundle PlugIns directory. + // Unlike the Cocoa API, it seems that the PlugIn path is relative + // and not absolute. So I will need to fetch both the bundle path + // (which is absolute) and the PlugIn path (which is relative), + // and combine the two to form a full path. + + // Get the bundle first + myBundle = CFBundleGetMainBundle(); + if(myBundle != NULL) + { + // Get the URL to the bundle + url = CFBundleCopyBundleURL( myBundle ); + + // Convert the URL to a CFString that looks like a Unix file path + bundlePathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); + // Convert the CFString to a C string + CFStringGetCString( bundlePathString, bundlePathBuffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 ); + + CFRelease( url ); + + // Now find the PlugIns directory + // Get the URL to the bundle + url = CFBundleCopyBuiltInPlugInsURL( myBundle ); + //pathString = CFURLCopyPath( url ); + // Convert the URL to a CFString that looks like a Unix file path + pathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); + // Convert the CFString to a C string + CFStringGetCString( pathString, buffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 ); + + // Combine the string and copy it into the FilePath list + filepath.push_back( + std::string(bundlePathBuffer) + + std::string("/") + + std::string(buffer) + ); + + CFRelease( pathString ); + CFRelease( bundlePathString ); + CFRelease( url ); + + // I was getting random crashes which I believe were caused by + // releasing the bundle. The documentation says I'm responsible + // for retaining and releasing which didn't immediately register + // in my head. I never retain the bundle, so I don't release it. + // CFRelease( myBundle ); + + pathString = NULL; + bundlePathString = NULL; + url = NULL; + // myBundle = NULL; + } + else + { + notify( DEBUG_INFO ) << "Couldn't find the Application Bundle" << std::endl; + } + + // Next, check the User's Application Support folder + errCode = FSFindFolder( kUserDomain, kApplicationSupportFolderType, kDontCreateFolder, &f ); + if(noErr == errCode) + { + // Get the URL + url = CFURLCreateFromFSRef( 0, &f ); + // Convert the URL to a CFString that looks like a Unix file path + pathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); + // Convert the CFString to a C string + CFStringGetCString( pathString, buffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 ); + + // Add the directory to the FilePathList + filepath.push_back( + std::string(buffer) + + OSG_PLUGIN_PATH + ); + + CFRelease( url ); + CFRelease( pathString ); + } + else + { + notify( DEBUG_INFO ) << "Couldn't find the User's Application Support Path" << std::endl; + } + + // Next, check the Local System's Application Support Folder + errCode = FSFindFolder( kLocalDomain, kApplicationSupportFolderType, kDontCreateFolder, &f ); + if(noErr == errCode) + { + // Get the URL + url = CFURLCreateFromFSRef( 0, &f ); + // Convert the URL to a CFString that looks like a Unix file path + pathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); + // Convert the CFString to a C string + CFStringGetCString( pathString, buffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 ); + + // Add the directory to the FilePathList + filepath.push_back( + std::string(buffer) + + OSG_PLUGIN_PATH + ); + + CFRelease( url ); + CFRelease( pathString ); + } + else + { + notify( DEBUG_INFO ) << "Couldn't find the Local System's Application Support Path" << std::endl; + } + + // Finally, check the Network Application Support Folder + // This one has a likely chance of not existing so an error + // may be returned. Don't panic. + errCode = FSFindFolder( kNetworkDomain, kApplicationSupportFolderType, kDontCreateFolder, &f ); + if(noErr == errCode) + { + // Get the URL + url = CFURLCreateFromFSRef( 0, &f ); + // Convert the URL to a CFString that looks like a Unix file path + pathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); + // Convert the CFString to a C string + CFStringGetCString( pathString, buffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 ); + + // Add the directory to the FilePathList + filepath.push_back( + std::string(buffer) + + OSG_PLUGIN_PATH + ); + + CFRelease( url ); + CFRelease( pathString ); + } + else + { + notify( DEBUG_INFO ) << "Couldn't find the Network Application Support Path" << std::endl; + } + } + + #endif + +#else + + void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath) + { + + char* ptr; + if( (ptr = getenv( "LD_LIBRARY_PATH" )) ) + { + convertStringPathIntoFilePathList(ptr,filepath); + } + + convertStringPathIntoFilePathList("/usr/lib/:/usr/local/lib/",filepath); + + } + +#endif + + + + + + + + + + diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index a4d793633..a9e83eeda 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -251,12 +251,21 @@ void Registry::initDataFilePathList() //PrintFilePathList(osg::notify(INFO),getDataFilePathList()); } +void Registry::setDataFilePathList(const std::string& paths) +{ + _dataFilePath.clear(); + convertStringPathIntoFilePathList(paths,_dataFilePath); +} + +void Registry::setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); } + #ifndef WIN32 static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [:path]..","Paths for locating libraries/ plugins"); #else static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH [;path]..","Paths for locating libraries/ plugins"); #endif + void Registry::initLibraryFilePathList() { // @@ -273,85 +282,15 @@ void Registry::initLibraryFilePathList() //notify(DEBUG_INFO) << "OSG_LD_LIBRARY_PATH("<