make panda3d.exe download the core API too
This commit is contained in:
parent
7406014cbc
commit
2d3fd6e709
|
|
@ -53,9 +53,11 @@ class ContentsMaker:
|
|||
f = open(contentsFilePathname.toOsSpecific(), 'w')
|
||||
print >> f, '<?xml version="1.0" ?>'
|
||||
print >> f, ''
|
||||
print >> f, '<contents>'
|
||||
for packageName, packageVersion, packagePlatform, file in self.packages:
|
||||
print >> f, '<package name="%s" version="%s" platform="%s" %s />' % (
|
||||
print >> f, ' <package name="%s" version="%s" platform="%s" %s />' % (
|
||||
packageName, packageVersion, packagePlatform or '', file.getParams())
|
||||
print >> f, '</contents>'
|
||||
f.close()
|
||||
|
||||
def scanDirectory(self):
|
||||
|
|
|
|||
|
|
@ -703,18 +703,21 @@ read_contents_file(const string &filename) {
|
|||
return false;
|
||||
}
|
||||
|
||||
TiXmlElement *xpackage = doc.FirstChildElement("package");
|
||||
while (xpackage != NULL) {
|
||||
const char *name = xpackage->Attribute("name");
|
||||
if (name != NULL && strcmp(name, "coreapi") == 0) {
|
||||
const char *platform = xpackage->Attribute("platform");
|
||||
if (platform != NULL && strcmp(platform, P3D_PLUGIN_PLATFORM) == 0) {
|
||||
get_core_api(xpackage);
|
||||
return true;
|
||||
TiXmlElement *xcontents = doc.FirstChildElement("contents");
|
||||
if (xcontents != NULL) {
|
||||
TiXmlElement *xpackage = xcontents->FirstChildElement("package");
|
||||
while (xpackage != NULL) {
|
||||
const char *name = xpackage->Attribute("name");
|
||||
if (name != NULL && strcmp(name, "coreapi") == 0) {
|
||||
const char *platform = xpackage->Attribute("platform");
|
||||
if (platform != NULL && strcmp(platform, P3D_PLUGIN_PLATFORM) == 0) {
|
||||
get_core_api(xpackage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xpackage = xpackage->NextSiblingElement("package");
|
||||
xpackage = xpackage->NextSiblingElement("package");
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find the coreapi package description.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
#include "panda3d.h"
|
||||
#include "httpClient.h"
|
||||
#include "load_plugin.h"
|
||||
#include "find_root_dir.h"
|
||||
#include "p3d_plugin_config.h"
|
||||
|
||||
#include <sstream>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
|
@ -36,6 +39,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
Panda3D::
|
||||
Panda3D() {
|
||||
_root_dir = find_root_dir();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -48,9 +52,12 @@ int Panda3D::
|
|||
run(int argc, char *argv[]) {
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
const char *optstr = "p:l:t:s:o:h";
|
||||
const char *optstr = "u:p:fl:t:s:o:h";
|
||||
|
||||
string root_url = P3D_PLUGIN_DOWNLOAD;
|
||||
string this_platform = P3D_PLUGIN_PLATFORM;
|
||||
bool force_download = false;
|
||||
|
||||
Filename p3d_plugin_filename;
|
||||
Filename output_filename;
|
||||
P3D_window_type window_type = P3D_WT_toplevel;
|
||||
int win_x = 0, win_y = 0;
|
||||
|
|
@ -60,8 +67,19 @@ run(int argc, char *argv[]) {
|
|||
|
||||
while (flag != EOF) {
|
||||
switch (flag) {
|
||||
case 'u':
|
||||
root_url = optarg;
|
||||
if (!root_url.empty() && root_url[root_url.length() - 1] != '/') {
|
||||
root_url += '/';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
p3d_plugin_filename = Filename::from_os_specific(optarg);
|
||||
this_platform = optarg;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
force_download = true;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
|
@ -114,7 +132,7 @@ run(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!load_plugin(p3d_plugin_filename.to_os_specific())) {
|
||||
if (!get_plugin(root_url, this_platform, force_download)) {
|
||||
cerr << "Unable to load Panda3D plugin.\n";
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -257,66 +275,132 @@ run(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::feed_file
|
||||
// Function: Panda3D::get_plugin
|
||||
// Access: Private
|
||||
// Description: Opens the named file (extracted from a file:// URL)
|
||||
// and feeds its contents to the plugin.
|
||||
// Description: Downloads the contents.xml file from the named URL
|
||||
// and attempts to use it to load the core API. Returns
|
||||
// true on success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
feed_file(P3D_instance *inst, int unique_id, string filename) {
|
||||
#ifdef _WIN32
|
||||
// On Windows, we have to munge the filename specially, because it's
|
||||
// been URL-munged. It might begin with a leading slash as well as
|
||||
// a drive letter. Clean up that nonsense.
|
||||
if (!filename.empty()) {
|
||||
if (filename[0] == '/' || filename[0] == '\\') {
|
||||
Filename fname = Filename::from_os_specific(filename.substr(1));
|
||||
if (fname.is_local()) {
|
||||
// Put the slash back on.
|
||||
fname = string("/") + fname.get_fullpath();
|
||||
}
|
||||
filename = fname.to_os_specific();
|
||||
}
|
||||
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)) {
|
||||
// Got the file, and it's good.
|
||||
return true;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
ifstream file(filename.c_str(), ios::in | ios::binary);
|
||||
|
||||
// First, seek to the end to get the file size.
|
||||
file.seekg(0, ios::end);
|
||||
size_t file_size = file.tellg();
|
||||
|
||||
// Then return to the beginning to read the data.
|
||||
file.seekg(0, ios::beg);
|
||||
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
|
||||
file.read(buffer, buffer_size);
|
||||
size_t count = file.gcount();
|
||||
size_t total_count = 0;
|
||||
while (count != 0) {
|
||||
bool download_ok = P3D_instance_feed_url_stream
|
||||
(inst, unique_id, P3D_RC_in_progress,
|
||||
0, file_size, (const unsigned char *)buffer, count);
|
||||
|
||||
if (!download_ok) {
|
||||
// Never mind.
|
||||
return;
|
||||
}
|
||||
file.read(buffer, buffer_size);
|
||||
count = file.gcount();
|
||||
total_count += count;
|
||||
// Couldn't read it, so go get it.
|
||||
string url = root_url;
|
||||
url += "contents.xml";
|
||||
cerr << "Getting URL " << root_url << "\n";
|
||||
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
PT(HTTPChannel) channel = http->get_document(url);
|
||||
Ramfile rf;
|
||||
if (!channel->download_to_file(contents)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
P3D_result_code result = P3D_RC_done;
|
||||
if (file.fail() && !file.eof()) {
|
||||
// Got an error while reading.
|
||||
result = P3D_RC_generic_error;
|
||||
return read_contents_file(contents, root_url, this_platform);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::read_contents_file
|
||||
// Access: Private
|
||||
// Description: Attempts to open and read the contents.xml file on
|
||||
// disk, and uses that data to load the plugin, if
|
||||
// possible. Returns true on success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
read_contents_file(Filename contents, 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";
|
||||
return false;
|
||||
}
|
||||
|
||||
P3D_instance_feed_url_stream
|
||||
(inst, unique_id, result, 0, total_count, NULL, 0);
|
||||
TiXmlDocument doc;
|
||||
in >> doc;
|
||||
|
||||
TiXmlElement *xcontents = doc.FirstChildElement("contents");
|
||||
if (xcontents != NULL) {
|
||||
TiXmlElement *xpackage = xcontents->FirstChildElement("package");
|
||||
while (xpackage != NULL) {
|
||||
const char *name = xpackage->Attribute("name");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
xpackage = xpackage->NextSiblingElement("package");
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find the coreapi package description.
|
||||
cerr << "No coreapi package defined in contents file for "
|
||||
<< this_platform << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::get_core_api
|
||||
// Access: Private
|
||||
// Description: Checks the core API DLL file against the
|
||||
// specification in the contents file, and downloads it
|
||||
// if necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
get_core_api(const string &root_url, TiXmlElement *xpackage) {
|
||||
_core_api_dll.load_xml(xpackage);
|
||||
|
||||
if (!_core_api_dll.quick_verify(_root_dir)) {
|
||||
// The DLL file needs to be downloaded. Go get it.
|
||||
string url = root_url;
|
||||
url += _core_api_dll.get_filename();
|
||||
|
||||
Filename pathname = Filename::from_os_specific(_core_api_dll.get_pathname(_root_dir));
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
PT(HTTPChannel) channel = http->get_document(url);
|
||||
if (!channel->download_to_file(pathname)) {
|
||||
cerr << "Unable to download " << url << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_core_api_dll.quick_verify(_root_dir)) {
|
||||
cerr << "Mismatched download for " << url << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we've got the DLL. Load it.
|
||||
string pathname = _core_api_dll.get_pathname(_root_dir);
|
||||
|
||||
#ifdef P3D_PLUGIN_P3D_PLUGIN
|
||||
// This is a convenience macro for development. If defined and
|
||||
// nonempty, it indicates the name of the plugin DLL that we will
|
||||
// actually run, even after downloading a possibly different
|
||||
// (presumably older) version. Its purpose is to simplify iteration
|
||||
// on the plugin DLL.
|
||||
string override_filename = P3D_PLUGIN_P3D_PLUGIN;
|
||||
if (!override_filename.empty()) {
|
||||
pathname = override_filename;
|
||||
}
|
||||
#endif // P3D_PLUGIN_P3D_PLUGIN
|
||||
|
||||
if (!load_plugin(pathname)) {
|
||||
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Successfully loaded.
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -370,18 +454,9 @@ handle_request(P3D_request *request) {
|
|||
{
|
||||
int unique_id = request->_request._get_url._unique_id;
|
||||
const string &url = request->_request._get_url._url;
|
||||
if (url.substr(0, 7) == "file://") {
|
||||
// A special case: if the url begins with "file://", just open
|
||||
// the named file and feed it directly to the plugin.
|
||||
feed_file(request->_instance, unique_id, url.substr(7));
|
||||
|
||||
} else {
|
||||
// Otherwise, assume it's a legitimate URL and pass it down to
|
||||
// Panda's HTTPClient to read it.
|
||||
URLGetter *getter = new URLGetter
|
||||
(request->_instance, unique_id, URLSpec(url), "");
|
||||
_url_getters.insert(getter);
|
||||
}
|
||||
URLGetter *getter = new URLGetter
|
||||
(request->_instance, unique_id, URLSpec(url), "");
|
||||
_url_getters.insert(getter);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -570,11 +645,6 @@ usage() {
|
|||
|
||||
<< "Options:\n\n"
|
||||
|
||||
<< " -p " << get_plugin_basename() << "\n"
|
||||
<< " Specify the full path to the particular Panda plugin DLL to\n"
|
||||
<< " run. Normally, this will be found by searching in the usual\n"
|
||||
<< " places.\n\n"
|
||||
|
||||
<< " -l output.log\n"
|
||||
<< " Specify the name of the file to receive the log output of the\n"
|
||||
<< " plugin process(es). The default is to send this output to the\n"
|
||||
|
|
@ -589,7 +659,20 @@ usage() {
|
|||
|
||||
<< " -o x,y\n"
|
||||
<< " Specify the position (origin) of the graphic window on the\n"
|
||||
<< " screen, or on the parent window.\n\n";
|
||||
<< " screen, or on the parent window.\n\n"
|
||||
|
||||
<< " -f\n"
|
||||
<< " Force a HTTP contact to the Panda3D download server, to check\n"
|
||||
<< " if a new version is available. Normally, this is done only\n"
|
||||
<< " if contents.xml cannot be read.\n\n"
|
||||
|
||||
<< " -u url\n"
|
||||
<< " Specify the URL of the Panda3D download server. The default is\n"
|
||||
<< " " << P3D_PLUGIN_DOWNLOAD << "\n\n"
|
||||
|
||||
<< " -p platform\n"
|
||||
<< " Specify the platform to masquerade as. The default is "
|
||||
<< P3D_PLUGIN_PLATFORM << "\n\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "p3d_plugin.h"
|
||||
#include "httpChannel.h"
|
||||
#include "ramfile.h"
|
||||
#include "fileSpec.h"
|
||||
#include "pset.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -41,7 +42,11 @@ public:
|
|||
int run(int argc, char *argv[]);
|
||||
|
||||
private:
|
||||
void feed_file(P3D_instance *inst, int unique_id, string filename);
|
||||
bool get_plugin(const string &root_url, const string &this_platform,
|
||||
bool force_download);
|
||||
bool read_contents_file(Filename contents, const string &root_url,
|
||||
const string &this_platform);
|
||||
bool get_core_api(const string &root_url, TiXmlElement *xpackage);
|
||||
void run_getters();
|
||||
void handle_request(P3D_request *request);
|
||||
void make_parent_window(P3D_window_handle &parent_window,
|
||||
|
|
@ -58,6 +63,9 @@ private:
|
|||
bool parse_int_pair(char *arg, int &x, int &y);
|
||||
|
||||
private:
|
||||
string _root_dir;
|
||||
FileSpec _core_api_dll;
|
||||
|
||||
typedef pset<P3D_instance *> Instances;
|
||||
Instances _instances;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue