mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
more robust temp file and log handling
This commit is contained in:
parent
19e866c803
commit
5289285624
@ -45,6 +45,7 @@
|
||||
p3dSession.h p3dSession.I \
|
||||
p3dSplashWindow.h p3dSplashWindow.I \
|
||||
p3dStringObject.h \
|
||||
p3dTemporaryFile.h p3dTemporaryFile.I \
|
||||
p3dToplevelObject.h \
|
||||
p3dUndefinedObject.h \
|
||||
p3dWinSplashWindow.h p3dWinSplashWindow.I \
|
||||
@ -74,6 +75,7 @@
|
||||
p3dSession.cxx \
|
||||
p3dSplashWindow.cxx \
|
||||
p3dStringObject.cxx \
|
||||
p3dTemporaryFile.cxx \
|
||||
p3dToplevelObject.cxx \
|
||||
p3dUndefinedObject.cxx \
|
||||
p3dWinSplashWindow.cxx \
|
||||
|
@ -124,7 +124,8 @@ static void unload_dso();
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
load_plugin(const string &p3d_plugin_filename, const string &contents_filename,
|
||||
const string &download_url, const string &platform) {
|
||||
const string &download_url, const string &platform,
|
||||
const string &log_directory, const string &log_basename) {
|
||||
string filename = p3d_plugin_filename;
|
||||
if (filename.empty()) {
|
||||
// Look for the plugin along the path.
|
||||
@ -294,7 +295,8 @@ load_plugin(const string &p3d_plugin_filename, const string &contents_filename,
|
||||
plugin_loaded = true;
|
||||
|
||||
if (!P3D_initialize(P3D_API_VERSION, contents_filename.c_str(),
|
||||
download_url.c_str(), platform.c_str())) {
|
||||
download_url.c_str(), platform.c_str(),
|
||||
log_directory.c_str(), log_basename.c_str())) {
|
||||
// Oops, failure to initialize.
|
||||
cerr << "Failed to initialize plugin (wrong API version?)\n";
|
||||
unload_plugin();
|
||||
|
@ -60,7 +60,8 @@ extern P3D_instance_handle_event_func *P3D_instance_handle_event;
|
||||
string get_plugin_basename();
|
||||
bool
|
||||
load_plugin(const string &p3d_plugin_filename, const string &contents_filename,
|
||||
const string &download_url, const string &platform);
|
||||
const string &download_url, const string &platform,
|
||||
const string &log_directory, const string &log_basename);
|
||||
void unload_plugin();
|
||||
bool is_plugin_loaded();
|
||||
|
||||
|
@ -122,6 +122,19 @@ lookup_token(const string &keyword) const {
|
||||
return string();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DFileParams::lookup_token_int
|
||||
// Access: Public
|
||||
// Description: Returns the integer value associated with the first
|
||||
// appearance of the named token, or zero if the
|
||||
// token does not appear or is not an integer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int P3DFileParams::
|
||||
lookup_token_int(const string &keyword) const {
|
||||
string value = lookup_token(keyword);
|
||||
return atoi(value.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DFileParams::has_token
|
||||
// Access: Public
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
|
||||
inline const string &get_p3d_filename() const;
|
||||
string lookup_token(const string &keyword) const;
|
||||
int lookup_token_int(const string &keyword) const;
|
||||
bool has_token(const string &keyword) const;
|
||||
|
||||
TiXmlElement *make_xml();
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "p3dToplevelObject.h"
|
||||
#include "p3dUndefinedObject.h"
|
||||
#include "p3dMultifileReader.h"
|
||||
#include "p3dTemporaryFile.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
@ -59,6 +60,8 @@ P3DInstance(P3D_request_ready_func *func,
|
||||
_panda_script_object = new P3DToplevelObject;
|
||||
_user_data = user_data;
|
||||
_request_pending = false;
|
||||
_temp_p3d_filename = NULL;
|
||||
_temp_splash_image = NULL;
|
||||
_got_fparams = false;
|
||||
_got_wparams = false;
|
||||
|
||||
@ -68,6 +71,7 @@ P3DInstance(P3D_request_ready_func *func,
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
_instance_id = inst_mgr->get_unique_id();
|
||||
_full_disk_access = false;
|
||||
_hidden = false;
|
||||
_session = NULL;
|
||||
_panda3d = NULL;
|
||||
_splash_window = NULL;
|
||||
@ -122,6 +126,16 @@ P3DInstance::
|
||||
_splash_window = NULL;
|
||||
}
|
||||
|
||||
if (_temp_p3d_filename != NULL) {
|
||||
delete _temp_p3d_filename;
|
||||
_temp_p3d_filename = NULL;
|
||||
}
|
||||
|
||||
if (_temp_splash_image != NULL) {
|
||||
delete _temp_splash_image;
|
||||
_temp_splash_image = NULL;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (_frame_timer != NULL) {
|
||||
CFRunLoopTimerInvalidate(_frame_timer);
|
||||
@ -167,9 +181,8 @@ void P3DInstance::
|
||||
set_p3d_url(const string &p3d_url) {
|
||||
nout << "set_p3d_url(" << p3d_url << ")\n";
|
||||
// Make a temporary file to receive the instance data.
|
||||
char *name = tempnam(NULL, "p3d_");
|
||||
string filename = name;
|
||||
free(name);
|
||||
assert(_temp_p3d_filename == NULL);
|
||||
_temp_p3d_filename = new P3DTemporaryFile(".p3d");
|
||||
|
||||
// Mark the time we started downloading, so we'll know when to set
|
||||
// the install label.
|
||||
@ -183,7 +196,7 @@ set_p3d_url(const string &p3d_url) {
|
||||
// Start downloading the data.
|
||||
InstanceDownload *download = new InstanceDownload(this);
|
||||
download->set_url(p3d_url);
|
||||
download->set_filename(filename);
|
||||
download->set_filename(_temp_p3d_filename->get_filename());
|
||||
|
||||
_panda_script_object->set_string_property("status", "downloading_instance");
|
||||
start_download(download);
|
||||
@ -243,10 +256,15 @@ set_p3d_filename(const string &p3d_filename) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
set_wparams(const P3DWindowParams &wparams) {
|
||||
nout << "set_wparams, _session = " << _session << "\n";
|
||||
_got_wparams = true;
|
||||
_wparams = wparams;
|
||||
nout << "set window_type = " << _wparams.get_window_type() << "\n";
|
||||
|
||||
if (_hidden || _wparams.get_win_width() == 0 || _wparams.get_win_height() == 0) {
|
||||
// If we're a hidden app, or if the window has no size, then it is
|
||||
// really a hidden window, regardless of what type it claims to
|
||||
// be.
|
||||
_wparams.set_window_type(P3D_WT_hidden);
|
||||
}
|
||||
|
||||
if (_wparams.get_window_type() != P3D_WT_hidden) {
|
||||
// Update or create the splash window.
|
||||
@ -854,6 +872,15 @@ scan_app_desc_file(TiXmlDocument *doc) {
|
||||
_full_disk_access = (full_disk_access != 0);
|
||||
}
|
||||
|
||||
int hidden = 0;
|
||||
if (xpackage->QueryIntAttribute("hidden", &hidden) == TIXML_SUCCESS) {
|
||||
_hidden = (hidden != 0);
|
||||
}
|
||||
|
||||
if (_hidden && _got_wparams) {
|
||||
_wparams.set_window_type(P3D_WT_hidden);
|
||||
}
|
||||
|
||||
TiXmlElement *xrequires = xpackage->FirstChildElement("requires");
|
||||
while (xrequires != NULL) {
|
||||
const char *name = xrequires->Attribute("name");
|
||||
@ -1015,6 +1042,11 @@ handle_notify_request(const string &message) {
|
||||
_splash_window = NULL;
|
||||
}
|
||||
|
||||
if (_temp_splash_image != NULL) {
|
||||
delete _temp_splash_image;
|
||||
_temp_splash_image = NULL;
|
||||
}
|
||||
|
||||
_panda_script_object->set_string_property("status", "open");
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -1112,7 +1144,6 @@ handle_script_request(const string &operation, P3D_object *object,
|
||||
char *buffer = new char[size + 1];
|
||||
P3D_OBJECT_GET_STRING(value, buffer, size + 1);
|
||||
result = P3D_OBJECT_EVAL(object, buffer);
|
||||
logfile << " eval " << *object << ": " << buffer << ", result = " << result << "\n";
|
||||
delete[] buffer;
|
||||
|
||||
if (result != NULL) {
|
||||
@ -1157,14 +1188,13 @@ make_splash_window() {
|
||||
}
|
||||
|
||||
// Make a temporary file to receive the splash image.
|
||||
char *name = tempnam(NULL, "p3d_");
|
||||
string filename = name;
|
||||
free(name);
|
||||
assert(_temp_splash_image == NULL);
|
||||
_temp_splash_image = new P3DTemporaryFile(".jpg");
|
||||
|
||||
// Start downloading the requested splash image.
|
||||
SplashDownload *download = new SplashDownload(this);
|
||||
download->set_url(splash_image_url);
|
||||
download->set_filename(filename);
|
||||
download->set_filename(_temp_splash_image->get_filename());
|
||||
|
||||
start_download(download);
|
||||
}
|
||||
@ -1202,6 +1232,8 @@ report_package_info_ready(P3DPackage *package) {
|
||||
_splash_window->set_install_progress(0.0);
|
||||
}
|
||||
_panda_script_object->set_string_property("status", "downloading");
|
||||
_panda_script_object->set_int_property("numDownloadingPackages", _downloading_packages.size());
|
||||
_panda_script_object->set_int_property("totalDownloadSize", _total_download_size);
|
||||
send_notify("ondownloadbegin");
|
||||
|
||||
start_next_download();
|
||||
@ -1232,6 +1264,8 @@ start_next_download() {
|
||||
}
|
||||
_panda_script_object->set_string_property("downloadPackageName", package->get_package_name());
|
||||
_panda_script_object->set_string_property("downloadPackageDisplayName", name);
|
||||
_panda_script_object->set_int_property("downloadPackageNumber", _download_package_index + 1);
|
||||
_panda_script_object->set_int_property("downloadPackageSize", package->get_download_size());
|
||||
set_install_label("Installing " + name);
|
||||
|
||||
nout << "Downloading " << package->get_package_name()
|
||||
@ -1241,6 +1275,7 @@ start_next_download() {
|
||||
<< " bytes.\n";
|
||||
|
||||
package->activate_download();
|
||||
send_notify("ondownloadnext");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1253,10 +1288,12 @@ start_next_download() {
|
||||
_downloading_packages.clear();
|
||||
|
||||
if (get_packages_ready()) {
|
||||
_panda_script_object->set_bool_property("downloadComplete", true);
|
||||
_panda_script_object->set_string_property("status", "starting");
|
||||
send_notify("ondownloadcomplete");
|
||||
|
||||
if (!_panda_script_object->get_bool_property("downloadComplete")) {
|
||||
_panda_script_object->set_bool_property("downloadComplete", true);
|
||||
_panda_script_object->set_string_property("status", "starting");
|
||||
send_notify("ondownloadcomplete");
|
||||
}
|
||||
|
||||
// Notify the session also.
|
||||
if (_session != NULL) {
|
||||
_session->report_packages_done(this, true);
|
||||
|
@ -40,6 +40,7 @@ class P3DDownload;
|
||||
class P3DPackage;
|
||||
class P3DObject;
|
||||
class P3DToplevelObject;
|
||||
class P3DTemporaryFile;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DInstance
|
||||
@ -145,6 +146,9 @@ private:
|
||||
P3D_object *_browser_script_object;
|
||||
P3DToplevelObject *_panda_script_object;
|
||||
|
||||
P3DTemporaryFile *_temp_p3d_filename;
|
||||
P3DTemporaryFile *_temp_splash_image;
|
||||
|
||||
bool _got_fparams;
|
||||
P3DFileParams _fparams;
|
||||
|
||||
@ -156,6 +160,7 @@ private:
|
||||
string _python_version;
|
||||
string _log_basename;
|
||||
bool _full_disk_access;
|
||||
bool _hidden;
|
||||
|
||||
// Not ref-counted: session is the parent.
|
||||
P3DSession *_session;
|
||||
|
@ -60,6 +60,20 @@ get_platform() const {
|
||||
return _platform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::get_log_directory
|
||||
// Access: Public
|
||||
// Description: Returns the pathname of the directory into which all
|
||||
// log files should be written. This filename will end
|
||||
// with a slash or backslash, as appropriate, so that
|
||||
// logfile pathnames may be made by concatenting
|
||||
// directly with this string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline const string &P3DInstanceManager::
|
||||
get_log_directory() const {
|
||||
return _log_directory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::has_contents_file
|
||||
// Access: Public
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "find_root_dir.h"
|
||||
#include "fileSpec.h"
|
||||
#include "get_tinyxml.h"
|
||||
#include "mkdir_complete.h"
|
||||
|
||||
// We can include this header file to get the DTOOL_PLATFORM
|
||||
// definition, even though we don't link with dtool.
|
||||
@ -32,9 +33,12 @@
|
||||
#ifdef _WIN32
|
||||
#include <shlobj.h>
|
||||
#else
|
||||
//#include <sys/stat.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
static ofstream logfile;
|
||||
ostream *nout_stream = &logfile;
|
||||
|
||||
P3DInstanceManager *P3DInstanceManager::_global_ptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -45,6 +49,7 @@ P3DInstanceManager *P3DInstanceManager::_global_ptr;
|
||||
P3DInstanceManager::
|
||||
P3DInstanceManager() {
|
||||
_is_initialized = false;
|
||||
_next_temp_filename_counter = 0;
|
||||
_unique_id = 0;
|
||||
_xcontents = NULL;
|
||||
|
||||
@ -105,6 +110,15 @@ P3DInstanceManager::
|
||||
assert(_instances.empty());
|
||||
assert(_sessions.empty());
|
||||
|
||||
// Delete any remaining temporary files.
|
||||
TempFilenames::iterator ti;
|
||||
for (ti = _temp_filenames.begin(); ti != _temp_filenames.end(); ++ti) {
|
||||
const string &filename = (*ti);
|
||||
nout << "Removing delinquent temp file " << filename << "\n";
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
_temp_filenames.clear();
|
||||
|
||||
nout << "counts: " << _undefined_object->_ref_count
|
||||
<< " " << _none_object->_ref_count
|
||||
<< " " << _true_object->_ref_count
|
||||
@ -138,23 +152,104 @@ P3DInstanceManager::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DInstanceManager::
|
||||
initialize(const string &contents_filename, const string &download_url,
|
||||
const string &platform) {
|
||||
const string &platform, const string &log_directory,
|
||||
const string &log_basename) {
|
||||
|
||||
_root_dir = find_root_dir();
|
||||
_download_url = download_url;
|
||||
#ifdef P3D_PLUGIN_DOWNLOAD
|
||||
if (_download_url.empty()) {
|
||||
_download_url = P3D_PLUGIN_DOWNLOAD;
|
||||
}
|
||||
#endif
|
||||
_platform = platform;
|
||||
if (_platform.empty()) {
|
||||
_platform = DTOOL_PLATFORM;
|
||||
}
|
||||
|
||||
_log_directory = log_directory;
|
||||
#ifdef P3D_PLUGIN_LOG_DIRECTORY
|
||||
if (_log_directory.empty()) {
|
||||
_log_directory = P3D_PLUGIN_LOG_DIRECTORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine the temporary directory.
|
||||
#ifdef _WIN32
|
||||
size_t needs_size_1 = GetTempPath(0, NULL);
|
||||
char *buffer_1 = new char[needs_size_1];
|
||||
if (GetTempPath(needs_size_1, buffer_1) != 0) {
|
||||
_temp_directory = buffer_1;
|
||||
}
|
||||
delete[] buffer_1;
|
||||
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
if (GetTempPath(buffer_size, buffer) != 0) {
|
||||
_temp_directory = buffer;
|
||||
}
|
||||
|
||||
// Also insist that the temp directory is fully specified.
|
||||
size_t needs_size_2 = GetFullPathName(_temp_directory.c_str(), 0, NULL, NULL);
|
||||
char *buffer_2 = new char[needs_size_2];
|
||||
if (GetFullPathName(_temp_directory.c_str(), needs_size_2, buffer_2, NULL) != 0) {
|
||||
_temp_directory = buffer_2;
|
||||
}
|
||||
delete[] buffer_2;
|
||||
|
||||
// Also make sure the directory actually exists.
|
||||
mkdir_complete(_temp_directory, nout);
|
||||
|
||||
#else
|
||||
_temp_directory = "/tmp/";
|
||||
#endif // _WIN32
|
||||
|
||||
// If the log directory is still empty, use the temp directory.
|
||||
if (_log_directory.empty()) {
|
||||
_log_directory = _temp_directory;
|
||||
}
|
||||
|
||||
_log_basename = log_basename;
|
||||
#ifdef P3D_PLUGIN_LOG_BASENAME2
|
||||
if (_log_basename.empty()) {
|
||||
_log_basename = P3D_PLUGIN_LOG_BASENAME2;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure that the download URL ends with a slash.
|
||||
if (!_download_url.empty() && _download_url[_download_url.size() - 1] != '/') {
|
||||
_download_url += "/";
|
||||
}
|
||||
|
||||
// Ensure that the temp directory ends with a slash.
|
||||
if (!_temp_directory.empty() && _temp_directory[_temp_directory.size() - 1] != '/') {
|
||||
#ifdef _WIN32
|
||||
if (_temp_directory[_temp_directory.size() - 1] != '\\')
|
||||
#endif
|
||||
_temp_directory += "/";
|
||||
}
|
||||
|
||||
// Ensure that the log directory ends with a slash.
|
||||
if (!_log_directory.empty() && _log_directory[_log_directory.size() - 1] != '/') {
|
||||
#ifdef _WIN32
|
||||
if (_log_directory[_log_directory.size() - 1] != '\\')
|
||||
#endif
|
||||
_log_directory += "/";
|
||||
}
|
||||
|
||||
// Construct the logfile pathname.
|
||||
if (!_log_basename.empty()) {
|
||||
_log_pathname = _log_directory;
|
||||
_log_pathname += _log_basename;
|
||||
_log_pathname += ".log";
|
||||
|
||||
logfile.open(_log_pathname.c_str(), ios::out | ios::trunc);
|
||||
if (logfile) {
|
||||
logfile.setf(ios::unitbuf);
|
||||
nout_stream = &logfile;
|
||||
}
|
||||
}
|
||||
|
||||
nout << "_root_dir = " << _root_dir
|
||||
<< ", contents = " << contents_filename
|
||||
<< ", download = " << _download_url
|
||||
@ -497,6 +592,82 @@ make_class_definition() const {
|
||||
return new_class;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::make_temp_filename
|
||||
// Access: Public
|
||||
// Description: Constructs a new, unique temporary filename with the
|
||||
// indicated extension. You should use the
|
||||
// P3DTemporaryFilename interface instead of calling
|
||||
// this method directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string P3DInstanceManager::
|
||||
make_temp_filename(const string &extension) {
|
||||
string result;
|
||||
bool exists;
|
||||
|
||||
do {
|
||||
int tid;
|
||||
#ifdef _WIN32
|
||||
tid = GetCurrentProcessId();
|
||||
#else
|
||||
tid = getpid();
|
||||
#endif
|
||||
if (tid == 0) {
|
||||
tid = 1;
|
||||
}
|
||||
int hash = ((clock() + _next_temp_filename_counter) * ((time(NULL) * tid) >> 8)) & 0xffffff;
|
||||
++_next_temp_filename_counter;
|
||||
char hex_code[10];
|
||||
sprintf(hex_code, "%06x", hash);
|
||||
|
||||
result = _temp_directory;
|
||||
result += "p3d_";
|
||||
result += hex_code;
|
||||
result += extension;
|
||||
|
||||
exists = false;
|
||||
if (_temp_filenames.find(result) != _temp_filenames.end()) {
|
||||
// We've previously allocated this file.
|
||||
exists = true;
|
||||
|
||||
} else {
|
||||
|
||||
// Check if the file exists on disk.
|
||||
#ifdef _WIN32
|
||||
DWORD results = GetFileAttributes(result.c_str());
|
||||
if (results != -1) {
|
||||
exists = true;
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
struct stat this_buf;
|
||||
if (stat(result.c_str(), &this_buf) == 0) {
|
||||
exists = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} while (exists);
|
||||
|
||||
nout << "make_temp_filename: " << result << "\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::release_temp_filename
|
||||
// Access: Public
|
||||
// Description: Releases a temporary filename assigned earlier via
|
||||
// make_temp_filename(). If the file exists, it will be
|
||||
// removed. You should use the P3DTemporaryFilename
|
||||
// interface instead of calling this method directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstanceManager::
|
||||
release_temp_filename(const string &filename) {
|
||||
nout << "release_temp_filename: " << filename << "\n";
|
||||
_temp_filenames.erase(filename);
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstanceManager::get_global_ptr
|
||||
// Access: Public, Static
|
||||
|
@ -45,13 +45,16 @@ private:
|
||||
public:
|
||||
bool initialize(const string &contents_filename,
|
||||
const string &download_url,
|
||||
const string &platform);
|
||||
const string &platform,
|
||||
const string &log_directory,
|
||||
const string &log_basename);
|
||||
|
||||
inline bool is_initialized() const;
|
||||
|
||||
inline const string &get_root_dir() const;
|
||||
inline const string &get_download_url() const;
|
||||
inline const string &get_platform() const;
|
||||
inline const string &get_log_directory() const;
|
||||
|
||||
inline bool has_contents_file() const;
|
||||
bool read_contents_file(const string &contents_filename);
|
||||
@ -88,6 +91,9 @@ public:
|
||||
inline P3D_object *new_none_object();
|
||||
inline P3D_object *new_bool_object(bool value);
|
||||
|
||||
string make_temp_filename(const string &extension);
|
||||
void release_temp_filename(const string &filename);
|
||||
|
||||
static P3DInstanceManager *get_global_ptr();
|
||||
static void delete_global_ptr();
|
||||
|
||||
@ -106,6 +112,10 @@ private:
|
||||
string _root_dir;
|
||||
string _download_url;
|
||||
string _platform;
|
||||
string _log_directory;
|
||||
string _log_basename;
|
||||
string _log_pathname;
|
||||
string _temp_directory;
|
||||
|
||||
TiXmlElement *_xcontents;
|
||||
|
||||
@ -123,6 +133,10 @@ private:
|
||||
typedef map<string, P3DPackage *> Packages;
|
||||
Packages _packages;
|
||||
|
||||
typedef set<string> TempFilenames;
|
||||
TempFilenames _temp_filenames;
|
||||
int _next_temp_filename_counter;
|
||||
|
||||
int _unique_id;
|
||||
|
||||
// This condition var is waited on the main thread and signaled in a
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "p3dInstanceManager.h"
|
||||
#include "p3dInstance.h"
|
||||
#include "p3dMultifileReader.h"
|
||||
#include "p3dTemporaryFile.h"
|
||||
#include "mkdir_complete.h"
|
||||
|
||||
#include "zlib.h"
|
||||
@ -53,6 +54,8 @@ P3DPackage(const string &package_name,
|
||||
_package_fullname += string("_") + _package_version;
|
||||
_package_dir += string("/") + _package_version;
|
||||
|
||||
_temp_contents_file = NULL;
|
||||
|
||||
_info_ready = false;
|
||||
_download_size = 0;
|
||||
_allow_data_download = false;
|
||||
@ -85,6 +88,7 @@ P3DPackage::
|
||||
_active_download = NULL;
|
||||
}
|
||||
|
||||
assert(_temp_contents_file == NULL);
|
||||
assert(_instances.empty());
|
||||
}
|
||||
|
||||
@ -179,10 +183,10 @@ download_contents_file() {
|
||||
|
||||
// Download contents.xml to a temporary filename first, in case
|
||||
// multiple packages are downloading it simultaneously.
|
||||
_contents_file_pathname = tempnam(NULL, "p3d_");
|
||||
assert(_temp_contents_file == NULL);
|
||||
_temp_contents_file = new P3DTemporaryFile(".xml");
|
||||
|
||||
cerr << "starting contents download\n";
|
||||
start_download(DT_contents_file, url, _contents_file_pathname, false);
|
||||
start_download(DT_contents_file, url, _temp_contents_file->get_filename(), false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -193,20 +197,18 @@ download_contents_file() {
|
||||
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";
|
||||
if (!success || !inst_mgr->read_contents_file(_temp_contents_file->get_filename())) {
|
||||
nout << "Couldn't read " << *_temp_contents_file << "\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());
|
||||
delete _temp_contents_file;
|
||||
_temp_contents_file = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -214,7 +216,8 @@ contents_file_download_finished(bool success) {
|
||||
|
||||
// The file is correctly installed by now; we can remove the
|
||||
// temporary file.
|
||||
unlink(_contents_file_pathname.c_str());
|
||||
delete _temp_contents_file;
|
||||
_temp_contents_file = NULL;
|
||||
|
||||
download_desc_file();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "get_tinyxml.h"
|
||||
|
||||
class P3DInstance;
|
||||
class P3DTemporaryFile;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DPackage
|
||||
@ -107,7 +108,7 @@ private:
|
||||
string _package_fullname;
|
||||
string _package_dir;
|
||||
|
||||
string _contents_file_pathname;
|
||||
P3DTemporaryFile *_temp_contents_file;
|
||||
|
||||
string _desc_file_basename;
|
||||
string _desc_file_pathname;
|
||||
|
@ -978,7 +978,7 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
|
||||
|
||||
xarg = xarg->NextSiblingElement("arg");
|
||||
}
|
||||
|
||||
|
||||
PyObject *result = PyObject_CallMethod
|
||||
(_runner, (char *)"setP3DFilename", (char *)"sOOi", p3d_filename.c_str(),
|
||||
token_list, arg_list, inst->get_instance_id());
|
||||
|
@ -650,6 +650,8 @@ start_p3dpython(P3DInstance *inst) {
|
||||
return;
|
||||
}
|
||||
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
|
||||
_python_root_dir = inst->_panda3d->get_package_dir();
|
||||
|
||||
// We'll be changing the directory to the standard start directory
|
||||
@ -699,7 +701,7 @@ start_p3dpython(P3DInstance *inst) {
|
||||
const char *keep[] = {
|
||||
"TMP", "TEMP", "HOME", "USER",
|
||||
#ifdef _WIN32
|
||||
"SYSTEMROOT", "USERPROFILE", "COMSPEC",
|
||||
"SYSTEMROOT", "USERPROFILE", "COMSPEC", "PANDA_ROOT",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@ -766,7 +768,17 @@ start_p3dpython(P3DInstance *inst) {
|
||||
log_basename = inst->get_fparams().lookup_token("log_basename");
|
||||
}
|
||||
|
||||
// However, it is always written into the temp directory only; the
|
||||
bool console_output = (inst->get_fparams().lookup_token_int("console_output") != 0);
|
||||
|
||||
#ifdef P3D_PLUGIN_LOG_BASENAME3
|
||||
if (log_basename.empty()) {
|
||||
// No log_basename specified for the app; use the compiled-in
|
||||
// default.
|
||||
log_basename = P3D_PLUGIN_LOG_BASENAME3;
|
||||
}
|
||||
#endif
|
||||
|
||||
// However, it is always written into the log directory only; the
|
||||
// user may not override the log file to put it anywhere else.
|
||||
size_t slash = log_basename.rfind('/');
|
||||
if (slash != string::npos) {
|
||||
@ -779,32 +791,24 @@ start_p3dpython(P3DInstance *inst) {
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
if (!log_basename.empty()) {
|
||||
#ifdef _WIN32
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
if (GetTempPath(buffer_size, buffer) != 0) {
|
||||
_output_filename = buffer;
|
||||
}
|
||||
#else
|
||||
_output_filename = "/tmp/";
|
||||
#endif // _WIN32
|
||||
_output_filename += log_basename;
|
||||
if (!console_output && !log_basename.empty()) {
|
||||
_log_pathname = inst_mgr->get_log_directory();
|
||||
_log_pathname += log_basename;
|
||||
|
||||
// We always tack on the extension ".log", to make it even more
|
||||
// difficult to overwrite a system file.
|
||||
_output_filename += ".log";
|
||||
_log_pathname += ".log";
|
||||
}
|
||||
|
||||
nout << "Attempting to start python from " << p3dpython << "\n";
|
||||
#ifdef _WIN32
|
||||
_p3dpython_handle = win_create_process
|
||||
(p3dpython, start_dir, env, _output_filename,
|
||||
(p3dpython, start_dir, env, _log_pathname,
|
||||
_pipe_read, _pipe_write);
|
||||
bool started_p3dpython = (_p3dpython_handle != INVALID_HANDLE_VALUE);
|
||||
#else
|
||||
_p3dpython_pid = posix_create_process
|
||||
(p3dpython, start_dir, env, _output_filename,
|
||||
(p3dpython, start_dir, env, _log_pathname,
|
||||
_pipe_read, _pipe_write);
|
||||
bool started_p3dpython = (_p3dpython_pid > 0);
|
||||
#endif
|
||||
@ -976,7 +980,7 @@ rt_terminate() {
|
||||
// Access: Private, Static
|
||||
// Description: Creates a sub-process to run the named program
|
||||
// executable, with the indicated environment string.
|
||||
// Standard error is logged to output_filename, if that
|
||||
// Standard error is logged to log_pathname, if that
|
||||
// string is nonempty.
|
||||
//
|
||||
// Opens the two HandleStreams as the read and write
|
||||
@ -988,7 +992,7 @@ rt_terminate() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
HANDLE P3DSession::
|
||||
win_create_process(const string &program, const string &start_dir,
|
||||
const string &env, const string &output_filename,
|
||||
const string &env, const string &log_pathname,
|
||||
HandleStream &pipe_read, HandleStream &pipe_write) {
|
||||
|
||||
// Create a bi-directional pipe to communicate with the sub-process.
|
||||
@ -1013,19 +1017,19 @@ win_create_process(const string &program, const string &start_dir,
|
||||
}
|
||||
|
||||
HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
bool got_output_filename = !output_filename.empty();
|
||||
if (got_output_filename) {
|
||||
bool got_log_pathname = !log_pathname.empty();
|
||||
if (got_log_pathname) {
|
||||
// Open the named file for output and redirect the child's stderr
|
||||
// into it.
|
||||
HANDLE handle = CreateFile
|
||||
(output_filename.c_str(), GENERIC_WRITE,
|
||||
(log_pathname.c_str(), GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
error_handle = handle;
|
||||
SetHandleInformation(error_handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||
} else {
|
||||
nout << "Unable to open " << output_filename << "\n";
|
||||
nout << "Unable to open " << log_pathname << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1063,7 +1067,7 @@ win_create_process(const string &program, const string &start_dir,
|
||||
// Close the pipe handles that are now owned by the child.
|
||||
CloseHandle(w_from);
|
||||
CloseHandle(r_to);
|
||||
if (got_output_filename) {
|
||||
if (got_log_pathname) {
|
||||
CloseHandle(error_handle);
|
||||
}
|
||||
|
||||
@ -1099,7 +1103,7 @@ win_create_process(const string &program, const string &start_dir,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int P3DSession::
|
||||
posix_create_process(const string &program, const string &start_dir,
|
||||
const string &env, const string &output_filename,
|
||||
const string &env, const string &log_pathname,
|
||||
HandleStream &pipe_read, HandleStream &pipe_write) {
|
||||
// Create a bi-directional pipe to communicate with the sub-process.
|
||||
int to_fd[2];
|
||||
@ -1124,14 +1128,14 @@ posix_create_process(const string &program, const string &start_dir,
|
||||
|
||||
if (child == 0) {
|
||||
// Here we are in the child process.
|
||||
bool got_output_filename = !output_filename.empty();
|
||||
if (got_output_filename) {
|
||||
bool got_log_pathname = !log_pathname.empty();
|
||||
if (got_log_pathname) {
|
||||
// Open the named file for output and redirect the child's stderr
|
||||
// into it.
|
||||
int logfile_fd = open(output_filename.c_str(),
|
||||
int logfile_fd = open(log_pathname.c_str(),
|
||||
O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (logfile_fd < 0) {
|
||||
nout << "Unable to open " << output_filename << "\n";
|
||||
nout << "Unable to open " << log_pathname << "\n";
|
||||
} else {
|
||||
dup2(logfile_fd, STDERR_FILENO);
|
||||
close(logfile_fd);
|
||||
|
@ -90,7 +90,7 @@ private:
|
||||
int _session_id;
|
||||
string _session_key;
|
||||
string _python_version;
|
||||
string _output_filename;
|
||||
string _log_pathname;
|
||||
string _python_root_dir;
|
||||
string _start_dir;
|
||||
|
||||
|
24
direct/src/plugin/p3dTemporaryFile.I
Normal file
24
direct/src/plugin/p3dTemporaryFile.I
Normal file
@ -0,0 +1,24 @@
|
||||
// Filename: p3dTemporaryFile.I
|
||||
// Created by: drose (19Aug09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DTemporaryFile::get_filename
|
||||
// Access: Public
|
||||
// Description: Returns the temporary filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline const string &P3DTemporaryFile::
|
||||
get_filename() const {
|
||||
return _filename;
|
||||
}
|
38
direct/src/plugin/p3dTemporaryFile.cxx
Normal file
38
direct/src/plugin/p3dTemporaryFile.cxx
Normal file
@ -0,0 +1,38 @@
|
||||
// Filename: p3dTemporaryFile.cxx
|
||||
// Created by: drose (19Aug09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "p3dTemporaryFile.h"
|
||||
#include "p3dInstanceManager.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DTemporaryFile::Constructor
|
||||
// Access: Public
|
||||
// Description: Constructs a new, unique temporary filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DTemporaryFile::
|
||||
P3DTemporaryFile(const string &extension) {
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
_filename = inst_mgr->make_temp_filename(extension);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DTemporaryFile::Destructor
|
||||
// Access: Public
|
||||
// Description: Deletes the temporary file, if it exists.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
P3DTemporaryFile::
|
||||
~P3DTemporaryFile() {
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
inst_mgr->release_temp_filename(_filename);
|
||||
}
|
47
direct/src/plugin/p3dTemporaryFile.h
Normal file
47
direct/src/plugin/p3dTemporaryFile.h
Normal file
@ -0,0 +1,47 @@
|
||||
// Filename: p3dTemporaryFile.h
|
||||
// Created by: drose (19Aug09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef P3DTEMPORARYFILE_H
|
||||
#define P3DTEMPORARYFILE_H
|
||||
|
||||
#include "p3d_plugin_common.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : P3DTemporaryFile
|
||||
// Description : This represents a temporary filename for some
|
||||
// transitory purpose. This returns a filename which is
|
||||
// guaranteed to be unique at the time the constructor
|
||||
// was called.
|
||||
//
|
||||
// The file on disk, if it exists, will automatically be
|
||||
// deleted when the destructor is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class P3DTemporaryFile {
|
||||
public:
|
||||
P3DTemporaryFile(const string &extension);
|
||||
~P3DTemporaryFile();
|
||||
|
||||
inline const string &get_filename() const;
|
||||
|
||||
private:
|
||||
string _filename;
|
||||
};
|
||||
|
||||
inline ostream &operator << (ostream &out, P3DTemporaryFile &tfile) {
|
||||
return out << tfile.get_filename();
|
||||
}
|
||||
|
||||
#include "p3dTemporaryFile.I"
|
||||
|
||||
#endif
|
@ -17,13 +17,23 @@
|
||||
// Function: P3DWindowParams::get_window_type
|
||||
// Access: Public
|
||||
// Description: Returns the window_type that was passed to the
|
||||
// constructor.
|
||||
// constructor, or to set_window_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline P3D_window_type P3DWindowParams::
|
||||
get_window_type() const {
|
||||
return _window_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWindowParams::set_window_type
|
||||
// Access: Public
|
||||
// Description: Changes the window_type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void P3DWindowParams::
|
||||
set_window_type(P3D_window_type window_type) {
|
||||
_window_type = window_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DWindowParams::get_window_x
|
||||
// Access: Public
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
void operator = (const P3DWindowParams &other);
|
||||
|
||||
inline P3D_window_type get_window_type() const;
|
||||
inline void set_window_type(P3D_window_type window_type);
|
||||
|
||||
inline int get_win_x() const;
|
||||
inline int get_win_y() const;
|
||||
inline int get_win_width() const;
|
||||
|
@ -32,14 +32,10 @@
|
||||
bool initialized_lock = false;
|
||||
LOCK _api_lock;
|
||||
|
||||
ofstream logfile;
|
||||
string plugin_output_filename;
|
||||
ostream *nout_stream;
|
||||
|
||||
|
||||
bool
|
||||
P3D_initialize(int api_version, const char *contents_filename,
|
||||
const char *download_url, const char *platform) {
|
||||
const char *download_url, const char *platform,
|
||||
const char *log_directory, const char *log_basename) {
|
||||
if (api_version != P3D_API_VERSION) {
|
||||
// Can't accept an incompatible version.
|
||||
return false;
|
||||
@ -63,36 +59,17 @@ P3D_initialize(int api_version, const char *contents_filename,
|
||||
platform = "";
|
||||
}
|
||||
|
||||
#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 (log_directory == NULL) {
|
||||
log_directory = "";
|
||||
}
|
||||
|
||||
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;
|
||||
if (log_basename == NULL) {
|
||||
log_basename = "";
|
||||
}
|
||||
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
bool result = inst_mgr->initialize(contents_filename, download_url, platform);
|
||||
bool result = inst_mgr->initialize(contents_filename, download_url,
|
||||
platform, log_directory, log_basename);
|
||||
RELEASE_LOCK(_api_lock);
|
||||
return result;
|
||||
}
|
||||
|
@ -101,13 +101,26 @@ extern "C" {
|
||||
If platform is not NULL or empty, it specifies the current platform
|
||||
string; otherwise, the compiled-in default is used.
|
||||
|
||||
If log_directory is not NULL or empty, it specifies the directory
|
||||
into which all log files will be written; otherwise, the
|
||||
compiled-in default will be used, or the system temp directory if
|
||||
no default is compiled in.
|
||||
|
||||
If log_basename is not NULL or empty, it specifies the filename in
|
||||
log_directory to which the core API's logfile output will be
|
||||
written. Otherwise, the compiled-in default is used; if there is
|
||||
no compiled-in default, no logfile output will be generated by the
|
||||
core API. Note that the individual instances also have their own
|
||||
log_basename values.
|
||||
|
||||
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 *contents_filename,
|
||||
const char *download_url, const char *platform);
|
||||
const char *download_url, const char *platform,
|
||||
const char *log_directory, const char *log_basename);
|
||||
|
||||
/* This function should be called to unload the core API. It will
|
||||
release all internally-allocated memory and return the core API to
|
||||
|
@ -38,8 +38,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Appears in p3d_plugin.cxx.
|
||||
extern string plugin_output_filename;
|
||||
// Appears in p3dInstanceManager.cxx.
|
||||
extern ostream *nout_stream;
|
||||
#define nout (*nout_stream)
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "p3dSession.cxx"
|
||||
#include "p3dSplashWindow.cxx"
|
||||
#include "p3dStringObject.cxx"
|
||||
#include "p3dTemporaryFile.cxx"
|
||||
#include "p3dToplevelObject.cxx"
|
||||
#include "p3dUndefinedObject.cxx"
|
||||
#include "p3dWinSplashWindow.cxx"
|
||||
|
@ -13,8 +13,10 @@
|
||||
|
||||
/* The filename(s) to generate output to when the plugin is running.
|
||||
For debugging purposes only. */
|
||||
#$[]define P3D_PLUGIN_LOGFILE1 "$[subst \,\\,$[osfilename $[P3D_PLUGIN_LOGFILE1]]]"
|
||||
#$[]define P3D_PLUGIN_LOGFILE2 "$[subst \,\\,$[osfilename $[P3D_PLUGIN_LOGFILE2]]]"
|
||||
#$[]define P3D_PLUGIN_LOG_DIRECTORY "$[subst \,\\,$[osfilename $[P3D_PLUGIN_LOG_DIRECTORY]]]"
|
||||
#$[]define P3D_PLUGIN_LOG_BASENAME1 "$[P3D_PLUGIN_LOG_BASENAME1]"
|
||||
#$[]define P3D_PLUGIN_LOG_BASENAME2 "$[P3D_PLUGIN_LOG_BASENAME2]"
|
||||
#$[]define P3D_PLUGIN_LOG_BASENAME3 "$[P3D_PLUGIN_LOG_BASENAME3]"
|
||||
|
||||
/* For development only: the location at which p3dpython.exe can be
|
||||
found. Empty string for the default. */
|
||||
|
@ -928,7 +928,7 @@ do_load_plugin() {
|
||||
#endif // P3D_PLUGIN_P3D_PLUGIN
|
||||
|
||||
nout << "Attempting to load core API from " << pathname << "\n";
|
||||
if (!load_plugin(pathname, "", "", "")) {
|
||||
if (!load_plugin(pathname, "", "", "", "", "")) {
|
||||
nout << "Unable to launch core API in " << pathname << "\n";
|
||||
return;
|
||||
}
|
||||
|
@ -30,26 +30,44 @@ static bool logfile_is_open = false;
|
||||
static void
|
||||
open_logfile() {
|
||||
if (!logfile_is_open) {
|
||||
#ifdef P3D_PLUGIN_LOGFILE1
|
||||
string logfilename = P3D_PLUGIN_LOGFILE1;
|
||||
#else
|
||||
string logfilename;
|
||||
#endif // P3D_PLUGIN_LOGFILE1
|
||||
// Note that this logfile name may not be specified at runtime. It
|
||||
// must be compiled in if it is specified at all.
|
||||
|
||||
if (logfilename.empty()) {
|
||||
string log_basename;
|
||||
#ifdef P3D_PLUGIN_LOG_BASENAME1
|
||||
log_basename = P3D_PLUGIN_LOG_BASENAME1;
|
||||
#endif
|
||||
|
||||
if (!log_basename.empty()) {
|
||||
// Get the log directory.
|
||||
string log_directory;
|
||||
#ifdef P3D_PLUGIN_LOG_DIRECTORY
|
||||
log_directory = P3D_PLUGIN_LOG_DIRECTORY;
|
||||
#endif
|
||||
if (log_directory.empty()) {
|
||||
#ifdef _WIN32
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
if (GetTempPath(buffer_size, buffer) != 0) {
|
||||
logfilename = buffer;
|
||||
logfilename += "panda3d.1.log";
|
||||
}
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
if (GetTempPath(buffer_size, buffer) != 0) {
|
||||
log_directory = buffer;
|
||||
}
|
||||
#else
|
||||
logfilename = "/tmp/panda3d.1.log";
|
||||
log_directory = "/tmp/";
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
// Construct the full logfile pathname.
|
||||
string log_pathname = log_directory;
|
||||
log_pathname += log_basename;
|
||||
log_pathname += ".log";
|
||||
|
||||
logfile.open(log_pathname.c_str());
|
||||
logfile.setf(ios::unitbuf);
|
||||
}
|
||||
logfile.open(logfilename.c_str());
|
||||
logfile.setf(ios::unitbuf);
|
||||
|
||||
// If we didn't have a logfile name compiled in, we throw away log
|
||||
// output by the simple expedient of never actually opening the
|
||||
// ofstream.
|
||||
logfile_is_open = true;
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
Panda3D::
|
||||
Panda3D() {
|
||||
_root_dir = find_root_dir();
|
||||
_reporting_download = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -60,7 +61,7 @@ run(int argc, char *argv[]) {
|
||||
// We prefix a "+" sign to tell gnu getopt not to parse options
|
||||
// following the first not-option parameter. (These will be passed
|
||||
// into the sub-process.)
|
||||
const char *optstr = "+mu:p:ft:s:o:h";
|
||||
const char *optstr = "+mu:p:ft:s:o:l:h";
|
||||
|
||||
bool allow_multiple = false;
|
||||
string download_url = P3D_PLUGIN_DOWNLOAD;
|
||||
@ -69,7 +70,7 @@ run(int argc, char *argv[]) {
|
||||
|
||||
P3D_window_type window_type = P3D_WT_toplevel;
|
||||
int win_x = 0, win_y = 0;
|
||||
int win_width = 0, win_height = 0;
|
||||
int win_width = 640, win_height = 480;
|
||||
|
||||
int flag = getopt(argc, argv, optstr);
|
||||
|
||||
@ -120,6 +121,11 @@ run(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
_log_dirname = Filename::from_os_specific(optarg).to_os_specific();
|
||||
_log_basename = "panda3d";
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
case '+':
|
||||
@ -321,7 +327,6 @@ get_plugin(const string &download_url, const string &this_platform, bool force_d
|
||||
// Couldn't read it, so go get it.
|
||||
string url = download_url;
|
||||
url += "contents.xml";
|
||||
cerr << "Getting URL " << url << "\n";
|
||||
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
PT(HTTPChannel) channel = http->get_document(url);
|
||||
@ -436,7 +441,8 @@ get_core_api(const Filename &contents_filename, const string &download_url,
|
||||
#endif // P3D_PLUGIN_P3D_PLUGIN
|
||||
|
||||
if (!load_plugin(pathname, contents_filename.to_os_specific(),
|
||||
download_url, this_platform)) {
|
||||
download_url, this_platform, _log_dirname,
|
||||
_log_basename)) {
|
||||
cerr << "Unable to launch core API in " << pathname << "\n" << flush;
|
||||
return false;
|
||||
}
|
||||
@ -481,7 +487,6 @@ handle_request(P3D_request *request) {
|
||||
|
||||
switch (request->_request_type) {
|
||||
case P3D_RT_stop:
|
||||
cerr << "Got P3D_RT_stop\n";
|
||||
delete_instance(request->_instance);
|
||||
#ifdef _WIN32
|
||||
// Post a silly message to spin the event loop.
|
||||
@ -491,8 +496,6 @@ handle_request(P3D_request *request) {
|
||||
break;
|
||||
|
||||
case P3D_RT_get_url:
|
||||
cerr << "Got P3D_RT_get_url: " << request->_request._get_url._url
|
||||
<< "\n";
|
||||
{
|
||||
int unique_id = request->_request._get_url._unique_id;
|
||||
const string &url = request->_request._get_url._url;
|
||||
@ -504,8 +507,6 @@ handle_request(P3D_request *request) {
|
||||
break;
|
||||
|
||||
case P3D_RT_post_url:
|
||||
cerr << "Got P3D_RT_post_url: " << request->_request._post_url._url
|
||||
<< "\n";
|
||||
{
|
||||
int unique_id = request->_request._post_url._unique_id;
|
||||
const string &url = request->_request._post_url._url;
|
||||
@ -519,9 +520,15 @@ handle_request(P3D_request *request) {
|
||||
break;
|
||||
|
||||
case P3D_RT_notify:
|
||||
cerr << "Got P3D_RT_notify: " << request->_request._notify._message
|
||||
<< "\n";
|
||||
// Ignore notifications.
|
||||
{
|
||||
if (strcmp(request->_request._notify._message, "ondownloadnext") == 0) {
|
||||
// Tell the user we're downloading a package.
|
||||
report_downloading_package(request->_instance);
|
||||
} else if (strcmp(request->_request._notify._message, "ondownloadcomplete") == 0) {
|
||||
// Tell the user we're done downloading.
|
||||
report_download_complete(request->_instance);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -624,6 +631,30 @@ create_instance(const string &p3d, P3D_window_type window_type,
|
||||
is_local = true;
|
||||
}
|
||||
|
||||
// Build up the token list.
|
||||
pvector<P3D_token> tokens;
|
||||
string log_basename;
|
||||
if (!_log_dirname.empty()) {
|
||||
// Generate output to a logfile.
|
||||
log_basename = p3d_filename.get_basename_wo_extension();
|
||||
P3D_token token;
|
||||
token._keyword = "log_basename";
|
||||
token._value = log_basename.c_str();
|
||||
tokens.push_back(token);
|
||||
} else {
|
||||
// Send output to the console.
|
||||
P3D_token token;
|
||||
token._keyword = "console_output";
|
||||
token._value = "1";
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
P3D_token *tokens_p;
|
||||
size_t num_tokens = tokens.size();
|
||||
if (!tokens.empty()) {
|
||||
tokens_p = &tokens[0];
|
||||
}
|
||||
|
||||
// Build up the argument list, beginning with the p3d_filename.
|
||||
pvector<const char *> argv;
|
||||
argv.push_back(os_p3d_filename.c_str());
|
||||
@ -631,13 +662,15 @@ create_instance(const string &p3d, P3D_window_type window_type,
|
||||
argv.push_back(args[i]);
|
||||
}
|
||||
|
||||
P3D_instance *inst = P3D_new_instance(NULL, NULL, 0,
|
||||
P3D_instance *inst = P3D_new_instance(NULL, tokens_p, num_tokens,
|
||||
argv.size(), &argv[0], NULL);
|
||||
|
||||
if (inst != NULL) {
|
||||
// We call start() first, to give the core API a chance to notice
|
||||
// the "hidden" attrib before we set the window parameters.
|
||||
P3D_instance_start(inst, is_local, os_p3d_filename.c_str());
|
||||
P3D_instance_setup_window
|
||||
(inst, window_type, win_x, win_y, win_width, win_height, parent_window);
|
||||
P3D_instance_start(inst, is_local, os_p3d_filename.c_str());
|
||||
}
|
||||
|
||||
return inst;
|
||||
@ -682,10 +715,10 @@ usage() {
|
||||
<< " panda3d -m [opts] file_a.p3d file_b.p3d [file_c.p3d ...]\n\n"
|
||||
|
||||
<< "This program is used to execute a Panda3D application bundle stored\n"
|
||||
<< "in a .p3d file. In the first form, without a -m option, it\n"
|
||||
<< "in a .p3d file. In the first form, without the -m option, it\n"
|
||||
<< "executes one application; remaining arguments following the\n"
|
||||
<< "application name are passed into the application. In the second\n"
|
||||
<< "form, with a -m option, it can execute multiple applications\n"
|
||||
<< "form, with the -m option, it can execute multiple applications\n"
|
||||
<< "simultaneously, though in this form arguments cannot be passed into\n"
|
||||
<< "the applications.\n\n"
|
||||
|
||||
@ -708,6 +741,11 @@ usage() {
|
||||
<< " Specify the position (origin) of the graphic window on the\n"
|
||||
<< " screen, or on the parent window.\n\n"
|
||||
|
||||
<< " -l log_dirname\n"
|
||||
<< " Specify the full path to the directory in which log files are\n"
|
||||
<< " to be written. If this is not specified, the default is to send\n"
|
||||
<< " the application output to the console.\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"
|
||||
@ -743,6 +781,44 @@ parse_int_pair(char *arg, int &x, int &y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::report_downloading_package
|
||||
// Access: Private
|
||||
// Description: Tells the user we have to download a package.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
report_downloading_package(P3D_instance *instance) {
|
||||
P3D_object *obj = P3D_instance_get_panda_script_object(instance);
|
||||
|
||||
P3D_object *display_name = P3D_object_get_property(obj, "downloadPackageDisplayName");
|
||||
if (display_name == NULL) {
|
||||
cerr << "no name: " << obj << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int name_length = P3D_object_get_string(display_name, NULL, 0);
|
||||
char *name = new char[name_length + 1];
|
||||
P3D_object_get_string(display_name, name, name_length + 1);
|
||||
|
||||
cerr << "Downloading " << name << "\n";
|
||||
|
||||
delete[] name;
|
||||
P3D_object_decref(display_name);
|
||||
_reporting_download = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::report_download_complete
|
||||
// Access: Private
|
||||
// Description: Tells the user we're done downloading packages
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Panda3D::
|
||||
report_download_complete(P3D_instance *instance) {
|
||||
if (_reporting_download) {
|
||||
cerr << "Download complete.\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::URLGetter::Constructor
|
||||
// Access: Public
|
||||
@ -758,8 +834,6 @@ URLGetter(P3D_instance *instance, int unique_id,
|
||||
{
|
||||
HTTPClient *http = HTTPClient::get_global_ptr();
|
||||
|
||||
cerr << "Getting URL " << _url << "\n";
|
||||
|
||||
_channel = http->make_channel(false);
|
||||
if (_post_data.empty()) {
|
||||
_channel->begin_get_document(_url);
|
||||
@ -815,8 +889,6 @@ run() {
|
||||
status = P3D_RC_generic_error;
|
||||
}
|
||||
cerr << "Error getting URL " << _url << "\n";
|
||||
} else {
|
||||
cerr << "Done getting URL " << _url << ", got " << _bytes_sent << " bytes\n";
|
||||
}
|
||||
|
||||
P3D_instance_feed_url_stream
|
||||
|
@ -65,9 +65,15 @@ private:
|
||||
void usage();
|
||||
bool parse_int_pair(char *arg, int &x, int &y);
|
||||
|
||||
void report_downloading_package(P3D_instance *instance);
|
||||
void report_download_complete(P3D_instance *instance);
|
||||
|
||||
private:
|
||||
string _root_dir;
|
||||
string _log_dirname;
|
||||
string _log_basename;
|
||||
FileSpec _core_api_dll;
|
||||
bool _reporting_download;
|
||||
|
||||
typedef pset<P3D_instance *> Instances;
|
||||
Instances _instances;
|
||||
|
@ -84,7 +84,7 @@ def makePackedApp(args):
|
||||
elif option == '-h':
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if not args:
|
||||
raise ArgumentError, "No destination app specified. Use:\npackp3d.py app.p3d"
|
||||
|
||||
@ -133,10 +133,6 @@ def main(appRunner):
|
||||
""" This function is called when this module is invoked as
|
||||
packp3d.p3d. """
|
||||
|
||||
print "args = %s" % (appRunner.argv,)
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
print "cwd = %s, %s" % (vfs.getCwd(), ExecutionEnvironment.getCwd())
|
||||
print "sys.path = %s" % (sys.path,)
|
||||
try:
|
||||
makePackedApp(appRunner.argv[1:])
|
||||
except ArgumentError, e:
|
||||
@ -145,7 +141,6 @@ def main(appRunner):
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "sys.path = %s" % (sys.path,)
|
||||
try:
|
||||
makePackedApp(sys.argv[1:])
|
||||
except ArgumentError, e:
|
||||
|
@ -244,7 +244,6 @@ class AppRunner(DirectObject):
|
||||
same page with the Panda3D plugin. """
|
||||
|
||||
self.dom = dom
|
||||
print "setBrowserScriptObject(%s)" % (dom)
|
||||
|
||||
# Now evaluate any deferred expressions.
|
||||
for expression in self.deferredEvals:
|
||||
@ -334,11 +333,6 @@ class AppRunner(DirectObject):
|
||||
settings, for future windows; or applies them directly to the
|
||||
main window if the window has already been opened. """
|
||||
|
||||
print "session %s, nextScriptId = %s" % (self.sessionId, self.nextScriptId)
|
||||
|
||||
|
||||
print "setupWindow %s, %s, %s, %s, %s, %s, %s" % (windowType, x, y, width, height, parent, subprocessWindow)
|
||||
|
||||
if self.started and base.win:
|
||||
# If we've already got a window, this must be a
|
||||
# resize/reposition request.
|
||||
|
@ -248,7 +248,7 @@ open = file
|
||||
def listdir(path):
|
||||
""" Implements os.listdir over vfs. """
|
||||
files = []
|
||||
dirlist = _vfs.scanDirectory(path)
|
||||
dirlist = _vfs.scanDirectory(pm.Filename.fromOsSpecific(path))
|
||||
if dirlist is None:
|
||||
message = 'No such file or directory: %s' % (path)
|
||||
raise OSError, message
|
||||
|
Loading…
x
Reference in New Issue
Block a user