pandaSystem.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. // Filename: pandaSystem.cxx
  2. // Created by: drose (26Jan05)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "pandaSystem.h"
  15. #include "pandaVersion.h"
  16. #include "dtool_platform.h"
  17. PandaSystem *PandaSystem::_global_ptr = NULL;
  18. TypeHandle PandaSystem::_type_handle;
  19. ////////////////////////////////////////////////////////////////////
  20. // Function: PandaSystem::Constructor
  21. // Access: Protected
  22. // Description: Don't try to construct a PandaSystem object; there is
  23. // only one of these, and it constructs itself. Use
  24. // get_global_ptr() to get a pointer to the one
  25. // PandaSystem.
  26. ////////////////////////////////////////////////////////////////////
  27. PandaSystem::
  28. PandaSystem() :
  29. _systems(get_class_type())
  30. {
  31. _system_names_dirty = false;
  32. // These are settable via Config.prc, but only in development
  33. // (!NDEBUG) mode, and only if they are not already defined.
  34. _package_version_string = PANDA_PACKAGE_VERSION_STR;
  35. _package_host_url = PANDA_PACKAGE_HOST_URL;
  36. }
  37. ////////////////////////////////////////////////////////////////////
  38. // Function: PandaSystem::Destructor
  39. // Access: Protected
  40. // Description: Don't try to destruct the global PandaSystem object.
  41. ////////////////////////////////////////////////////////////////////
  42. PandaSystem::
  43. ~PandaSystem() {
  44. }
  45. ////////////////////////////////////////////////////////////////////
  46. // Function: PandaSystem::get_version_string
  47. // Access: Published, Static
  48. // Description: Returns the current version of Panda, expressed as a
  49. // string, e.g. "1.0.0". The string will end in the
  50. // letter "c" if this build does not represent an
  51. // official version.
  52. ////////////////////////////////////////////////////////////////////
  53. string PandaSystem::
  54. get_version_string() {
  55. return PANDA_VERSION_STR;
  56. }
  57. ////////////////////////////////////////////////////////////////////
  58. // Function: PandaSystem::get_package_version_string
  59. // Access: Published, Static
  60. // Description: Returns the version of the Panda3D distributable
  61. // package that provides this build of Panda.
  62. //
  63. // When the currently-executing version of Panda was
  64. // loaded from a distributable package, such as via the
  65. // browser plugin, then this string will be nonempty and
  66. // will contain the corresponding version string. You
  67. // can build applications that use this particular
  68. // version of Panda by requesting it in the pdef file,
  69. // using "panda3d", this version string, and the
  70. // download host provided by get_package_host_url().
  71. //
  72. // If this string is empty, then the currently-executing
  73. // Panda was built independently, and is not part of a
  74. // distributable package.
  75. //
  76. // This string is set explicitly at compilation time.
  77. // Normally, it should be set to a nonempty string only
  78. // when building a Panda3D package for distribution.
  79. ////////////////////////////////////////////////////////////////////
  80. string PandaSystem::
  81. get_package_version_string() {
  82. #ifdef NDEBUG
  83. return PANDA_PACKAGE_VERSION_STR;
  84. #else
  85. return get_global_ptr()->_package_version_string;
  86. #endif
  87. }
  88. ////////////////////////////////////////////////////////////////////
  89. // Function: PandaSystem::get_package_host_url
  90. // Access: Published, Static
  91. // Description: Returns the URL of the download server that provides
  92. // the Panda3D distributable package currently running.
  93. // This can be used, along with the
  94. // get_package_version_string(), to uniquely identify
  95. // the running version of Panda among distributable
  96. // Panda versions.
  97. //
  98. // See get_package_version_string() for more information.
  99. //
  100. // This string is set explicitly at compilation time.
  101. // Normally, it should be set to a nonempty string only
  102. // when building a Panda3D package for distribution.
  103. ////////////////////////////////////////////////////////////////////
  104. string PandaSystem::
  105. get_package_host_url() {
  106. #ifdef NDEBUG
  107. return PANDA_PACKAGE_HOST_URL;
  108. #else
  109. return get_global_ptr()->_package_host_url;
  110. #endif
  111. }
  112. ////////////////////////////////////////////////////////////////////
  113. // Function: PandaSystem::get_p3d_coreapi_version_string
  114. // Access: Published, Static
  115. // Description: Returns the current version of Panda's Core API,
  116. // expressed as a string of dot-delimited integers.
  117. // There are usually four integers in this version, but
  118. // this is not guaranteed.
  119. //
  120. // The Core API is used during the runtime (plugin)
  121. // environment only. This may be the empty string if
  122. // the current version of Panda is not built to provide
  123. // a particular Core API, which will be the normal case
  124. // in a development SDK. However, you should not use
  125. // this method to determine whether you are running in a
  126. // runtime environment or not.
  127. ////////////////////////////////////////////////////////////////////
  128. string PandaSystem::
  129. get_p3d_coreapi_version_string() {
  130. #ifndef P3D_COREAPI_VERSION_STR
  131. return "";
  132. #else
  133. return P3D_COREAPI_VERSION_STR;
  134. #endif
  135. }
  136. ////////////////////////////////////////////////////////////////////
  137. // Function: PandaSystem::get_major_version
  138. // Access: Published, Static
  139. // Description: Returns the major version number of the current
  140. // version of Panda. This is the first number of the
  141. // dotted triple returned by get_version_string(). It
  142. // changes very rarely.
  143. ////////////////////////////////////////////////////////////////////
  144. int PandaSystem::
  145. get_major_version() {
  146. return PANDA_MAJOR_VERSION;
  147. }
  148. ////////////////////////////////////////////////////////////////////
  149. // Function: PandaSystem::get_minor_version
  150. // Access: Published, Static
  151. // Description: Returns the minor version number of the current
  152. // version of Panda. This is the second number of the
  153. // dotted triple returned by get_version_string(). It
  154. // changes with each release that introduces new
  155. // features.
  156. ////////////////////////////////////////////////////////////////////
  157. int PandaSystem::
  158. get_minor_version() {
  159. return PANDA_MINOR_VERSION;
  160. }
  161. ////////////////////////////////////////////////////////////////////
  162. // Function: PandaSystem::get_sequence_version
  163. // Access: Published, Static
  164. // Description: Returns the sequence version number of the current
  165. // version of Panda. This is the third number of the
  166. // dotted triple returned by get_version_string(). It
  167. // changes with bugfix updates and very minor feature
  168. // updates.
  169. ////////////////////////////////////////////////////////////////////
  170. int PandaSystem::
  171. get_sequence_version() {
  172. return PANDA_SEQUENCE_VERSION;
  173. }
  174. ////////////////////////////////////////////////////////////////////
  175. // Function: PandaSystem::is_official_version
  176. // Access: Published, Static
  177. // Description: Returns true if current version of Panda claims to be
  178. // an "official" version, that is, one that was compiled
  179. // by an official distributor of Panda using a specific
  180. // version of the panda source tree. If this is true,
  181. // there will not be a "c" at the end of the version
  182. // string returned by get_version_string().
  183. //
  184. // Note that we must take the distributor's word for it
  185. // here.
  186. ////////////////////////////////////////////////////////////////////
  187. bool PandaSystem::
  188. is_official_version() {
  189. #ifdef PANDA_OFFICIAL_VERSION
  190. return true;
  191. #else
  192. return false;
  193. #endif
  194. }
  195. ////////////////////////////////////////////////////////////////////
  196. // Function: PandaSystem::get_distributor
  197. // Access: Published, Static
  198. // Description: Returns the string defined by the distributor of this
  199. // version of Panda, or "homebuilt" if this version was
  200. // built directly from the sources by the end-user.
  201. // This is a completely arbitrary string.
  202. ////////////////////////////////////////////////////////////////////
  203. string PandaSystem::
  204. get_distributor() {
  205. return PANDA_DISTRIBUTOR;
  206. }
  207. ////////////////////////////////////////////////////////////////////
  208. // Function: PandaSystem::get_compiler
  209. // Access: Published, Static
  210. // Description: Returns a string representing the compiler that was
  211. // used to generate this version of Panda, if it is
  212. // available, or "unknown" if it is not.
  213. ////////////////////////////////////////////////////////////////////
  214. string PandaSystem::
  215. get_compiler() {
  216. #if defined(_MSC_VER)
  217. // MSVC defines this macro. It's an integer; we need to format it.
  218. ostringstream strm;
  219. strm << "MSC v." << _MSC_VER;
  220. // We also get this suite of macros that tells us what the build
  221. // platform is.
  222. #if defined(_M_IX86)
  223. #ifdef MS_WIN64
  224. strm << " 64 bit (Intel)";
  225. #else // MS_WIN64
  226. strm << " 32 bit (Intel)";
  227. #endif // MS_WIN64
  228. #elif defined(_M_IA64)
  229. strm << " 64 bit (Itanium)";
  230. #elif defined(_M_AMD64)
  231. strm << " 64 bit (AMD64)";
  232. #endif
  233. return strm.str();
  234. #elif defined(__GNUC__)
  235. // GCC defines this simple macro.
  236. return "GCC " __VERSION__;
  237. #else
  238. // For other compilers, you're on your own.
  239. return "unknown";
  240. #endif
  241. }
  242. ////////////////////////////////////////////////////////////////////
  243. // Function: PandaSystem::get_build_date
  244. // Access: Published, Static
  245. // Description: Returns a string representing the date and time at
  246. // which this version of Panda (or at least dtool) was
  247. // compiled, if available.
  248. ////////////////////////////////////////////////////////////////////
  249. string PandaSystem::
  250. get_build_date() {
  251. return __DATE__ " " __TIME__;
  252. }
  253. ////////////////////////////////////////////////////////////////////
  254. // Function: PandaSystem::get_platform
  255. // Access: Published, Static
  256. // Description: Returns a string representing the runtime platform
  257. // that we are currently running on. This will be
  258. // something like "win32" or "osx.i386" or
  259. // "linux.amd64".
  260. ////////////////////////////////////////////////////////////////////
  261. string PandaSystem::
  262. get_platform() {
  263. return DTOOL_PLATFORM;
  264. }
  265. ////////////////////////////////////////////////////////////////////
  266. // Function: PandaSystem::has_system
  267. // Access: Published
  268. // Description: Returns true if the current version of Panda claims
  269. // to have the indicated subsystem installed, false
  270. // otherwise. The set of available subsystems is
  271. // implementation defined.
  272. ////////////////////////////////////////////////////////////////////
  273. bool PandaSystem::
  274. has_system(const string &system) const {
  275. Systems::const_iterator si;
  276. si = _systems.find(system);
  277. return (si != _systems.end());
  278. }
  279. ////////////////////////////////////////////////////////////////////
  280. // Function: PandaSystem::get_num_systems
  281. // Access: Published
  282. // Description: Returns the number of Panda subsystems that have
  283. // registered themselves. This can be used with
  284. // get_system() to iterate through the entire list of
  285. // available Panda subsystems.
  286. ////////////////////////////////////////////////////////////////////
  287. int PandaSystem::
  288. get_num_systems() const {
  289. return _systems.size();
  290. }
  291. ////////////////////////////////////////////////////////////////////
  292. // Function: PandaSystem::get_system
  293. // Access: Published
  294. // Description: Returns the nth Panda subsystem that has registered
  295. // itself. This list will be sorted in alphabetical
  296. // order.
  297. ////////////////////////////////////////////////////////////////////
  298. string PandaSystem::
  299. get_system(int n) const {
  300. if (n < 0 || n >= (int)_systems.size()) {
  301. return string();
  302. }
  303. if (_system_names_dirty) {
  304. ((PandaSystem *)this)->reset_system_names();
  305. }
  306. return _system_names[n];
  307. }
  308. ////////////////////////////////////////////////////////////////////
  309. // Function: PandaSystem::get_system_tag
  310. // Access: Published
  311. // Description: Returns the value associated with the indicated tag
  312. // for the given system. This provides a standard way
  313. // to query each subsystem's advertised capabilities.
  314. // The set of tags and values are per-system and
  315. // implementation-defined.
  316. //
  317. // The return value is the empty string if the indicated
  318. // system is undefined or if does not define the
  319. // indicated tag.
  320. ////////////////////////////////////////////////////////////////////
  321. string PandaSystem::
  322. get_system_tag(const string &system, const string &tag) const {
  323. Systems::const_iterator si;
  324. si = _systems.find(system);
  325. if (si != _systems.end()) {
  326. const SystemTags &tags = (*si).second;
  327. SystemTags::const_iterator ti;
  328. ti = tags.find(tag);
  329. if (ti != tags.end()) {
  330. return (*ti).second;
  331. }
  332. }
  333. return string();
  334. }
  335. ////////////////////////////////////////////////////////////////////
  336. // Function: PandaSystem::add_system
  337. // Access: Published
  338. // Description: Intended for use by each subsystem to register itself
  339. // at startup.
  340. ////////////////////////////////////////////////////////////////////
  341. void PandaSystem::
  342. add_system(const string &system) {
  343. bool inserted = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))).second;
  344. if (inserted) {
  345. _system_names_dirty = true;
  346. }
  347. }
  348. ////////////////////////////////////////////////////////////////////
  349. // Function: PandaSystem::set_system_tag
  350. // Access: Published
  351. // Description: Intended for use by each subsystem to register its
  352. // set of capabilities at startup.
  353. ////////////////////////////////////////////////////////////////////
  354. void PandaSystem::
  355. set_system_tag(const string &system, const string &tag,
  356. const string &value) {
  357. pair<Systems::iterator, bool> result;
  358. result = _systems.insert(Systems::value_type(system, SystemTags(get_class_type())));
  359. if (result.second) {
  360. _system_names_dirty = true;
  361. }
  362. SystemTags &tags = (*result.first).second;
  363. tags[tag] = value;
  364. }
  365. ////////////////////////////////////////////////////////////////////
  366. // Function: PandaSystem::heap_trim
  367. // Access: Published
  368. // Description: Attempts to release memory back to the system, if
  369. // possible. The pad argument is the minimum amount of
  370. // unused memory to keep in the heap (against future
  371. // allocations). Any memory above that may be released
  372. // to the system, reducing the memory size of this
  373. // process. There is no guarantee that any memory may
  374. // be released.
  375. //
  376. // Returns true if any memory was actually released,
  377. // false otherwise.
  378. ////////////////////////////////////////////////////////////////////
  379. bool PandaSystem::
  380. heap_trim(size_t pad) {
  381. // This actually just vectors into _memory_hook, which isn't
  382. // published. This method only exists on PandaSystem for the
  383. // convenience of Python programmers.
  384. return memory_hook->heap_trim(pad);
  385. }
  386. ////////////////////////////////////////////////////////////////////
  387. // Function: PandaSystem::output
  388. // Access: Published
  389. // Description:
  390. ////////////////////////////////////////////////////////////////////
  391. void PandaSystem::
  392. output(ostream &out) const {
  393. out << "Panda version " << get_version_string();
  394. }
  395. ////////////////////////////////////////////////////////////////////
  396. // Function: PandaSystem::write
  397. // Access: Published
  398. // Description:
  399. ////////////////////////////////////////////////////////////////////
  400. void PandaSystem::
  401. write(ostream &out) const {
  402. out << *this << "\n"
  403. << "compiled on " << get_build_date() << " by "
  404. << get_distributor() << "\n"
  405. << "with compiler " << PandaSystem::get_compiler() << "\n\n";
  406. out << "Optional systems:\n";
  407. for (Systems::const_iterator si = _systems.begin();
  408. si != _systems.end();
  409. ++si) {
  410. out << " " << (*si).first << "\n";
  411. const SystemTags &tags = (*si).second;
  412. SystemTags::const_iterator ti;
  413. for (ti = tags.begin(); ti != tags.end(); ++ti) {
  414. out << " " << (*ti).first << " " << (*ti).second << "\n";
  415. }
  416. }
  417. }
  418. ////////////////////////////////////////////////////////////////////
  419. // Function: PandaSystem::get_global_ptr
  420. // Access: Published, Static
  421. // Description: Returns the global PandaSystem object.
  422. ////////////////////////////////////////////////////////////////////
  423. PandaSystem *PandaSystem::
  424. get_global_ptr() {
  425. if (_global_ptr == (PandaSystem *)NULL) {
  426. _global_ptr = new PandaSystem;
  427. }
  428. return _global_ptr;
  429. }
  430. ////////////////////////////////////////////////////////////////////
  431. // Function: PandaSystem::reset_system_names
  432. // Access: Private
  433. // Description: Refills the _system_names vector, which is used for
  434. // get_system_name(), from the current set of available
  435. // system names.
  436. ////////////////////////////////////////////////////////////////////
  437. void PandaSystem::
  438. reset_system_names() {
  439. _system_names.clear();
  440. _system_names.reserve(_systems.size());
  441. Systems::const_iterator si;
  442. for (si = _systems.begin(); si != _systems.end(); ++si) {
  443. _system_names.push_back((*si).first);
  444. }
  445. _system_names_dirty = false;
  446. }
  447. ////////////////////////////////////////////////////////////////////
  448. // Function: PandaSystem::set_package_version_string
  449. // Access: Private
  450. // Description: Loads the value returned by
  451. // get_package_version_string(). This is intended to be
  452. // called by ConfigPageManager to preload the value from
  453. // the panda-package-version config variable, for
  454. // developer's convenience. This has no effect if the
  455. // PANDA_PACKAGE_VERSION_STR configure variable is
  456. // defined at compilation time. This also has no effect
  457. // in NDEBUG mode.
  458. ////////////////////////////////////////////////////////////////////
  459. void PandaSystem::
  460. set_package_version_string(const string &package_version_string) {
  461. _package_version_string = PANDA_PACKAGE_VERSION_STR;
  462. if (_package_version_string.empty()) {
  463. _package_version_string = package_version_string;
  464. }
  465. }
  466. ////////////////////////////////////////////////////////////////////
  467. // Function: PandaSystem::set_package_host_url
  468. // Access: Private
  469. // Description: Loads the value returned by
  470. // get_package_host_url(). This is intended to be
  471. // called by ConfigPageManager to preload the value from
  472. // the panda-package-host-url config variable, for
  473. // developer's convenience. This has no effect if the
  474. // PANDA_PACKAGE_HOST_URL configure variable is defined
  475. // at compilation time. This also has no effect in
  476. // NDEBUG mode.
  477. ////////////////////////////////////////////////////////////////////
  478. void PandaSystem::
  479. set_package_host_url(const string &package_host_url) {
  480. _package_host_url = PANDA_PACKAGE_HOST_URL;
  481. if (_package_host_url.empty()) {
  482. _package_host_url = package_host_url;
  483. }
  484. }