// Filename: pandaSystem.cxx // Created by: drose (26Jan05) // //////////////////////////////////////////////////////////////////// // // 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 "pandaSystem.h" #include "pandaVersion.h" #include "dtool_platform.h" PandaSystem *PandaSystem::_global_ptr = NULL; TypeHandle PandaSystem::_type_handle; //////////////////////////////////////////////////////////////////// // Function: PandaSystem::Constructor // Access: Protected // Description: Don't try to construct a PandaSystem object; there is // only one of these, and it constructs itself. Use // get_global_ptr() to get a pointer to the one // PandaSystem. //////////////////////////////////////////////////////////////////// PandaSystem:: PandaSystem() : _systems(get_class_type()) { _system_names_dirty = false; // These are settable via Config.prc, but only in development // (!NDEBUG) mode, and only if they are not already defined. _package_version_string = PANDA_PACKAGE_VERSION_STR; _package_host_url = PANDA_PACKAGE_HOST_URL; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::Destructor // Access: Protected // Description: Don't try to destruct the global PandaSystem object. //////////////////////////////////////////////////////////////////// PandaSystem:: ~PandaSystem() { } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_version_string // Access: Published, Static // Description: Returns the current version of Panda, expressed as a // string, e.g. "1.0.0". The string will end in the // letter "c" if this build does not represent an // official version. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_version_string() { return PANDA_VERSION_STR; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_package_version_string // Access: Published, Static // Description: Returns the version of the Panda3D distributable // package that provides this build of Panda. // // When the currently-executing version of Panda was // loaded from a distributable package, such as via the // browser plugin, then this string will be nonempty and // will contain the corresponding version string. You // can build applications that use this particular // version of Panda by requesting it in the pdef file, // using "panda3d", this version string, and the // download host provided by get_package_host_url(). // // If this string is empty, then the currently-executing // Panda was built independently, and is not part of a // distributable package. // // This string is set explicitly at compilation time. // Normally, it should be set to a nonempty string only // when building a Panda3D package for distribution. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_package_version_string() { #ifdef NDEBUG return PANDA_PACKAGE_VERSION_STR; #else return get_global_ptr()->_package_version_string; #endif } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_package_host_url // Access: Published, Static // Description: Returns the URL of the download server that provides // the Panda3D distributable package currently running. // This can be used, along with the // get_package_version_string(), to uniquely identify // the running version of Panda among distributable // Panda versions. // // See get_package_version_string() for more information. // // This string is set explicitly at compilation time. // Normally, it should be set to a nonempty string only // when building a Panda3D package for distribution. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_package_host_url() { #ifdef NDEBUG return PANDA_PACKAGE_HOST_URL; #else return get_global_ptr()->_package_host_url; #endif } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_p3d_coreapi_version_string // Access: Published, Static // Description: Returns the current version of Panda's Core API, // expressed as a string of dot-delimited integers. // There are usually four integers in this version, but // this is not guaranteed. // // The Core API is used during the runtime (plugin) // environment only. This may be the empty string if // the current version of Panda is not built to provide // a particular Core API, which will be the normal case // in a development SDK. However, you should not use // this method to determine whether you are running in a // runtime environment or not. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_p3d_coreapi_version_string() { #ifndef P3D_COREAPI_VERSION_STR return ""; #else return P3D_COREAPI_VERSION_STR; #endif } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_major_version // Access: Published, Static // Description: Returns the major version number of the current // version of Panda. This is the first number of the // dotted triple returned by get_version_string(). It // changes very rarely. //////////////////////////////////////////////////////////////////// int PandaSystem:: get_major_version() { return PANDA_MAJOR_VERSION; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_minor_version // Access: Published, Static // Description: Returns the minor version number of the current // version of Panda. This is the second number of the // dotted triple returned by get_version_string(). It // changes with each release that introduces new // features. //////////////////////////////////////////////////////////////////// int PandaSystem:: get_minor_version() { return PANDA_MINOR_VERSION; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_sequence_version // Access: Published, Static // Description: Returns the sequence version number of the current // version of Panda. This is the third number of the // dotted triple returned by get_version_string(). It // changes with bugfix updates and very minor feature // updates. //////////////////////////////////////////////////////////////////// int PandaSystem:: get_sequence_version() { return PANDA_SEQUENCE_VERSION; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::is_official_version // Access: Published, Static // Description: Returns true if current version of Panda claims to be // an "official" version, that is, one that was compiled // by an official distributor of Panda using a specific // version of the panda source tree. If this is true, // there will not be a "c" at the end of the version // string returned by get_version_string(). // // Note that we must take the distributor's word for it // here. //////////////////////////////////////////////////////////////////// bool PandaSystem:: is_official_version() { #ifdef PANDA_OFFICIAL_VERSION return true; #else return false; #endif } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_distributor // Access: Published, Static // Description: Returns the string defined by the distributor of this // version of Panda, or "homebuilt" if this version was // built directly from the sources by the end-user. // This is a completely arbitrary string. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_distributor() { return PANDA_DISTRIBUTOR; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_compiler // Access: Published, Static // Description: Returns a string representing the compiler that was // used to generate this version of Panda, if it is // available, or "unknown" if it is not. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_compiler() { #if defined(_MSC_VER) // MSVC defines this macro. It's an integer; we need to format it. ostringstream strm; strm << "MSC v." << _MSC_VER; // We also get this suite of macros that tells us what the build // platform is. #if defined(_M_IX86) #ifdef MS_WIN64 strm << " 64 bit (Intel)"; #else // MS_WIN64 strm << " 32 bit (Intel)"; #endif // MS_WIN64 #elif defined(_M_IA64) strm << " 64 bit (Itanium)"; #elif defined(_M_AMD64) strm << " 64 bit (AMD64)"; #endif return strm.str(); #elif defined(__GNUC__) // GCC defines this simple macro. return "GCC " __VERSION__; #else // For other compilers, you're on your own. return "unknown"; #endif } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_build_date // Access: Published, Static // Description: Returns a string representing the date and time at // which this version of Panda (or at least dtool) was // compiled, if available. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_build_date() { return __DATE__ " " __TIME__; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_platform // Access: Published, Static // Description: Returns a string representing the runtime platform // that we are currently running on. This will be // something like "win32" or "osx.i386" or // "linux.amd64". //////////////////////////////////////////////////////////////////// string PandaSystem:: get_platform() { return DTOOL_PLATFORM; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::has_system // Access: Published // Description: Returns true if the current version of Panda claims // to have the indicated subsystem installed, false // otherwise. The set of available subsystems is // implementation defined. //////////////////////////////////////////////////////////////////// bool PandaSystem:: has_system(const string &system) const { Systems::const_iterator si; si = _systems.find(system); return (si != _systems.end()); } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_num_systems // Access: Published // Description: Returns the number of Panda subsystems that have // registered themselves. This can be used with // get_system() to iterate through the entire list of // available Panda subsystems. //////////////////////////////////////////////////////////////////// int PandaSystem:: get_num_systems() const { return _systems.size(); } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_system // Access: Published // Description: Returns the nth Panda subsystem that has registered // itself. This list will be sorted in alphabetical // order. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_system(int n) const { if (n < 0 || n >= (int)_systems.size()) { return string(); } if (_system_names_dirty) { ((PandaSystem *)this)->reset_system_names(); } return _system_names[n]; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_system_tag // Access: Published // Description: Returns the value associated with the indicated tag // for the given system. This provides a standard way // to query each subsystem's advertised capabilities. // The set of tags and values are per-system and // implementation-defined. // // The return value is the empty string if the indicated // system is undefined or if does not define the // indicated tag. //////////////////////////////////////////////////////////////////// string PandaSystem:: get_system_tag(const string &system, const string &tag) const { Systems::const_iterator si; si = _systems.find(system); if (si != _systems.end()) { const SystemTags &tags = (*si).second; SystemTags::const_iterator ti; ti = tags.find(tag); if (ti != tags.end()) { return (*ti).second; } } return string(); } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::add_system // Access: Published // Description: Intended for use by each subsystem to register itself // at startup. //////////////////////////////////////////////////////////////////// void PandaSystem:: add_system(const string &system) { bool inserted = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))).second; if (inserted) { _system_names_dirty = true; } } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::set_system_tag // Access: Published // Description: Intended for use by each subsystem to register its // set of capabilities at startup. //////////////////////////////////////////////////////////////////// void PandaSystem:: set_system_tag(const string &system, const string &tag, const string &value) { pair result; result = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))); if (result.second) { _system_names_dirty = true; } SystemTags &tags = (*result.first).second; tags[tag] = value; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::heap_trim // Access: Published // Description: Attempts to release memory back to the system, if // possible. The pad argument is the minimum amount of // unused memory to keep in the heap (against future // allocations). Any memory above that may be released // to the system, reducing the memory size of this // process. There is no guarantee that any memory may // be released. // // Returns true if any memory was actually released, // false otherwise. //////////////////////////////////////////////////////////////////// bool PandaSystem:: heap_trim(size_t pad) { // This actually just vectors into _memory_hook, which isn't // published. This method only exists on PandaSystem for the // convenience of Python programmers. return memory_hook->heap_trim(pad); } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::output // Access: Published // Description: //////////////////////////////////////////////////////////////////// void PandaSystem:: output(ostream &out) const { out << "Panda version " << get_version_string(); } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::write // Access: Published // Description: //////////////////////////////////////////////////////////////////// void PandaSystem:: write(ostream &out) const { out << *this << "\n" << "compiled on " << get_build_date() << " by " << get_distributor() << "\n" << "with compiler " << PandaSystem::get_compiler() << "\n\n"; out << "Optional systems:\n"; for (Systems::const_iterator si = _systems.begin(); si != _systems.end(); ++si) { out << " " << (*si).first << "\n"; const SystemTags &tags = (*si).second; SystemTags::const_iterator ti; for (ti = tags.begin(); ti != tags.end(); ++ti) { out << " " << (*ti).first << " " << (*ti).second << "\n"; } } } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::get_global_ptr // Access: Published, Static // Description: Returns the global PandaSystem object. //////////////////////////////////////////////////////////////////// PandaSystem *PandaSystem:: get_global_ptr() { if (_global_ptr == (PandaSystem *)NULL) { _global_ptr = new PandaSystem; } return _global_ptr; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::reset_system_names // Access: Private // Description: Refills the _system_names vector, which is used for // get_system_name(), from the current set of available // system names. //////////////////////////////////////////////////////////////////// void PandaSystem:: reset_system_names() { _system_names.clear(); _system_names.reserve(_systems.size()); Systems::const_iterator si; for (si = _systems.begin(); si != _systems.end(); ++si) { _system_names.push_back((*si).first); } _system_names_dirty = false; } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::set_package_version_string // Access: Private // Description: Loads the value returned by // get_package_version_string(). This is intended to be // called by ConfigPageManager to preload the value from // the panda-package-version config variable, for // developer's convenience. This has no effect if the // PANDA_PACKAGE_VERSION_STR configure variable is // defined at compilation time. This also has no effect // in NDEBUG mode. //////////////////////////////////////////////////////////////////// void PandaSystem:: set_package_version_string(const string &package_version_string) { _package_version_string = PANDA_PACKAGE_VERSION_STR; if (_package_version_string.empty()) { _package_version_string = package_version_string; } } //////////////////////////////////////////////////////////////////// // Function: PandaSystem::set_package_host_url // Access: Private // Description: Loads the value returned by // get_package_host_url(). This is intended to be // called by ConfigPageManager to preload the value from // the panda-package-host-url config variable, for // developer's convenience. This has no effect if the // PANDA_PACKAGE_HOST_URL configure variable is defined // at compilation time. This also has no effect in // NDEBUG mode. //////////////////////////////////////////////////////////////////// void PandaSystem:: set_package_host_url(const string &package_host_url) { _package_host_url = PANDA_PACKAGE_HOST_URL; if (_package_host_url.empty()) { _package_host_url = package_host_url; } }