support deferred loading of loader file types

This commit is contained in:
David Rose 2003-10-09 16:07:27 +00:00
parent e435834ec8
commit 25a599e3c9
14 changed files with 241 additions and 33 deletions

View File

@ -31,9 +31,10 @@
#include "circBuffer.h" #include "circBuffer.h"
#include "filename.h" #include "filename.h"
#include "load_dso.h" #include "load_dso.h"
#include "string_utils.h"
#include "plist.h" #include "plist.h"
#include "pvector.h" #include "pvector.h"
#include <algorithm> #include <algorithm>
@ -310,17 +311,49 @@ load_file_types() {
nassertv(load_file_type != (Config::ConfigTable::Symbol *)NULL); nassertv(load_file_type != (Config::ConfigTable::Symbol *)NULL);
if (!_file_types_loaded) { if (!_file_types_loaded) {
// When we use GetAll(), we might inadvertently read duplicate
// lines. Filter them out with a set.
pset<string> already_read;
Config::ConfigTable::Symbol::iterator ti; Config::ConfigTable::Symbol::iterator ti;
for (ti = load_file_type->begin(); ti != load_file_type->end(); ++ti) { for (ti = load_file_type->begin(); ti != load_file_type->end(); ++ti) {
Filename dlname = Filename::dso_filename("lib" + (*ti).Val() + ".so"); string param = (*ti).Val();
loader_cat.info() if (already_read.insert(param).second) {
<< "loading file type module: " << dlname.to_os_specific() << endl; vector_string words;
void *tmp = load_dso(dlname); extract_words(param, words);
if (tmp == (void *)NULL) {
loader_cat.info() if (words.size() == 1) {
<< "Unable to load: " << load_dso_error() << endl; // Exactly one word: load the named library immediately.
Filename dlname = Filename::dso_filename("lib" + words[0] + ".so");
loader_cat.info()
<< "loading file type module: " << dlname.to_os_specific() << endl;
void *tmp = load_dso(dlname);
if (tmp == (void *)NULL) {
loader_cat.info()
<< "Unable to load: " << load_dso_error() << endl;
}
} else if (words.size() > 1) {
// Multiple words: the first n words are filename extensions,
// and the last word is the name of the library to load should
// any of those filename extensions be encountered.
LoaderFileTypeRegistry *registry = LoaderFileTypeRegistry::get_ptr();
size_t num_extensions = words.size() - 1;
string library_name = words[num_extensions];
for (size_t i = 0; i < num_extensions; i++) {
string extension = words[i];
if (extension[0] == '.') {
extension = extension.substr(1);
}
registry->register_deferred_type(extension, library_name);
}
}
} }
} }
_file_types_loaded = true; _file_types_loaded = true;
} }
} }

View File

