diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index 1794fcd86a..468c9e194e 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -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 \ diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index ef66137acf..1dae223e75 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.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(); diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index 455cbd106c..9e4511b61c 100755 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -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(); diff --git a/direct/src/plugin/p3dFileParams.cxx b/direct/src/plugin/p3dFileParams.cxx index e5cdbb235e..8b324d5fce 100644 --- a/direct/src/plugin/p3dFileParams.cxx +++ b/direct/src/plugin/p3dFileParams.cxx @@ -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 diff --git a/direct/src/plugin/p3dFileParams.h b/direct/src/plugin/p3dFileParams.h index 78efa22058..31c1859cba 100644 --- a/direct/src/plugin/p3dFileParams.h +++ b/direct/src/plugin/p3dFileParams.h @@ -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(); diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 996724333f..2d3fd0c405 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -25,6 +25,7 @@ #include "p3dToplevelObject.h" #include "p3dUndefinedObject.h" #include "p3dMultifileReader.h" +#include "p3dTemporaryFile.h" #include #include @@ -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); diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index 603f44e1b7..c8e6b44854 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -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; diff --git a/direct/src/plugin/p3dInstanceManager.I b/direct/src/plugin/p3dInstanceManager.I index 706b69120f..2fa2fa7e2a 100644 --- a/direct/src/plugin/p3dInstanceManager.I +++ b/direct/src/plugin/p3dInstanceManager.I @@ -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 diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 8b254e7578..50574c9e5f 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -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 #else -//#include +#include #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 diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index 0faa3d7fc6..c7a803e188 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -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 Packages; Packages _packages; + typedef set 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 diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index 4ae7faba96..1383c47187 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -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(); } diff --git a/direct/src/plugin/p3dPackage.h b/direct/src/plugin/p3dPackage.h index 7203a48dcb..ff9917625e 100755 --- a/direct/src/plugin/p3dPackage.h +++ b/direct/src/plugin/p3dPackage.h @@ -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; diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 6e43a8e329..f09872b047 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -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()); diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index 56fca9ddda..692a1e1231 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -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); diff --git a/direct/src/plugin/p3dSession.h b/direct/src/plugin/p3dSession.h index 250628a8c4..af15b1f931 100644 --- a/direct/src/plugin/p3dSession.h +++ b/direct/src/plugin/p3dSession.h @@ -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; diff --git a/direct/src/plugin/p3dTemporaryFile.I b/direct/src/plugin/p3dTemporaryFile.I new file mode 100644 index 0000000000..ae878afa8b --- /dev/null +++ b/direct/src/plugin/p3dTemporaryFile.I @@ -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; +} diff --git a/direct/src/plugin/p3dTemporaryFile.cxx b/direct/src/plugin/p3dTemporaryFile.cxx new file mode 100644 index 0000000000..ca83347b64 --- /dev/null +++ b/direct/src/plugin/p3dTemporaryFile.cxx @@ -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); +} diff --git a/direct/src/plugin/p3dTemporaryFile.h b/direct/src/plugin/p3dTemporaryFile.h new file mode 100644 index 0000000000..7e17b80c1c --- /dev/null +++ b/direct/src/plugin/p3dTemporaryFile.h @@ -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 diff --git a/direct/src/plugin/p3dWindowParams.I b/direct/src/plugin/p3dWindowParams.I index 8aa06c8707..eb67cc84c5 100644 --- a/direct/src/plugin/p3dWindowParams.I +++ b/direct/src/plugin/p3dWindowParams.I @@ -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 diff --git a/direct/src/plugin/p3dWindowParams.h b/direct/src/plugin/p3dWindowParams.h index fd93bc5545..17b3001c98 100644 --- a/direct/src/plugin/p3dWindowParams.h +++ b/direct/src/plugin/p3dWindowParams.h @@ -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; diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index db91e162e6..8d45422111 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -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; } diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index 123484b93e..15c4048a32 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -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 diff --git a/direct/src/plugin/p3d_plugin_common.h b/direct/src/plugin/p3d_plugin_common.h index ce40837f93..53ab372740 100644 --- a/direct/src/plugin/p3d_plugin_common.h +++ b/direct/src/plugin/p3d_plugin_common.h @@ -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) diff --git a/direct/src/plugin/p3d_plugin_composite1.cxx b/direct/src/plugin/p3d_plugin_composite1.cxx index 2f207e7378..fd6c806cab 100644 --- a/direct/src/plugin/p3d_plugin_composite1.cxx +++ b/direct/src/plugin/p3d_plugin_composite1.cxx @@ -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" diff --git a/direct/src/plugin/p3d_plugin_config.h.pp b/direct/src/plugin/p3d_plugin_config.h.pp index 36678f5f68..891f63dc75 100644 --- a/direct/src/plugin/p3d_plugin_config.h.pp +++ b/direct/src/plugin/p3d_plugin_config.h.pp @@ -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. */ diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 794c4e2661..e0140cd51d 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -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; } diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index e4b709d844..dd3006310b 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -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; } } diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index 2376fda359..56e736161d 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -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 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 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 diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index 6929a5d85b..f695b3798f 100755 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -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 Instances; Instances _instances; diff --git a/direct/src/showutil/packp3d.py b/direct/src/showutil/packp3d.py index 222d6a0fe9..045aa930c7 100755 --- a/direct/src/showutil/packp3d.py +++ b/direct/src/showutil/packp3d.py @@ -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: diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index 400eea7259..44b99e3796 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -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. diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index d70a5058aa..902837e161 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -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