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 "filename.h"
#include "load_dso.h"
#include "string_utils.h"
#include "plist.h"
#include "pvector.h"
#include <algorithm>
@ -310,17 +311,49 @@ load_file_types() {
nassertv(load_file_type != (Config::ConfigTable::Symbol *)NULL);
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;
for (ti = load_file_type->begin(); ti != load_file_type->end(); ++ti) {
Filename dlname = Filename::dso_filename("lib" + (*ti).Val() + ".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;
string param = (*ti).Val();
if (already_read.insert(param).second) {
vector_string words;
extract_words(param, words);
if (words.size() == 1) {
// 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;
}
}

View File

@ -38,6 +38,18 @@ 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
// Access: Public, Virtual

View File

@ -43,6 +43,7 @@ public:
virtual string get_name() 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;

View File

@ -20,8 +20,8 @@
#include "loaderFileType.h"
#include "config_pgraph.h"
#include <string_utils.h>
#include <indent.h>
#include "string_utils.h"
#include "indent.h"
#include <algorithm>
@ -88,11 +88,41 @@ get_type(int n) const {
// the extension matches no known file types.
////////////////////////////////////////////////////////////////////
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;
ei = _extensions.find(downcase(extension));
ei = _extensions.find(dcextension);
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;
}
@ -119,6 +149,16 @@ write_types(ostream &out, int indent_level) const {
<< " ." << 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) {
// Make sure we haven't already registered this type.
if (find(_types.begin(), _types.end(), type) != _types.end()) {
loader_cat.warning()
loader_cat->info()
<< "Attempt to register LoaderFileType " << type->get_name()
<< " (" << type->get_type() << ") more than once.\n";
return;
@ -138,14 +178,77 @@ register_type(LoaderFileType *type) {
_types.push_back(type);
string extension = downcase(type->get_extension());
Extensions::const_iterator ei;
ei = _extensions.find(extension);
if (ei != _extensions.end()) {
loader_cat.warning()
<< "Multiple LoaderFileTypes registered that use the extension "
<< extension << "\n";
} else {
_extensions.insert(Extensions::value_type(extension, type));
record_extension(type->get_extension(), type);
vector_string words;
extract_words(type->get_additional_extensions(), words);
vector_string::const_iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
record_extension(*wi, 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
#define LOADERFILETYPEREGISTRY_H
#include <pandabase.h>
#include "pandabase.h"
#include "pvector.h"
#include "pmap.h"
@ -44,11 +44,15 @@ public:
int get_num_types() 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 register_type(LoaderFileType *type);
void register_deferred_type(const string &extension, const string &library);
private:
void record_extension(const string &extension, LoaderFileType *type);
private:
typedef pvector<LoaderFileType *> Types;
@ -57,6 +61,9 @@ private:
typedef pmap<string, LoaderFileType *> Extensions;
Extensions _extensions;
typedef pmap<string, string> DeferredTypes;
DeferredTypes _deferred_types;
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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Public

View File

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

View File

@ -151,6 +151,18 @@ get_extension() const {
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
// Access: Public, Virtual

View File

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

View File

@ -94,4 +94,21 @@
mayaPview.cxx mayaPview.h
#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 BUILDING_DLL BUILDING_PTLOADER
#define LOCAL_LIBS \
fltegg flt lwoegg lwo mayaegg converter pandatoolbase
fltegg flt lwoegg lwo converter pandatoolbase
#define OTHER_LIBS \
egg2pg:c builder:c egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
@ -11,10 +11,6 @@
#define UNIX_SYS_LIBS \
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 \
config_ptloader.cxx config_ptloader.h \
loaderFileTypePandatool.cxx loaderFileTypePandatool.h

View File

@ -19,9 +19,9 @@
#ifndef 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);

View File

@ -66,6 +66,18 @@ get_extension() const {
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
// Access: Public, Virtual

View File

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