@ -38,6 +38,18 @@ LoaderFileType::
~LoaderFileType() { ~LoaderFileType() {
} }
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::get_additional_extensions
// Access: Public, Virtual
// Description: Returns a space-separated list of extension, in
// addition to the one returned by get_extension(), that
// are recognized by this loader.
////////////////////////////////////////////////////////////////////
string LoaderFileType::
get_additional_extensions() const {
return string();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::load_file // Function: LoaderFileType::load_file
// Access: Public, Virtual // Access: Public, Virtual

View File

@ -43,6 +43,7 @@ public:
virtual string get_name() const=0; virtual string get_name() const=0;
virtual string get_extension() const=0; virtual string get_extension() const=0;
virtual string get_additional_extensions() const;
virtual PT(PandaNode) load_file(const Filename &path, bool report_errors) const; virtual PT(PandaNode) load_file(const Filename &path, bool report_errors) const;

View File

@ -20,8 +20,8 @@
#include "loaderFileType.h" #include "loaderFileType.h"
#include "config_pgraph.h" #include "config_pgraph.h"
#include <string_utils.h> #include "string_utils.h"
#include <indent.h> #include "indent.h"
#include <algorithm> #include <algorithm>
@ -88,11 +88,41 @@ get_type(int n) const {
// the extension matches no known file types. // the extension matches no known file types.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
LoaderFileType *LoaderFileTypeRegistry:: LoaderFileType *LoaderFileTypeRegistry::
get_type_from_extension(const string &extension) const { get_type_from_extension(const string &extension) {
string dcextension = downcase(extension);
Extensions::const_iterator ei; Extensions::const_iterator ei;
ei = _extensions.find(downcase(extension)); ei = _extensions.find(dcextension);
if (ei == _extensions.end()) { if (ei == _extensions.end()) {
// Nothing matches that extension. // Nothing matches that extension. Do we have a deferred type?
DeferredTypes::iterator di;
di = _deferred_types.find(dcextension);
if (di != _deferred_types.end()) {
// We do! Try to load the deferred library on-the-fly. Note
// that this is a race condition if we support threaded loading;
// this whole function needs to be protected from multiple
// entry.
Filename dlname = Filename::dso_filename("lib" + (*di).second + ".so");
_deferred_types.erase(di);
loader_cat->info()
<< "loading file type module: " << dlname.to_os_specific() << endl;
void *tmp = load_dso(dlname);
if (tmp == (void *)NULL) {
loader_cat->info()
<< "Unable to load: " << load_dso_error() << endl;
return NULL;
}
// Now try again to find the LoaderFileType.
ei = _extensions.find(dcextension);
}
}
if (ei == _extensions.end()) {
// Nothing matches that extension, even after we've checked for a
// deferred type description.
return NULL; return NULL;
} }
@ -119,6 +149,16 @@ write_types(ostream &out, int indent_level) const {
<< " ." << type->get_extension() << "\n"; << " ." << type->get_extension() << "\n";
} }
} }
if (!_deferred_types.empty()) {
indent(out, indent_level) << "Also available:";
DeferredTypes::const_iterator di;
for (di = _deferred_types.begin(); di != _deferred_types.end(); ++di) {
const string &extension = (*di).first;
out << " ." << extension;
}
out << "\n";
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -130,7 +170,7 @@ void LoaderFileTypeRegistry::
register_type(LoaderFileType *type) { register_type(LoaderFileType *type) {
// Make sure we haven't already registered this type. // Make sure we haven't already registered this type.
if (find(_types.begin(), _types.end(), type) != _types.end()) { if (find(_types.begin(), _types.end(), type) != _types.end()) {
loader_cat.warning() loader_cat->info()
<< "Attempt to register LoaderFileType " << type->get_name() << "Attempt to register LoaderFileType " << type->get_name()
<< " (" << type->get_type() << ") more than once.\n"; << " (" << type->get_type() << ") more than once.\n";
return; return;
@ -138,14 +178,77 @@ register_type(LoaderFileType *type) {
_types.push_back(type); _types.push_back(type);
string extension = downcase(type->get_extension()); record_extension(type->get_extension(), type);
Extensions::const_iterator ei;
ei = _extensions.find(extension); vector_string words;
if (ei != _extensions.end()) { extract_words(type->get_additional_extensions(), words);
loader_cat.warning() vector_string::const_iterator wi;
<< "Multiple LoaderFileTypes registered that use the extension " for (wi = words.begin(); wi != words.end(); ++wi) {
<< extension << "\n"; record_extension(*wi, type);
} else {
_extensions.insert(Extensions::value_type(extension, type));
} }
} }
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeRegistry::register_deferred_type
// Access: Public
// Description: Records a type associated with a particular extension
// to be loaded in the future. The named library will
// be dynamically loaded the first time files of this
// extension are loaded; presumably this library will
// call register_type() when it initializes, thus making
// the extension loadable.
////////////////////////////////////////////////////////////////////
void LoaderFileTypeRegistry::
register_deferred_type(const string &extension, const string &library) {
string dcextension = downcase(extension);
Extensions::const_iterator ei;
ei = _extensions.find(dcextension);
if (ei != _extensions.end()) {
// We already have a loader for this type; no need to register
// another one.
loader_cat->info()
<< "Attempt to register loader library " << library
<< " (" << dcextension << ") when extension is already known.\n";
return;
}
DeferredTypes::const_iterator di;
di = _deferred_types.find(dcextension);
if (di != _deferred_types.end()) {
if ((*di).second == library) {
loader_cat->info()
<< "Attempt to register loader library " << library
<< " (" << dcextension << ") more than once.\n";
return;
} else {
loader_cat->info()
<< "Multiple libraries registered that use the extension "
<< dcextension << "\n";
}
}
_deferred_types[dcextension] = library;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeRegistry::record_extension
// Access: Private
// Description: Records a filename extension recognized by a loader
// file type.
////////////////////////////////////////////////////////////////////
void LoaderFileTypeRegistry::
record_extension(const string &extension, LoaderFileType *type) {
string dcextension = downcase(extension);
Extensions::const_iterator ei;
ei = _extensions.find(dcextension);
if (ei != _extensions.end()) {
loader_cat->info()
<< "Multiple LoaderFileTypes registered that use the extension "
<< dcextension << "\n";
} else {
_extensions.insert(Extensions::value_type(dcextension, type));
}
_deferred_types.erase(dcextension);
}

View File

@ -19,7 +19,7 @@
#ifndef LOADERFILETYPEREGISTRY_H #ifndef LOADERFILETYPEREGISTRY_H
#define LOADERFILETYPEREGISTRY_H #define LOADERFILETYPEREGISTRY_H
#include <pandabase.h> #include "pandabase.h"
#include "pvector.h" #include "pvector.h"
#include "pmap.h" #include "pmap.h"
@ -44,11 +44,15 @@ public:
int get_num_types() const; int get_num_types() const;
LoaderFileType *get_type(int n) const; LoaderFileType *get_type(int n) const;
LoaderFileType *get_type_from_extension(const string &extension) const; LoaderFileType *get_type_from_extension(const string &extension);
void write_types(ostream &out, int indent_level = 0) const; void write_types(ostream &out, int indent_level = 0) const;
void register_type(LoaderFileType *type); void register_type(LoaderFileType *type);
void register_deferred_type(const string &extension, const string &library);
private:
void record_extension(const string &extension, LoaderFileType *type);
private: private:
typedef pvector<LoaderFileType *> Types; typedef pvector<LoaderFileType *> Types;
@ -57,6 +61,9 @@ private:
typedef pmap<string, LoaderFileType *> Extensions; typedef pmap<string, LoaderFileType *> Extensions;
Extensions _extensions; Extensions _extensions;
typedef pmap<string, string> DeferredTypes;
DeferredTypes _deferred_types;
static LoaderFileTypeRegistry *_global_ptr; static LoaderFileTypeRegistry *_global_ptr;
}; };

View File

@ -90,6 +90,18 @@ set_egg_data(EggData *egg_data, bool owns_egg_data) {
_owns_egg_data = owns_egg_data; _owns_egg_data = owns_egg_data;
} }
////////////////////////////////////////////////////////////////////
// Function: SomethingToEggConverter::get_additional_extensions
// Access: Public, Virtual
// Description: Returns a space-separated list of extension, in
// addition to the one returned by get_extension(), that
// are recognized by this converter.
////////////////////////////////////////////////////////////////////
string SomethingToEggConverter::
get_additional_extensions() const {
return string();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SomethingToEggConverter::handle_external_reference // Function: SomethingToEggConverter::handle_external_reference
// Access: Public // Access: Public

View File

@ -101,6 +101,7 @@ public:
virtual string get_name() const=0; virtual string get_name() const=0;
virtual string get_extension() const=0; virtual string get_extension() const=0;
virtual string get_additional_extensions() const;
virtual bool convert_file(const Filename &filename)=0; virtual bool convert_file(const Filename &filename)=0;

View File

@ -151,6 +151,18 @@ get_extension() const {
return "mb"; return "mb";
} }
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_additional_extensions
// Access: Public, Virtual
// Description: Returns a space-separated list of extension, in
// addition to the one returned by get_extension(), that
// are recognized by this converter.
////////////////////////////////////////////////////////////////////
string MayaToEggConverter::
get_additional_extensions() const {
return "ma";
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::convert_file // Function: MayaToEggConverter::convert_file
// Access: Public, Virtual // Access: Public, Virtual

View File

@ -70,6 +70,7 @@ public:
virtual string get_name() const; virtual string get_name() const;
virtual string get_extension() const; virtual string get_extension() const;
virtual string get_additional_extensions() const;
virtual bool convert_file(const Filename &filename); virtual bool convert_file(const Filename &filename);
bool convert_maya(bool from_selection); bool convert_maya(bool from_selection);

View File

@ -94,4 +94,21 @@
mayaPview.cxx mayaPview.h mayaPview.cxx mayaPview.h
#end lib_target #end lib_target
#begin lib_target
#define USE_PACKAGES maya
#define TARGET mayaloader
#define BUILDING_DLL BUILDING_MISC
#define LOCAL_LIBS \
mayaegg ptloader converter pandatoolbase
#define OTHER_LIBS \
egg2pg:c builder:c egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
express:c pandaexpress:m \
dtoolconfig dtool \
$[if $[UNIX_PLATFORM],OpenMayalib]
#define SOURCES \
config_mayaloader.cxx
#end lib_target

View File

@ -2,7 +2,7 @@
#define TARGET ptloader #define TARGET ptloader
#define BUILDING_DLL BUILDING_PTLOADER #define BUILDING_DLL BUILDING_PTLOADER
#define LOCAL_LIBS \ #define LOCAL_LIBS \
fltegg flt lwoegg lwo mayaegg converter pandatoolbase fltegg flt lwoegg lwo converter pandatoolbase
#define OTHER_LIBS \ #define OTHER_LIBS \
egg2pg:c builder:c egg:c pandaegg:m \ egg2pg:c builder:c egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \ mathutil:c linmath:c putil:c panda:m \
@ -11,10 +11,6 @@
#define UNIX_SYS_LIBS \ #define UNIX_SYS_LIBS \
m m
// If we've got Maya, link in the Maya libraries.
// On second thought, don't. It takes forever to load.
//#define USE_PACKAGES maya
#define SOURCES \ #define SOURCES \
config_ptloader.cxx config_ptloader.h \ config_ptloader.cxx config_ptloader.h \
loaderFileTypePandatool.cxx loaderFileTypePandatool.h loaderFileTypePandatool.cxx loaderFileTypePandatool.h

View File

@ -19,9 +19,9 @@
#ifndef CONFIG_PTLOADER_H #ifndef CONFIG_PTLOADER_H
#define CONFIG_PTLOADER_H #define CONFIG_PTLOADER_H
#include <pandatoolbase.h> #include "pandatoolbase.h"
#include <dconfig.h> #include "dconfig.h"
ConfigureDecl(config_ptloader, EXPCL_PTLOADER, EXPTP_PTLOADER); ConfigureDecl(config_ptloader, EXPCL_PTLOADER, EXPTP_PTLOADER);

View File

@ -66,6 +66,18 @@ get_extension() const {
return _converter->get_extension(); return _converter->get_extension();
} }
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypePandatool::get_additional_extensions
// Access: Public, Virtual
// Description: Returns a space-separated list of extension, in
// addition to the one returned by get_extension(), that
// are recognized by this converter.
////////////////////////////////////////////////////////////////////
string LoaderFileTypePandatool::
get_additional_extensions() const {
return _converter->get_additional_extensions();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypePandatool::resolve_filename // Function: LoaderFileTypePandatool::resolve_filename
// Access: Public, Virtual // Access: Public, Virtual

View File

@ -39,6 +39,7 @@ public:
virtual string get_name() const; virtual string get_name() const;
virtual string get_extension() const; virtual string get_extension() const;
virtual string get_additional_extensions() const;
virtual void resolve_filename(Filename &path) const; virtual void resolve_filename(Filename &path) const;
virtual PT(PandaNode) load_file(const Filename &path, bool report_errors) const; virtual PT(PandaNode) load_file(const Filename &path, bool report_errors) const;