diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx
index a7a45befc9..c5c21fe9dd 100755
--- a/direct/src/plugin/load_plugin.cxx
+++ b/direct/src/plugin/load_plugin.cxx
@@ -123,7 +123,8 @@ static void unload_dso();
// path.
////////////////////////////////////////////////////////////////////
bool
-load_plugin(const string &p3d_plugin_filename) {
+load_plugin(const string &p3d_plugin_filename,
+ const string &contents_filename) {
string filename = p3d_plugin_filename;
if (filename.empty()) {
// Look for the plugin along the path.
@@ -292,26 +293,7 @@ load_plugin(const string &p3d_plugin_filename) {
// Successfully loaded.
plugin_loaded = true;
-#ifdef P3D_PLUGIN_LOGFILE2
- string logfilename = P3D_PLUGIN_LOGFILE2;
-#else
- string logfilename;
-#endif // P3D_PLUGIN_LOGFILE2
-
- if (logfilename.empty()) {
-#ifdef _WIN32
- static const size_t buffer_size = 4096;
- char buffer[buffer_size];
- if (GetTempPath(buffer_size, buffer) != 0) {
- logfilename = buffer;
- logfilename += "panda3d.2.log";
- }
-#else
- logfilename = "/tmp/panda3d.2.log";
-#endif // _WIN32
- }
-
- if (!P3D_initialize(P3D_API_VERSION, logfilename.c_str())) {
+ if (!P3D_initialize(P3D_API_VERSION, contents_filename.c_str())) {
// Oops, failure to initialize.
cerr << "Failed to initialize plugin (wrong API version?)\n";
unload_plugin();
diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h
index 4edf19ecd7..59562f31df 100755
--- a/direct/src/plugin/load_plugin.h
+++ b/direct/src/plugin/load_plugin.h
@@ -58,7 +58,8 @@ extern P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream;
extern P3D_instance_handle_event_func *P3D_instance_handle_event;
string get_plugin_basename();
-bool load_plugin(const string &p3d_plugin_filename);
+bool load_plugin(const string &p3d_plugin_filename,
+ const string &contents_filename);
void unload_plugin();
bool is_plugin_loaded();
diff --git a/direct/src/plugin/make_contents.py b/direct/src/plugin/make_contents.py
index cfb7408e3f..a4ce5d88cf 100755
--- a/direct/src/plugin/make_contents.py
+++ b/direct/src/plugin/make_contents.py
@@ -54,9 +54,9 @@ class ContentsMaker:
print >> f, ''
print >> f, ''
print >> f, ''
- for packageName, packageVersion, packagePlatform, file in self.packages:
- print >> f, ' ' % (
- packageName, packageVersion, packagePlatform or '', file.getParams())
+ for packageName, packagePlatform, packageVersion, file in self.packages:
+ print >> f, ' ' % (
+ packageName, packagePlatform or '', packageVersion, file.getParams())
print >> f, ''
f.close()
@@ -93,14 +93,14 @@ class ContentsMaker:
file = FileSpec(localpath + xml,
Filename(self.stageDir, localpath + xml))
print file.filename
- self.packages.append((packageName, packageVersion, packagePlatform, file))
+ self.packages.append((packageName, packagePlatform, packageVersion, file))
if localpath.count('/') == 3:
- packageName, packageVersion, packagePlatform, junk = localpath.split('/')
+ packageName, packagePlatform, packageVersion, junk = localpath.split('/')
file = FileSpec(localpath + xml,
Filename(self.stageDir, localpath + xml))
print file.filename
- self.packages.append((packageName, packageVersion, packagePlatform, file))
+ self.packages.append((packageName, packagePlatform, packageVersion, file))
def makeContents(args):
diff --git a/direct/src/plugin/make_package.py b/direct/src/plugin/make_package.py
index f4ea98b00e..e9933a6424 100755
--- a/direct/src/plugin/make_package.py
+++ b/direct/src/plugin/make_package.py
@@ -77,8 +77,9 @@ class PackageMaker:
self.packageStageDir = Filename(self.stageDir, '%s/%s' % (self.packageName, self.packageVersion))
if self.packagePlatform:
- self.packageFullname += '_%s' % (self.packagePlatform)
- self.packageStageDir = Filename(self.packageStageDir, self.packagePlatform)
+ self.packageFullname = '%s_%s_%s' % (
+ self.packageName, self.packagePlatform, self.packageVersion)
+ self.packageStageDir = Filename(self.stageDir, '%s/%s/%s' % (self.packageName, self.packagePlatform, self.packageVersion))
Filename(self.packageStageDir, '.').makeDir()
self.cleanDir(self.packageStageDir)
@@ -121,7 +122,7 @@ class PackageMaker:
f = open(descFilePathname.toOsSpecific(), 'w')
print >> f, ''
print >> f, ''
- print >> f, '' % (self.packageName, self.packageVersion, self.packagePlatform or '')
+ print >> f, '' % (self.packageName, self.packagePlatform or '', self.packageVersion)
print >> f, ' ' % (uncompressedArchive.getParams())
print >> f, ' ' % (compressedArchive.getParams())
for file in self.components:
@@ -209,9 +210,9 @@ def makePackage(args):
if len(tokens) >= 1:
pm.packageName = tokens[0]
if len(tokens) >= 2:
- pm.packageVersion = tokens[1]
- if len(tokens) >= 3:
pm.packagePlatform = tokens[2]
+ if len(tokens) >= 3:
+ pm.packageVersion = tokens[1]
if len(tokens) >= 4:
raise ArgumentError, 'Too many tokens in string: %s' % (value)
diff --git a/direct/src/plugin/mkdir_complete.cxx b/direct/src/plugin/mkdir_complete.cxx
index 56b0179925..bdcded13a2 100755
--- a/direct/src/plugin/mkdir_complete.cxx
+++ b/direct/src/plugin/mkdir_complete.cxx
@@ -85,7 +85,7 @@ mkdir_complete(const string &dirname, ostream &logfile) {
return false;
#else //_WIN32
- if (mkdir(dirname.c_str(), 0777) == 0) {
+ if (mkdir(dirname.c_str(), 0755) == 0) {
// Success!
return true;
}
@@ -101,7 +101,7 @@ mkdir_complete(const string &dirname, ostream &logfile) {
string parent = get_dirname(dirname);
if (!parent.empty() && mkdir_complete(parent, logfile)) {
// Parent successfully created. Try again to make the child.
- if (mkdir(dirname.c_str(), 0777) == 0) {
+ if (mkdir(dirname.c_str(), 0755) == 0) {
// Got it!
return true;
}
@@ -147,13 +147,13 @@ mkfile_complete(const string &filename, ostream &logfile) {
return true;
#else // _WIN32
- int fd = creat(filename.c_str(), 0777);
+ int fd = creat(filename.c_str(), 0755);
if (fd == -1) {
// Try to make the parent directory first.
string parent = get_dirname(filename);
if (!parent.empty() && mkdir_complete(parent, logfile)) {
// Parent successfully created. Try again to make the file.
- fd = creat(filename.c_str(), 0777);
+ fd = creat(filename.c_str(), 0755);
}
if (fd == -1) {
logfile
diff --git a/direct/src/plugin/p3dDownload.cxx b/direct/src/plugin/p3dDownload.cxx
index d925d8ca06..bc19c3e3b4 100755
--- a/direct/src/plugin/p3dDownload.cxx
+++ b/direct/src/plugin/p3dDownload.cxx
@@ -131,6 +131,8 @@ download_progress() {
if (now != _last_reported_time || true) {
_last_reported_time = now;
}
+ nout << "Downloading " << get_url() << ": "
+ << int(get_download_progress() * 1000.0) / 10.0 << "\n";
}
////////////////////////////////////////////////////////////////////
@@ -143,6 +145,6 @@ download_progress() {
////////////////////////////////////////////////////////////////////
void P3DDownload::
download_finished(bool success) {
- nout << "Downloading " << get_url() << ": "
+ nout << "Downloaded " << get_url() << ": "
<< int(get_download_progress() * 1000.0) / 10.0 << "\n";
}
diff --git a/direct/src/plugin/p3dFileParams.cxx b/direct/src/plugin/p3dFileParams.cxx
index 7f953fafe0..38325b92cb 100644
--- a/direct/src/plugin/p3dFileParams.cxx
+++ b/direct/src/plugin/p3dFileParams.cxx
@@ -25,15 +25,47 @@ P3DFileParams() {
}
////////////////////////////////////////////////////////////////////
-// Function: P3DFileParams::Constructor
+// Function: P3DFileParams::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
P3DFileParams::
-P3DFileParams(const string &p3d_filename,
- const P3D_token tokens[], size_t num_tokens) :
- _p3d_filename(p3d_filename)
+P3DFileParams(const P3DFileParams ©) :
+ _p3d_filename(copy._p3d_filename),
+ _tokens(copy._tokens)
{
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: P3DFileParams::Copy Assignment
+// Access: Public
+// Description:
+////////////////////////////////////////////////////////////////////
+void P3DFileParams::
+operator = (const P3DFileParams &other) {
+ _p3d_filename = other._p3d_filename;
+ _tokens = other._tokens;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: P3DFileParams::set_p3d_filename
+// Access: Public
+// Description: Specifies the file that contains the instance data.
+////////////////////////////////////////////////////////////////////
+void P3DFileParams::
+set_p3d_filename(const string &p3d_filename) {
+ _p3d_filename = p3d_filename;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: P3DFileParams::set_tokens
+// Access: Public
+// Description: Specifies the tokens associated with the instance.
+////////////////////////////////////////////////////////////////////
+void P3DFileParams::
+set_tokens(const P3D_token tokens[], size_t num_tokens) {
+ _tokens.clear();
+
for (size_t i = 0; i < num_tokens; ++i) {
Token token;
if (tokens[i]._keyword != NULL) {
@@ -50,17 +82,6 @@ P3DFileParams(const string &p3d_filename,
}
}
-////////////////////////////////////////////////////////////////////
-// Function: P3DFileParams::Copy Assignment
-// Access: Public
-// Description:
-////////////////////////////////////////////////////////////////////
-void P3DFileParams::
-operator = (const P3DFileParams &other) {
- _p3d_filename = other._p3d_filename;
- _tokens = other._tokens;
-}
-
////////////////////////////////////////////////////////////////////
// Function: P3DFileParams::lookup_token
// Access: Public
diff --git a/direct/src/plugin/p3dFileParams.h b/direct/src/plugin/p3dFileParams.h
index 674affea7c..7495d3631c 100644
--- a/direct/src/plugin/p3dFileParams.h
+++ b/direct/src/plugin/p3dFileParams.h
@@ -27,11 +27,12 @@
class P3DFileParams {
public:
P3DFileParams();
- P3DFileParams(const string &p3d_filename,
- const P3D_token tokens[], size_t num_tokens);
-
+ P3DFileParams(const P3DFileParams ©);
void operator = (const P3DFileParams &other);
+ void set_p3d_filename(const string &p3d_filename);
+ void set_tokens(const P3D_token tokens[], size_t num_tokens);
+
inline const string &get_p3d_filename() const;
string lookup_token(const string &keyword) const;
bool has_token(const string &keyword) const;
diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx
index 6e858cd26f..f2fbd1df80 100644
--- a/direct/src/plugin/p3dInstance.cxx
+++ b/direct/src/plugin/p3dInstance.cxx
@@ -49,7 +49,8 @@ typedef P3DSplashWindow SplashWindowType;
// Description:
////////////////////////////////////////////////////////////////////
P3DInstance::
-P3DInstance(P3D_request_ready_func *func, void *user_data) :
+P3DInstance(P3D_request_ready_func *func,
+ const P3D_token tokens[], size_t num_tokens, void *user_data) :
_func(func)
{
_browser_script_object = NULL;
@@ -59,6 +60,8 @@ P3DInstance(P3D_request_ready_func *func, void *user_data) :
_got_fparams = false;
_got_wparams = false;
+ _fparams.set_tokens(tokens, num_tokens);
+
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
_instance_id = inst_mgr->get_unique_id();
@@ -137,16 +140,17 @@ P3DInstance::
// download is still running? Who will crash when this happens?
}
+
////////////////////////////////////////////////////////////////////
-// Function: P3DInstance::set_fparams
+// Function: P3DInstance::set_p3d_filename
// Access: Public
-// Description: Sets up the initial file parameters for the instance.
+// Description: Specifies the file that contains the instance data.
// Normally this is only called once.
////////////////////////////////////////////////////////////////////
void P3DInstance::
-set_fparams(const P3DFileParams &fparams) {
+set_p3d_filename(const string &p3d_filename) {
_got_fparams = true;
- _fparams = fparams;
+ _fparams.set_p3d_filename(p3d_filename);
// This also sets up some internal data based on the contents of the
// above file and the associated tokens.
@@ -176,13 +180,6 @@ set_fparams(const P3DFileParams &fparams) {
P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
P3D_OBJECT_XDECREF(result);
}
-
- // Maybe create the splash window.
- if (!_instance_window_opened && _got_wparams) {
- if (_splash_window == NULL) {
- make_splash_window();
- }
- }
}
////////////////////////////////////////////////////////////////////
@@ -198,7 +195,7 @@ set_wparams(const P3DWindowParams &wparams) {
_wparams = wparams;
// Update or create the splash window.
- if (!_instance_window_opened && _got_fparams) {
+ if (!_instance_window_opened) {
if (_splash_window == NULL) {
make_splash_window();
}
diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h
index 33c8b09a0d..71ac83145c 100644
--- a/direct/src/plugin/p3dInstance.h
+++ b/direct/src/plugin/p3dInstance.h
@@ -44,10 +44,11 @@ class P3DToplevelObject;
////////////////////////////////////////////////////////////////////
class P3DInstance : public P3D_instance, public P3DReferenceCount {
public:
- P3DInstance(P3D_request_ready_func *func, void *user_data);
+ P3DInstance(P3D_request_ready_func *func,
+ const P3D_token tokens[], size_t num_tokens, void *user_data);
~P3DInstance();
- void set_fparams(const P3DFileParams &fparams);
+ void set_p3d_filename(const string &p3d_filename);
inline const P3DFileParams &get_fparams() const;
void set_wparams(const P3DWindowParams &wparams);
diff --git a/direct/src/plugin/p3dInstanceManager.I b/direct/src/plugin/p3dInstanceManager.I
index b816349824..706b69120f 100644
--- a/direct/src/plugin/p3dInstanceManager.I
+++ b/direct/src/plugin/p3dInstanceManager.I
@@ -60,6 +60,17 @@ get_platform() const {
return _platform;
}
+////////////////////////////////////////////////////////////////////
+// Function: P3DInstanceManager::has_contents_file
+// Access: Public
+// Description: Returns true if a contents.xml file has been
+// successfully read, false otherwise.
+////////////////////////////////////////////////////////////////////
+inline bool P3DInstanceManager::
+has_contents_file() const {
+ return (_xcontents != NULL);
+}
+
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_num_instances
// Access: Public
diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx
index f4c7cb0e20..df51e23c76 100644
--- a/direct/src/plugin/p3dInstanceManager.cxx
+++ b/direct/src/plugin/p3dInstanceManager.cxx
@@ -22,6 +22,9 @@
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "find_root_dir.h"
+#include "mkdir_complete.h"
+#include "fileSpec.h"
+#include "get_tinyxml.h"
#ifdef _WIN32
#include
@@ -40,6 +43,7 @@ P3DInstanceManager::
P3DInstanceManager() {
_is_initialized = false;
_unique_id = 0;
+ _xcontents = NULL;
_notify_thread_continue = false;
_started_notify_thread = false;
@@ -77,6 +81,10 @@ P3DInstanceManager::
_started_notify_thread = false;
}
+ if (_xcontents != NULL) {
+ delete _xcontents;
+ }
+
assert(_instances.empty());
assert(_sessions.empty());
@@ -112,13 +120,14 @@ P3DInstanceManager::
// redownloaded.
////////////////////////////////////////////////////////////////////
bool P3DInstanceManager::
-initialize() {
+initialize(const string &contents_filename) {
_root_dir = find_root_dir();
_download_url = P3D_PLUGIN_DOWNLOAD;
_platform = P3D_PLUGIN_PLATFORM;
- nout << "_root_dir = " << _root_dir << ", download = "
- << _download_url << "\n";
+ nout << "_root_dir = " << _root_dir
+ << ", download = " << _download_url
+ << ", contents = " << contents_filename << "\n";
if (_root_dir.empty()) {
nout << "Could not find root directory.\n";
@@ -127,6 +136,47 @@ initialize() {
_is_initialized = true;
+ // Attempt to read the supplied contents.xml file.
+ if (!contents_filename.empty()) {
+ if (!read_contents_file(contents_filename)) {
+ nout << "Couldn't read " << contents_filename << "\n";
+ }
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: P3DInstanceManager::read_contents_file
+// Access: Public
+// Description: Reads the contents.xml file in the indicated
+// filename. On success, copies the contents.xml file
+// into the standard location.
+//
+// Returns true on success, false on failure.
+////////////////////////////////////////////////////////////////////
+bool P3DInstanceManager::
+read_contents_file(const string &contents_filename) {
+ TiXmlDocument doc(contents_filename.c_str());
+ if (!doc.LoadFile()) {
+ return false;
+ }
+
+ TiXmlElement *xcontents = doc.FirstChildElement("contents");
+ if (xcontents == NULL) {
+ return false;
+ }
+
+ if (_xcontents != NULL) {
+ delete _xcontents;
+ }
+ _xcontents = (TiXmlElement *)xcontents->Clone();
+
+ string standard_filename = _root_dir + "/contents.xml";
+ if (standard_filename != contents_filename) {
+ copy_file(contents_filename, standard_filename);
+ }
+
return true;
}
@@ -137,8 +187,10 @@ initialize() {
// indicated startup information.
////////////////////////////////////////////////////////////////////
P3DInstance *P3DInstanceManager::
-create_instance(P3D_request_ready_func *func, void *user_data) {
- P3DInstance *inst = new P3DInstance(func, user_data);
+create_instance(P3D_request_ready_func *func,
+ const P3D_token tokens[], size_t num_tokens,
+ void *user_data) {
+ P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, user_data);
inst->ref();
_instances.insert(inst);
@@ -154,13 +206,12 @@ create_instance(P3D_request_ready_func *func, void *user_data) {
// particular instance.
////////////////////////////////////////////////////////////////////
bool P3DInstanceManager::
-start_instance(P3DInstance *inst, const string &p3d_filename,
- const P3D_token tokens[], size_t num_tokens) {
+start_instance(P3DInstance *inst, const string &p3d_filename) {
if (inst->is_started()) {
nout << "Instance started twice: " << inst << "\n";
return false;
}
- inst->set_fparams(P3DFileParams(p3d_filename, tokens, num_tokens));
+ inst->set_p3d_filename(p3d_filename);
P3DSession *session;
Sessions::iterator si = _sessions.find(inst->get_session_key());
@@ -192,16 +243,17 @@ finish_instance(P3DInstance *inst) {
_instances.erase(ii);
Sessions::iterator si = _sessions.find(inst->get_session_key());
- assert(si != _sessions.end());
- P3DSession *session = (*si).second;
- session->terminate_instance(inst);
+ if (si != _sessions.end()) {
+ P3DSession *session = (*si).second;
+ session->terminate_instance(inst);
- // If that was the last instance in this session, terminate the
- // session.
- if (session->get_num_instances() == 0) {
- _sessions.erase(session->get_session_key());
- session->shutdown();
- unref_delete(session);
+ // If that was the last instance in this session, terminate the
+ // session.
+ if (session->get_num_instances() == 0) {
+ _sessions.erase(session->get_session_key());
+ session->shutdown();
+ unref_delete(session);
+ }
}
unref_delete(inst);
@@ -284,20 +336,61 @@ P3DPackage *P3DInstanceManager::
get_package(const string &package_name, const string &package_version,
const string &package_display_name) {
string package_platform = get_platform();
- string key = package_name + "_" + package_version + "_" + package_platform;
+ string key = package_name + "_" + package_platform + "_" + package_version;
Packages::iterator pi = _packages.find(key);
if (pi != _packages.end()) {
return (*pi).second;
}
- P3DPackage *package = new P3DPackage(package_name, package_version,
- package_platform, package_display_name);
+ P3DPackage *package = new P3DPackage(package_name, package_platform,
+ package_version, package_display_name);
bool inserted = _packages.insert(Packages::value_type(key, package)).second;
assert(inserted);
return package;
}
+////////////////////////////////////////////////////////////////////
+// Function: P3DInstanceManager::get_package_desc_file
+// Access: Public
+// Description: Fills the indicated FileSpec with the hash
+// information for the package's desc file. Returns
+// true if successful, false if the package is unknown.
+// This requires has_contents_file() to return true in
+// order to be successful.
+////////////////////////////////////////////////////////////////////
+bool P3DInstanceManager::
+get_package_desc_file(FileSpec &desc_file,
+ const string &package_name,
+ const string &package_version) {
+ if (_xcontents == NULL) {
+ return false;
+ }
+
+ string package_platform = get_platform();
+
+ // Scan the contents data for the indicated package.
+ TiXmlElement *xpackage = _xcontents->FirstChildElement("package");
+ while (xpackage != NULL) {
+ const char *name = xpackage->Attribute("name");
+ const char *platform = xpackage->Attribute("platform");
+ const char *version = xpackage->Attribute("version");
+ if (name != NULL && platform != NULL && version != NULL &&
+ package_name == name &&
+ package_platform == platform &&
+ package_version == version) {
+ // Here's the matching package definition.
+ desc_file.load_xml(xpackage);
+ return true;
+ }
+
+ xpackage = xpackage->NextSiblingElement("package");
+ }
+
+ // Couldn't find the named package.
+ return false;
+}
+
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_unique_id
// Access: Public
@@ -384,6 +477,38 @@ delete_global_ptr() {
}
}
+////////////////////////////////////////////////////////////////////
+// Function: P3DInstanceManager::copy_file
+// Access: Private
+// Description: Copies the data in the file named by from_filename
+// into the file named by to_filename.
+////////////////////////////////////////////////////////////////////
+bool P3DInstanceManager::
+copy_file(const string &from_filename, const string &to_filename) {
+ ifstream in(from_filename.c_str(), ios::in | ios::binary);
+ ofstream out(to_filename.c_str(), ios::out | ios::binary);
+
+ static const size_t buffer_size = 4096;
+ char buffer[buffer_size];
+
+ in.read(buffer, buffer_size);
+ size_t count = in.gcount();
+ while (count != 0) {
+ out.write(buffer, count);
+ if (out.fail()) {
+ return false;
+ }
+ in.read(buffer, buffer_size);
+ count = in.gcount();
+ }
+
+ if (!in.eof()) {
+ return false;
+ }
+
+ return true;
+}
+
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::nt_thread_run
// Access: Private
diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h
index d09cc7f69e..f2abc6b55d 100644
--- a/direct/src/plugin/p3dInstanceManager.h
+++ b/direct/src/plugin/p3dInstanceManager.h
@@ -25,6 +25,8 @@
class P3DInstance;
class P3DSession;
class P3DPackage;
+class FileSpec;
+class TiXmlElement;
////////////////////////////////////////////////////////////////////
// Class : P3DInstanceManager
@@ -37,7 +39,7 @@ private:
~P3DInstanceManager();
public:
- bool initialize();
+ bool initialize(const string &contents_xml_filename);
inline bool is_initialized() const;
@@ -45,11 +47,15 @@ public:
inline const string &get_download_url() const;
inline const string &get_platform() const;
- P3DInstance *
- create_instance(P3D_request_ready_func *func, void *user_data);
+ inline bool has_contents_file() const;
+ bool read_contents_file(const string &contents_filename);
- bool start_instance(P3DInstance *inst, const string &p3d_filename,
- const P3D_token tokens[], size_t num_tokens);
+ P3DInstance *
+ create_instance(P3D_request_ready_func *func,
+ const P3D_token tokens[], size_t num_tokens,
+ void *user_data);
+
+ bool start_instance(P3DInstance *inst, const string &p3d_filename);
void finish_instance(P3DInstance *inst);
P3DInstance *validate_instance(P3D_instance *instance);
@@ -60,6 +66,9 @@ public:
P3DPackage *get_package(const string &package_name,
const string &package_version,
const string &package_display_name);
+ bool get_package_desc_file(FileSpec &desc_file,
+ const string &package_name,
+ const string &package_version);
inline int get_num_instances() const;
@@ -75,6 +84,9 @@ public:
static P3DInstanceManager *get_global_ptr();
static void delete_global_ptr();
+private:
+ bool copy_file(const string &from_filename, const string &to_filename);
+
private:
// The notify thread. This thread runs only for the purpose of
// generating asynchronous notifications of requests, to callers who
@@ -88,6 +100,8 @@ private:
string _download_url;
string _platform;
+ TiXmlElement *_xcontents;
+
P3D_object *_undefined_object;
P3D_object *_none_object;
P3D_object *_true_object;
diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx
index f4daafe86f..c487785102 100755
--- a/direct/src/plugin/p3dPackage.cxx
+++ b/direct/src/plugin/p3dPackage.cxx
@@ -35,23 +35,25 @@ static const double extract_portion = 0.05;
// Description:
////////////////////////////////////////////////////////////////////
P3DPackage::
-P3DPackage(const string &package_name, const string &package_version,
+P3DPackage(const string &package_name,
const string &package_platform,
+ const string &package_version,
const string &package_display_name) :
_package_name(package_name),
- _package_version(package_version),
_package_platform(package_platform),
+ _package_version(package_version),
_package_display_name(package_display_name)
{
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
- _package_fullname = _package_name + "_" + _package_version;
+ _package_fullname = _package_name;
_package_dir = inst_mgr->get_root_dir() + string("/") + _package_name;
-
if (!_package_platform.empty()) {
- _package_fullname += "_" + _package_platform;
- _package_dir += "/" + _package_platform;
+ _package_fullname += string("_") + _package_platform;
+ _package_dir += string("/") + _package_platform;
}
+ _package_fullname += string("_") + _package_version;
+ _package_dir += string("/") + _package_version;
_ready = false;
_failed = false;
@@ -59,7 +61,6 @@ P3DPackage(const string &package_name, const string &package_version,
_partial_download = false;
// Ensure the package directory exists; create it if it does not.
- _package_dir += string("/") + _package_version;
mkdir_complete(_package_dir, nout);
_desc_file_basename = _package_fullname + ".xml";
@@ -186,20 +187,68 @@ begin_download() {
return;
}
- // TODO: we should check the desc file for updates with the server.
- // Perhaps this should be done in a parent class.
+ download_contents_file();
+}
- // TODO: if the desc file exists, and is consistent with the server
- // contents file, don't re-download it.
- /*
- // Load the desc file, if it exists.
- TiXmlDocument doc(_desc_file_pathname.c_str());
- if (!doc.LoadFile()) {
+////////////////////////////////////////////////////////////////////
+// Function: P3DPackage::download_contents_file
+// Access: Private
+// Description: Starts downloading the root-level contents.xml file.
+// This is only done for the first package, and only if
+// the instance manager doesn't have the file already.
+////////////////////////////////////////////////////////////////////
+void P3DPackage::
+download_contents_file() {
+ P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+
+ if (inst_mgr->has_contents_file()) {
+ // We've already got a contents.xml file; go straight to the
+ // package desc file.
download_desc_file();
- } else {
- got_desc_file(&doc, false);
+ return;
}
- */
+
+ string url = inst_mgr->get_download_url();
+ url += "contents.xml";
+
+ // Download contents.xml to a temporary filename first, in case
+ // multiple packages are downloading it simultaneously.
+ _contents_file_pathname = tempnam(NULL, "p3d_");
+
+ cerr << "starting contents download\n";
+ start_download(DT_contents_file, url, _contents_file_pathname, false);
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: P3DPackage::contents_file_download_finished
+// Access: Private
+// Description: Called when the desc file has been fully downloaded.
+////////////////////////////////////////////////////////////////////
+void P3DPackage::
+contents_file_download_finished(bool success) {
+ P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+ cerr << "done contents download: " << success
+ << ", has_contents = " << inst_mgr->has_contents_file()
+ << "\n";
+
+ if (!inst_mgr->has_contents_file()) {
+ if (!success || !inst_mgr->read_contents_file(_contents_file_pathname)) {
+ nout << "Couldn't read " << _contents_file_pathname << "\n";
+
+ // Maybe we can read an already-downloaded contents.xml file.
+ string standard_filename = inst_mgr->get_root_dir() + "/contents.xml";
+ if (!inst_mgr->read_contents_file(standard_filename)) {
+ // Couldn't even read that. Fail.
+ report_done(false);
+ unlink(_contents_file_pathname.c_str());
+ return;
+ }
+ }
+ }
+
+ // The file is correctly installed by now; we can remove the
+ // temporary file.
+ unlink(_contents_file_pathname.c_str());
download_desc_file();
}
@@ -212,12 +261,40 @@ begin_download() {
void P3DPackage::
download_desc_file() {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+
+ // Attempt to check the desc file for freshness. If it already
+ // exists, and is consistent with the server contents file, we don't
+ // need to re-download it.
+ string root_dir = inst_mgr->get_root_dir();
+ FileSpec desc_file;
+ if (!inst_mgr->get_package_desc_file(desc_file, _package_name, _package_version)) {
+ nout << "Couldn't find package " << _package_fullname
+ << " in contents file.\n";
+
+ } else if (desc_file.get_pathname(root_dir) != _desc_file_pathname) {
+ nout << "Wrong pathname for desc file: "
+ << desc_file.get_pathname(root_dir)
+ << " instead of " << _desc_file_pathname << "\n";
+
+ } else if (!desc_file.quick_verify(root_dir)) {
+ nout << _desc_file_pathname << " is stale.\n";
+
+ } else {
+ // The desc file is current. Attempt to read it.
+ TiXmlDocument doc(_desc_file_pathname.c_str());
+ if (doc.LoadFile()) {
+ got_desc_file(&doc, false);
+ return;
+ }
+ }
+
+ // The desc file is not current. Go download it.
string url = inst_mgr->get_download_url();
- url += _package_name + "/" + _package_version;
+ url += _package_name;
if (!_package_platform.empty()) {
url += "/" + _package_platform;
}
-
+ url += "/" + _package_version;
url += "/" + _desc_file_basename;
start_download(DT_desc_file, url, _desc_file_pathname, false);
@@ -321,11 +398,11 @@ void P3DPackage::
download_compressed_archive(bool allow_partial) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
string url = inst_mgr->get_download_url();
- url += _package_name + "/" + _package_version;
+ url += _package_name;
if (!_package_platform.empty()) {
url += "/" + _package_platform;
}
-
+ url += "/" + _package_version;
url += "/" + _compressed_archive.get_filename();
string target_pathname = _package_dir + "/" + _compressed_archive.get_filename();
@@ -667,6 +744,10 @@ download_finished(bool success) {
_package->_active_download = NULL;
switch (_dtype) {
+ case DT_contents_file:
+ _package->contents_file_download_finished(success);
+ break;
+
case DT_desc_file:
_package->desc_file_download_finished(success);
break;
diff --git a/direct/src/plugin/p3dPackage.h b/direct/src/plugin/p3dPackage.h
index eafff27fa9..b394e5248a 100755
--- a/direct/src/plugin/p3dPackage.h
+++ b/direct/src/plugin/p3dPackage.h
@@ -36,8 +36,9 @@ class P3DInstance;
////////////////////////////////////////////////////////////////////
class P3DPackage {
public:
- P3DPackage(const string &package_name, const string &package_version,
+ P3DPackage(const string &package_name,
const string &package_platform,
+ const string &package_version,
const string &package_display_name);
~P3DPackage();
@@ -63,6 +64,7 @@ public:
private:
enum DownloadType {
+ DT_contents_file,
DT_desc_file,
DT_compressed_archive
};
@@ -81,6 +83,9 @@ private:
};
void begin_download();
+ void download_contents_file();
+ void contents_file_download_finished(bool success);
+
void download_desc_file();
void desc_file_download_finished(bool success);
void got_desc_file(TiXmlDocument *doc, bool freshly_downloaded);
@@ -105,6 +110,8 @@ private:
string _package_fullname;
string _package_dir;
+ string _contents_file_pathname;
+
string _desc_file_basename;
string _desc_file_pathname;
diff --git a/direct/src/plugin/p3dWinSplashWindow.cxx b/direct/src/plugin/p3dWinSplashWindow.cxx
index e0446cf4c5..80984419ca 100755
--- a/direct/src/plugin/p3dWinSplashWindow.cxx
+++ b/direct/src/plugin/p3dWinSplashWindow.cxx
@@ -82,6 +82,7 @@ set_wparams(const P3DWindowParams &wparams) {
void P3DWinSplashWindow::
set_image_filename(const string &image_filename,
bool image_filename_temp) {
+ nout << "image_filename = " << image_filename << ", thread_id = " << _thread_id << "\n";
ACQUIRE_LOCK(_install_lock);
if (_image_filename != image_filename) {
_image_filename = image_filename;
@@ -261,34 +262,33 @@ thread_run() {
TranslateMessage(&msg);
DispatchMessage(&msg);
- if (_got_install) {
- ACQUIRE_LOCK(_install_lock);
- double install_progress = _install_progress;
- if (_image_filename_changed) {
- update_image_filename(_image_filename, _image_filename_temp);
- }
- _image_filename_changed = false;
- if (_install_label_changed && _progress_bar != NULL) {
- update_install_label(_install_label);
- }
- _install_label_changed = false;
- RELEASE_LOCK(_install_lock);
+ ACQUIRE_LOCK(_install_lock);
+ bool got_install = _got_install;
+ double install_progress = _install_progress;
+ if (_image_filename_changed) {
+ update_image_filename(_image_filename, _image_filename_temp);
+ }
+ _image_filename_changed = false;
+ if (_install_label_changed && _progress_bar != NULL) {
+ update_install_label(_install_label);
+ }
+ _install_label_changed = false;
+ RELEASE_LOCK(_install_lock);
- if (install_progress != last_progress) {
- if (_progress_bar == NULL) {
- // Is it time to create the progress bar?
- int now = GetTickCount();
- if (now - _loop_started > 2000) {
- make_progress_bar();
- }
- } else {
- // Update the progress bar. We do this only within the
- // thread, to ensure we don't get a race condition when
- // starting or closing the thread.
- SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0);
-
- last_progress = install_progress;
+ if (got_install && install_progress != last_progress) {
+ if (_progress_bar == NULL) {
+ // Is it time to create the progress bar?
+ int now = GetTickCount();
+ if (now - _loop_started > 2000) {
+ make_progress_bar();
}
+ } else {
+ // Update the progress bar. We do this only within the
+ // thread, to ensure we don't get a race condition when
+ // starting or closing the thread.
+ SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0);
+
+ last_progress = install_progress;
}
}
diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx
index 95c66e80b0..94aed438ce 100644
--- a/direct/src/plugin/p3d_plugin.cxx
+++ b/direct/src/plugin/p3d_plugin.cxx
@@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////
#include "p3d_plugin_common.h"
+#include "p3d_plugin_config.h"
#include "p3dInstanceManager.h"
#include "p3dInstance.h"
#include "p3dWindowParams.h"
@@ -37,7 +38,7 @@ ostream *nout_stream;
bool
-P3D_initialize(int api_version, const char *output_filename) {
+P3D_initialize(int api_version, const char *contents_filename) {
if (api_version != P3D_API_VERSION) {
// Can't accept an incompatible version.
return false;
@@ -49,21 +50,40 @@ P3D_initialize(int api_version, const char *output_filename) {
}
ACQUIRE_LOCK(_api_lock);
- plugin_output_filename = string();
- if (output_filename != NULL) {
- plugin_output_filename = output_filename;
+ if (contents_filename == NULL){
+ contents_filename = "";
}
- nout_stream = &cerr;
- if (!plugin_output_filename.empty()) {
- logfile.open(plugin_output_filename.c_str(), ios::out | ios::trunc);
- if (logfile) {
- logfile.setf(ios::unitbuf);
- nout_stream = &logfile;
+
+#ifdef P3D_PLUGIN_LOGFILE2
+ string logfilename = P3D_PLUGIN_LOGFILE2;
+#else
+ string logfilename;
+#endif // P3D_PLUGIN_LOGFILE2
+
+ if (logfilename.empty()) {
+#ifdef _WIN32
+ static const size_t buffer_size = 4096;
+ char buffer[buffer_size];
+ if (GetTempPath(buffer_size, buffer) != 0) {
+ logfilename = buffer;
+ logfilename += "panda3d.2.log";
}
+#else
+ logfilename = "/tmp/panda3d.2.log";
+#endif // _WIN32
+ }
+
+ cerr << "logfile: " << logfilename << "\n";
+
+ nout_stream = &cerr;
+ logfile.open(logfilename.c_str(), ios::out | ios::trunc);
+ if (logfile) {
+ logfile.setf(ios::unitbuf);
+ nout_stream = &logfile;
}
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
- bool result = inst_mgr->initialize();
+ bool result = inst_mgr->initialize(contents_filename);
RELEASE_LOCK(_api_lock);
return result;
}
@@ -74,18 +94,21 @@ P3D_finalize() {
}
P3D_instance *
-P3D_new_instance(P3D_request_ready_func *func, void *user_data) {
+P3D_new_instance(P3D_request_ready_func *func,
+ const P3D_token tokens[], size_t num_tokens,
+ void *user_data) {
+ nout << "new_instance\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
- P3DInstance *result = inst_mgr->create_instance(func, user_data);
+ P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, user_data);
RELEASE_LOCK(_api_lock);
return result;
}
bool
-P3D_instance_start(P3D_instance *instance, const char *p3d_filename,
- const P3D_token tokens[], size_t num_tokens) {
+P3D_instance_start(P3D_instance *instance, const char *p3d_filename) {
+ nout << "instance_start\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
if (p3d_filename == NULL) {
p3d_filename = "";
@@ -95,7 +118,7 @@ P3D_instance_start(P3D_instance *instance, const char *p3d_filename,
P3DInstance *inst = inst_mgr->validate_instance(instance);
bool result = false;
if (inst != NULL) {
- result = inst_mgr->start_instance(inst, p3d_filename, tokens, num_tokens);
+ result = inst_mgr->start_instance(inst, p3d_filename);
}
RELEASE_LOCK(_api_lock);
return result;
@@ -119,6 +142,7 @@ P3D_instance_setup_window(P3D_instance *instance,
int win_x, int win_y,
int win_width, int win_height,
P3D_window_handle parent_window) {
+ nout << "setup_window\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
P3DWindowParams wparams(window_type, win_x, win_y,
win_width, win_height, parent_window);
diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h
index c6adc037f2..329efb0828 100644
--- a/direct/src/plugin/p3d_plugin.h
+++ b/direct/src/plugin/p3d_plugin.h
@@ -79,7 +79,7 @@ extern "C" {
(below). This number will be incremented whenever there are changes
to any of the interface specifications defined in this header
file. */
-#define P3D_API_VERSION 4
+#define P3D_API_VERSION 5
/************************ GLOBAL FUNCTIONS **************************/
@@ -91,17 +91,16 @@ extern "C" {
the DLL can verify that it has been built with the same version of
the API as the host.
- The output_filename is usually NULL, but if you put a filename
- here, it will be used as the log file for the output from the core
- API. This is useful for debugging, particularly when running
- within a browser that squelches stderr.
+ The contents_filename, if not NULL or empty, names a contents.xml
+ file that has already been downloaded and verified from the server.
+ If this is NULL, a new file will be downloaded as needed.
This function returns true if the core API is valid and uses a
compatible API, false otherwise. If it returns false, the host
should not call any more functions in this API, and should
immediately unload the DLL and (if possible) download a new one. */
typedef bool
-P3D_initialize_func(int api_version, const char *output_filename);
+P3D_initialize_func(int api_version, const char *contents_filename);
/* This function should be called to unload the core API. It will
release all internally-allocated memory and return the core API to
@@ -210,16 +209,25 @@ typedef struct {
/* This function creates a new Panda3D instance.
+ For tokens, pass an array of P3D_token elements (above), which
+ correspond to the user-supplied keyword/value pairs that may appear
+ in the embed token within the HTML syntax; the host is responsible
+ for allocating this array, and for deallocating it after this call
+ (the core API will make its own copy of the array). The tokens are
+ passed to the application, who is free to decide how to interpret
+ them; they have no meaning at the system level.
+
The user_data pointer is any arbitrary pointer value; it will be
copied into the _user_data member of the new P3D_instance object.
This pointer is intended for the host to use to store private data
associated with each instance; the core API will not do anything with
this data.
-
*/
typedef P3D_instance *
-P3D_new_instance_func(P3D_request_ready_func *func, void *user_data);
+P3D_new_instance_func(P3D_request_ready_func *func,
+ const P3D_token tokens[], size_t num_tokens,
+ void *user_data);
/* This function should be called at some point after
P3D_new_instance(); it actually starts the instance running.
@@ -230,29 +238,9 @@ P3D_new_instance_func(P3D_request_ready_func *func, void *user_data);
instance. If this is empty or NULL, the "src" token (below) will
be downloaded instead.
- For tokens, pass an array of P3D_token elements (above), which
- correspond to the user-supplied keyword/value pairs that may appear
- in the embed token within the HTML syntax; the host is responsible
- for allocating this array, and for deallocating it after this call
- (the core API will make its own copy of the array).
-
- Most tokens are implemented by the application and are undefined at
- the system level. However, two tokens in particular are
- system-defined:
-
- "src" : names a URL that will be loaded for the contents of the
- p3d file, if p3d_filename is empty or NULL.
-
- "output_filename" : names a file to create on disk which contains
- the console output from the application. This may be useful in
- debugging. If this is omitted, or an empty string, the console
- output is written to the standard error output, which may be
- NULL on a gui application.
-
The return value is true on success, false on failure. */
typedef bool
-P3D_instance_start_func(P3D_instance *instance, const char *p3d_filename,
- const P3D_token tokens[], size_t num_tokens);
+P3D_instance_start_func(P3D_instance *instance, const char *p3d_filename);
/* Call this function to interrupt a particular instance and stop it
diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx
index afca7e10f0..cdbef6e617 100644
--- a/direct/src/plugin_npapi/ppInstance.cxx
+++ b/direct/src/plugin_npapi/ppInstance.cxx
@@ -51,6 +51,8 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
_tokens.push_back(token);
}
+ _root_dir = find_root_dir();
+
_started_instance_data = false;
_got_instance_data = false;
_got_window = false;
@@ -313,7 +315,15 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
case PPDownloadRequest::RT_contents_file:
if (reason != NPRES_DONE) {
nout << "Failure downloading " << url << "\n";
- // TODO: fail
+
+ // Couldn't download a fresh contents.xml for some reason. If
+ // there's an outstanding contents.xml file on disk, try to load
+ // that one as a fallback.
+ string contents_filename = _root_dir + "/contents.xml";
+ if (!read_contents_file(contents_filename)) {
+ nout << "Unable to read contents file " << contents_filename << "\n";
+ // TODO: fail
+ }
}
break;
@@ -361,11 +371,11 @@ stream_as_file(NPStream *stream, const char *fname) {
// Looks like we've converted it successfully.
filename = fname2;
- // Here's another temporary hack. In addition to the weird
- // filename format, the file that Safari tells us about appears
- // to be a temporary file that Safari's about to delete. In
- // order to protect ourselves from this, we need to temporarily
- // copy the file somewhere else.
+ // Here's another crazy hack. In addition to the weird filename
+ // format, the file that Safari tells us about appears to be a
+ // temporary file that Safari's about to delete. In order to
+ // protect ourselves from this, we need to temporarily copy the
+ // file somewhere else.
char *name = tempnam(NULL, "p3d_");
// We prefer just making a hard link; it's quick and easy.
@@ -373,19 +383,7 @@ stream_as_file(NPStream *stream, const char *fname) {
// But sometimes the hard link might fail, particularly if these
// are two different file systems. In this case we have to open
// the files and copy the data by hand.
- ifstream in(filename.c_str(), ios::in | ios::binary);
- ofstream out(name, ios::out | ios::binary);
-
- static const size_t buffer_size = 4096;
- char buffer[buffer_size];
-
- in.read(buffer, buffer_size);
- size_t count = in.gcount();
- while (count != 0) {
- out.write(buffer, count);
- in.read(buffer, buffer_size);
- count = in.gcount();
- }
+ copy_file(filename, name);
}
filename = name;
@@ -439,7 +437,7 @@ handle_request(P3D_request *request) {
if (strcmp(request->_request._notify._message, "onwindowopen") == 0) {
_python_window_open = true;
if (_got_window) {
- NPRect rect = { 0, 0, _window.height, _window.width };
+ NPRect rect = { 0, 0, (unsigned short)_window.height, (unsigned short)_window.width };
browser->invalidaterect(_npp_instance, &rect);
}
}
@@ -447,7 +445,7 @@ handle_request(P3D_request *request) {
case P3D_RT_refresh:
if (_got_window) {
- NPRect rect = { 0, 0, _window.height, _window.width };
+ NPRect rect = { 0, 0, (unsigned short)_window.height, (unsigned short)_window.width };
browser->invalidaterect(_npp_instance, &rect);
}
break;
@@ -700,8 +698,8 @@ start_download(const string &url, PPDownloadRequest *req) {
// DLL downloading, if necessary.
////////////////////////////////////////////////////////////////////
bool PPInstance::
-read_contents_file(const string &filename) {
- TiXmlDocument doc(filename.c_str());
+read_contents_file(const string &contents_filename) {
+ TiXmlDocument doc(contents_filename.c_str());
if (!doc.LoadFile()) {
return false;
}
@@ -765,9 +763,23 @@ downloaded_file(PPDownloadRequest *req, const string &filename) {
case PPDownloadRequest::RT_contents_file:
// Now we have the contents.xml file. Read this to get the
// filename and md5 hash of our core API DLL.
- if (!read_contents_file(filename)) {
- nout << "Unable to read contents file\n";
- // TODO: fail
+ if (read_contents_file(filename)) {
+ // Successfully read. Copy it into its normal place.
+ string contents_filename = _root_dir + "/contents.xml";
+ copy_file(filename, contents_filename);
+
+ } else {
+ // Error reading the contents.xml file, or in loading the core
+ // API that it references.
+ nout << "Unable to read contents file " << filename << "\n";
+
+ // If there's an outstanding contents.xml file on disk, try to
+ // load that one as a fallback.
+ string contents_filename = _root_dir + "/contents.xml";
+ if (!read_contents_file(contents_filename)) {
+ nout << "Unable to read contents file " << contents_filename << "\n";
+ // TODO: fail
+ }
}
break;
@@ -782,7 +794,10 @@ downloaded_file(PPDownloadRequest *req, const string &filename) {
// launch the instance.
_got_instance_data = true;
_p3d_filename = filename;
- create_instance();
+
+ if (_p3d_inst != NULL) {
+ P3D_instance_start(_p3d_inst, _p3d_filename.c_str());
+ }
break;
case PPDownloadRequest::RT_user:
@@ -821,8 +836,6 @@ void PPInstance::
get_core_api(TiXmlElement *xpackage) {
_core_api_dll.load_xml(xpackage);
- _root_dir = find_root_dir();
-
if (_core_api_dll.quick_verify(_root_dir)) {
// The DLL file is good. Just load it.
do_load_plugin();
@@ -919,7 +932,7 @@ do_load_plugin() {
}
#endif // P3D_PLUGIN_P3D_PLUGIN
- if (!load_plugin(pathname)) {
+ if (!load_plugin(pathname, "")) {
nout << "Unable to launch core API in " << pathname << "\n";
return;
}
@@ -944,12 +957,11 @@ create_instance() {
return;
}
- if (!_got_instance_data) {
- // No instance data yet.
- return;
+ P3D_token *tokens = NULL;
+ if (!_tokens.empty()) {
+ tokens = &_tokens[0];
}
-
- _p3d_inst = P3D_new_instance(request_ready, this);
+ _p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), this);
if (_p3d_inst != NULL) {
// Now get the browser's window object, to pass to the plugin.
@@ -971,11 +983,7 @@ create_instance() {
}
if (_got_instance_data) {
- P3D_token *tokens = NULL;
- if (!_tokens.empty()) {
- tokens = &_tokens[0];
- }
- P3D_instance_start(_p3d_inst, _p3d_filename.c_str(), tokens, _tokens.size());
+ P3D_instance_start(_p3d_inst, _p3d_filename.c_str());
}
if (_got_window) {
@@ -1062,6 +1070,38 @@ send_window() {
parent_window);
}
+////////////////////////////////////////////////////////////////////
+// Function: PPInstance::copy_file
+// Access: Public
+// Description: Copies the data in the file named by from_filename
+// into the file named by to_filename.
+////////////////////////////////////////////////////////////////////
+bool PPInstance::
+copy_file(const string &from_filename, const string &to_filename) {
+ ifstream in(from_filename.c_str(), ios::in | ios::binary);
+ ofstream out(to_filename.c_str(), ios::out | ios::binary);
+
+ static const size_t buffer_size = 4096;
+ char buffer[buffer_size];
+
+ in.read(buffer, buffer_size);
+ size_t count = in.gcount();
+ while (count != 0) {
+ out.write(buffer, count);
+ if (out.fail()) {
+ return false;
+ }
+ in.read(buffer, buffer_size);
+ count = in.gcount();
+ }
+
+ if (!in.eof()) {
+ return false;
+ }
+
+ return true;
+}
+
////////////////////////////////////////////////////////////////////
// Function: PPInstance::output_np_variant
// Access: Public
diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h
index 690ab841ee..92c6ff7a18 100644
--- a/direct/src/plugin_npapi/ppInstance.h
+++ b/direct/src/plugin_npapi/ppInstance.h
@@ -71,13 +71,14 @@ private:
static string get_filename_from_url(const string &url);
void feed_file(PPDownloadRequest *req, const string &filename);
- bool read_contents_file(const string &filename);
+ bool read_contents_file(const string &contents_filename);
void get_core_api(TiXmlElement *xpackage);
void downloaded_plugin(const string &filename);
void do_load_plugin();
void create_instance();
void send_window();
+ bool copy_file(const string &from_filename, const string &to_filename);
static void handle_request_loop();
static void browser_sync_callback(void *);
diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx
index caa25a828a..e1aa016192 100644
--- a/direct/src/plugin_standalone/panda3d.cxx
+++ b/direct/src/plugin_standalone/panda3d.cxx
@@ -286,8 +286,8 @@ run(int argc, char *argv[]) {
bool Panda3D::
get_plugin(const string &root_url, const string &this_platform, bool force_download) {
// First, look for the existing contents.xml file.
- Filename contents = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
- if (!force_download && read_contents_file(contents, root_url, this_platform)) {
+ Filename contents_filename = Filename(Filename::from_os_specific(_root_dir), "contents.xml");
+ if (!force_download && read_contents_file(contents_filename, root_url, this_platform)) {
// Got the file, and it's good.
return true;
}
@@ -299,13 +299,13 @@ get_plugin(const string &root_url, const string &this_platform, bool force_downl
HTTPClient *http = HTTPClient::get_global_ptr();
PT(HTTPChannel) channel = http->get_document(url);
- contents.make_dir();
- if (!channel->download_to_file(contents)) {
+ contents_filename.make_dir();
+ if (!channel->download_to_file(contents_filename)) {
cerr << "Unable to download " << url << "\n";
return false;
}
- return read_contents_file(contents, root_url, this_platform);
+ return read_contents_file(contents_filename, root_url, this_platform);
}
////////////////////////////////////////////////////////////////////
@@ -316,12 +316,12 @@ get_plugin(const string &root_url, const string &this_platform, bool force_downl
// possible. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool Panda3D::
-read_contents_file(Filename contents, const string &root_url,
+read_contents_file(Filename contents_filename, const string &root_url,
const string &this_platform) {
ifstream in;
- contents.set_text();
- if (!contents.open_read(in)) {
- cerr << "Couldn't read " << contents.to_os_specific() << "\n";
+ contents_filename.set_text();
+ if (!contents_filename.open_read(in)) {
+ cerr << "Couldn't read " << contents_filename.to_os_specific() << "\n";
return false;
}
@@ -336,7 +336,7 @@ read_contents_file(Filename contents, const string &root_url,
if (name != NULL && strcmp(name, "coreapi") == 0) {
const char *xplatform = xpackage->Attribute("platform");
if (xplatform != NULL && strcmp(xplatform, this_platform.c_str()) == 0) {
- return get_core_api(root_url, xpackage);
+ return get_core_api(contents_filename, root_url, xpackage);
}
}
@@ -359,7 +359,8 @@ read_contents_file(Filename contents, const string &root_url,
// if necessary.
////////////////////////////////////////////////////////////////////
bool Panda3D::
-get_core_api(const string &root_url, TiXmlElement *xpackage) {
+get_core_api(const Filename &contents_filename, const string &root_url,
+ TiXmlElement *xpackage) {
_core_api_dll.load_xml(xpackage);
if (!_core_api_dll.quick_verify(_root_dir)) {
@@ -397,7 +398,7 @@ get_core_api(const string &root_url, TiXmlElement *xpackage) {
}
#endif // P3D_PLUGIN_P3D_PLUGIN
- if (!load_plugin(pathname)) {
+ if (!load_plugin(pathname, contents_filename.to_os_specific())) {
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
return false;
}
@@ -592,12 +593,12 @@ create_instance(const string &arg, P3D_window_type window_type,
os_p3d_filename = p3d_filename.to_os_specific();
}
- P3D_instance *inst = P3D_new_instance(NULL, NULL);
+ P3D_instance *inst = P3D_new_instance(NULL, tokens, num_tokens, NULL);
if (inst != NULL) {
P3D_instance_setup_window
(inst, window_type, win_x, win_y, win_width, win_height, parent_window);
- P3D_instance_start(inst, os_p3d_filename.c_str(), tokens, num_tokens);
+ P3D_instance_start(inst, os_p3d_filename.c_str());
}
return inst;
diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h
index 119ed632fe..aac2547a61 100755
--- a/direct/src/plugin_standalone/panda3d.h
+++ b/direct/src/plugin_standalone/panda3d.h
@@ -44,9 +44,10 @@ public:
private:
bool get_plugin(const string &root_url, const string &this_platform,
bool force_download);
- bool read_contents_file(Filename contents, const string &root_url,
+ bool read_contents_file(Filename contents_filename, const string &root_url,
const string &this_platform);
- bool get_core_api(const string &root_url, TiXmlElement *xpackage);
+ bool get_core_api(const Filename &contents_filename, const string &root_url,
+ TiXmlElement *xpackage);
void run_getters();
void handle_request(P3D_request *request);
void make_parent_window(P3D_window_handle &parent_window,
diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py
index 54d9d507e2..5ef62cc191 100644
--- a/direct/src/showutil/FreezeTool.py
+++ b/direct/src/showutil/FreezeTool.py
@@ -55,7 +55,7 @@ if sys.platform == 'win32':
MSVC = Filename('/c/Program Files/Microsoft Visual Studio .NET 2003/Vc7').toOsSpecific()
else:
print 'Could not locate Microsoft Visual C++ Compiler! Try running from the Visual Studio Command Prompt.'
- exit(1)
+ sys.exit(1)
if ('WindowsSdkDir' in os.environ):
PSDK = os.environ['WindowsSdkDir']
@@ -65,7 +65,7 @@ if sys.platform == 'win32':
PSDK = os.path.join(MSVC, 'PlatformSDK')
else:
print 'Could not locate the Microsoft Windows Platform SDK! Try running from the Visual Studio Command Prompt.'
- exit(1)
+ sys.exit(1)
# If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself.
if ('MAKEPANDA' in os.environ):