瀏覽代碼

little refinements

David Rose 16 年之前
父節點
當前提交
63160f0c1f

+ 10 - 0
direct/src/plugin/Sources.pp

@@ -17,6 +17,7 @@
     p3d_plugin_common.h \
     p3dDownload.h p3dDownload.I \
     p3dFileDownload.h p3dFileDownload.I \
+    p3dFileParams.h p3dFileParams.I \
     p3dInstance.h p3dInstance.I \
     p3dInstanceManager.h p3dInstanceManager.I \
     p3dMultifileReader.h p3dMultifileReader.I \
@@ -30,6 +31,7 @@
     p3d_plugin.cxx \
     p3dDownload.cxx \
     p3dFileDownload.cxx \
+    p3dFileParams.cxx \
     p3dInstance.cxx \
     p3dInstanceManager.cxx \
     p3dMultifileReader.cxx \
@@ -67,3 +69,11 @@
     p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I
 
 #end bin_target
+
+#begin static_lib_target
+  #define TARGET plugin_common
+
+  #define SOURCES \
+     load_plugin.cxx load_plugin.h
+
+#end static_lib_target

+ 80 - 30
direct/src/plugin/load_plugin_src.cxx → direct/src/plugin/load_plugin.cxx

@@ -1,4 +1,4 @@
-// Filename: load_plugin_src.cxx
+// Filename: load_plugin.cxx
 // Created by:  drose (19Jun09)
 //
 ////////////////////////////////////////////////////////////////////
@@ -12,11 +12,7 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-
-// This code is used in the plugin_standalone directory, and also in
-// the plugin_npapi directory.  To facilitate that code re-use with
-// minimal structural overhead, it is designed to be simply #included
-// into the different source files.
+#include "load_plugin.h"
 
 #ifndef _WIN32
 #include <dlfcn.h>
@@ -46,42 +42,46 @@ P3D_request_finish_func *P3D_request_finish;
 P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream;
 
 #ifdef _WIN32
-static HMODULE module;
+static HMODULE module = NULL;
+#else
+static void *module = NULL;
 #endif
 
+static bool plugin_loaded = false;
 
 
-static void
-unload_plugin() {
-#ifdef _WIN32
-  FreeLibrary(module);
-  module = NULL;
-#else 
-  // TODO: unload_dso
-#endif
-  
-  P3D_initialize = NULL;
-  P3D_free_string = NULL;
-  P3D_create_instance = NULL;
-  P3D_instance_finish = NULL;
-  P3D_instance_has_property = NULL;
-  P3D_instance_get_property = NULL;
-  P3D_instance_set_property = NULL;
-  P3D_instance_get_request = NULL;
-  P3D_check_request = NULL;
-  P3D_request_finish = NULL;
-  P3D_instance_feed_url_stream = NULL;
+////////////////////////////////////////////////////////////////////
+//     Function: get_plugin_basename
+//  Description: Returns the default plugin filename, without any
+//               directory path (but including the extension
+//               appropriate to this platform).
+////////////////////////////////////////////////////////////////////
+string
+get_plugin_basename() {
+  return default_plugin_filename + dll_ext;
 }
 
-static bool
+////////////////////////////////////////////////////////////////////
+//     Function: load_plugin
+//  Description: Loads the plugin and assigns all of the function
+//               pointers.  Returns true on success, false on failure.
+//               If the filename is empty, it is searched along the
+//               path.
+////////////////////////////////////////////////////////////////////
+bool
 load_plugin(const string &p3d_plugin_filename) {
   string filename = p3d_plugin_filename;
   if (filename.empty()) {
     // Look for the plugin along the path.
-    filename = default_plugin_filename + dll_ext;
+    filename = get_plugin_basename();
+  }
+
+  if (plugin_loaded) {
+    return true;
   }
 
 #ifdef _WIN32
+  assert(module == NULL);
   module = LoadLibrary(filename.c_str());
   if (module == NULL) {
     // Couldn't load the DLL.
@@ -104,7 +104,8 @@ load_plugin(const string &p3d_plugin_filename) {
 
 #else  // _WIN32
   // Posix case.
-  void *module = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL);
+  assert(module == NULL);
+  module = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL);
   if (module == NULL) {
     // Couldn't load the .so.
     return false;
@@ -143,6 +144,8 @@ load_plugin(const string &p3d_plugin_filename) {
   }
 
   // Successfully loaded.
+  plugin_loaded = true;
+
 #ifdef _WIN32
   string logfilename = "c:/cygwin/home/drose/t0.log";
 #else
@@ -157,3 +160,50 @@ load_plugin(const string &p3d_plugin_filename) {
 
   return true;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: unload_plugin
+//  Description: Removes the plugin from memory space and clears all
+//               of the pointers.
+////////////////////////////////////////////////////////////////////
+void
+unload_plugin() {
+  if (!plugin_loaded) {
+    return;
+  }
+
+#ifdef _WIN32
+  assert(module != NULL);
+  FreeLibrary(module);
+  module = NULL;
+#else 
+  assert(module != NULL);
+  dlclose(module);
+  module = NULL;
+#endif
+  
+  P3D_initialize = NULL;
+  P3D_free_string = NULL;
+  P3D_create_instance = NULL;
+  P3D_instance_finish = NULL;
+  P3D_instance_has_property = NULL;
+  P3D_instance_get_property = NULL;
+  P3D_instance_set_property = NULL;
+  P3D_instance_get_request = NULL;
+  P3D_check_request = NULL;
+  P3D_request_finish = NULL;
+  P3D_instance_feed_url_stream = NULL;
+
+  plugin_loaded = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: is_plugin_loaded
+//  Description: Returns true if the plugin has been loaded
+//               successfully by a previous call to load_plugin(),
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool
+is_plugin_loaded() {
+  return plugin_loaded;
+}

+ 14 - 5
direct/src/plugin/load_plugin_src.h → direct/src/plugin/load_plugin.h

@@ -1,4 +1,4 @@
-// Filename: load_plugin_src.h
+// Filename: load_plugin.h
 // Created by:  drose (19Jun09)
 //
 ////////////////////////////////////////////////////////////////////
@@ -12,11 +12,13 @@
 //
 ////////////////////////////////////////////////////////////////////
 
+#ifndef LOAD_PLUGIN_H
+#define LOAD_PLUGIN_H
 
-// This code is used in the plugin_standalone directory, and also in
-// the plugin_npapi directory.  To facilitate that code re-use with
-// minimal structural overhead, it is designed to be simply #included
-// into the different source files.
+#include "p3d_plugin.h"
+
+#include <string>
+using namespace std;
 
 extern P3D_initialize_func *P3D_initialize;
 extern P3D_free_string_func *P3D_free_string;
@@ -30,3 +32,10 @@ extern P3D_instance_get_request_func *P3D_instance_get_request;
 extern P3D_check_request_func *P3D_check_request;
 extern P3D_request_finish_func *P3D_request_finish;
 extern P3D_instance_feed_url_stream_func *P3D_instance_feed_url_stream;
+
+string get_plugin_basename();
+bool load_plugin(const string &p3d_plugin_filename);
+void unload_plugin();
+bool is_plugin_loaded();
+
+#endif

+ 0 - 11
direct/src/plugin/p3dCInstance.I

@@ -13,17 +13,6 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: P3DCInstance::get_p3d_filename
-//       Access: Public
-//  Description: Returns the p3d filename that was passed to the
-//               constructor.
-////////////////////////////////////////////////////////////////////
-inline const string &P3DCInstance::
-get_p3d_filename() const {
-  return _p3d_filename;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DCInstance::get_instance_id
 //       Access: Public

+ 0 - 43
direct/src/plugin/p3dCInstance.cxx

@@ -25,28 +25,6 @@ P3DCInstance(TiXmlElement *xinstance) :
   _func(NULL)
 {
   xinstance->Attribute("id", &_instance_id);
-
-  const char *p3d_filename = xinstance->Attribute("p3d_filename");
-  if (p3d_filename != NULL) {
-    _p3d_filename = p3d_filename;
-  }
-
-  TiXmlElement *xtoken = xinstance->FirstChildElement("token");
-  while (xtoken != NULL) {
-    Token token;
-    const char *keyword = xtoken->Attribute("keyword");
-    if (keyword != NULL) {
-      token._keyword = keyword;
-    }
-
-    const char *value = xtoken->Attribute("value");
-    if (value != NULL) {
-      token._value = value;
-    }
-
-    _tokens.push_back(token);
-    xtoken = xtoken->NextSiblingElement("token");
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -57,24 +35,3 @@ P3DCInstance(TiXmlElement *xinstance) :
 P3DCInstance::
 ~P3DCInstance() {
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: P3DCInstance::get_py_tokens
-//       Access: Public
-//  Description: Returns a Python list object that corresponds to the
-//               tokens passed to this instance, expressed as a list
-//               of 2-tuples.  New instance.
-////////////////////////////////////////////////////////////////////
-PyObject *P3DCInstance::
-get_py_tokens() const {
-  PyObject *list = PyList_New(_tokens.size());
-
-  for (size_t i = 0; i < _tokens.size(); ++i) {
-    const Token &token = _tokens[i];
-    PyObject *tuple = Py_BuildValue("(ss)", token._keyword.c_str(), 
-                                    token._value.c_str());
-    PyList_SetItem(list, i, tuple);
-  }
-
-  return list;
-}

+ 0 - 13
direct/src/plugin/p3dCInstance.h

@@ -35,23 +35,10 @@ public:
   P3DCInstance(TiXmlElement *xinstance);
   ~P3DCInstance();
 
-  inline const string &get_p3d_filename() const;
   inline int get_instance_id() const;
 
-  PyObject *get_py_tokens() const;
-
 private:
-  class Token {
-  public:
-    string _keyword;
-    string _value;
-  };
-  typedef pvector<Token> Tokens;
-
   P3D_request_ready_func *_func;
-  string _p3d_filename;
-
-  Tokens _tokens;
 
   int _instance_id;
 

+ 25 - 0
direct/src/plugin/p3dFileParams.I

@@ -0,0 +1,25 @@
+// Filename: p3dFileParams.I
+// Created by:  drose (23Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: P3DFileParams::get_p3d_filename
+//       Access: Public
+//  Description: Returns the p3d filename that was passed to the
+//               constructor.
+////////////////////////////////////////////////////////////////////
+inline const string &P3DFileParams::
+get_p3d_filename() const {
+  return _p3d_filename;
+}

+ 102 - 0
direct/src/plugin/p3dFileParams.cxx

@@ -0,0 +1,102 @@
+// Filename: p3dFileParams.cxx
+// Created by:  drose (23Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "p3dFileParams.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::Default Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DFileParams::
+P3DFileParams() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DFileParams::
+P3DFileParams(const string &p3d_filename, 
+              const P3D_token tokens[], size_t num_tokens) :
+  _p3d_filename(p3d_filename)
+{
+  for (size_t i = 0; i < num_tokens; ++i) {
+    Token token;
+    if (tokens[i]._keyword != NULL) {
+      token._keyword = tokens[i]._keyword;
+    }
+    if (tokens[i]._value != NULL) {
+      token._value = tokens[i]._value;
+    }
+    _tokens.push_back(token);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::Copy Assignment
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void P3DFileParams::
+operator = (const P3DFileParams &other) {
+  _p3d_filename = other._p3d_filename;
+  _tokens = other._tokens;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::lookup_token
+//       Access: Public
+//  Description: Returns the value associated with the first
+//               appearance of the named token, or empty string if the
+//               token does not appear.
+////////////////////////////////////////////////////////////////////
+string P3DFileParams::
+lookup_token(const string &keyword) const {
+  Tokens::const_iterator ti;
+  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
+    if ((*ti)._keyword == keyword) {
+      return (*ti)._value;
+    }
+  }
+
+  return string();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::make_xml
+//       Access: Public
+//  Description: Returns a newly-allocated XML structure that
+//               corresponds to the file parameter data within this
+//               instance.
+////////////////////////////////////////////////////////////////////
+TiXmlElement *P3DFileParams::
+make_xml() {
+  TiXmlElement *xfparams = new TiXmlElement("fparams");
+
+  xfparams->SetAttribute("p3d_filename", _p3d_filename.c_str());
+
+  Tokens::const_iterator ti;
+  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
+    const Token &token = (*ti);
+    TiXmlElement *xtoken = new TiXmlElement("token");
+    xtoken->SetAttribute("keyword", token._keyword.c_str());
+    xtoken->SetAttribute("value", token._value.c_str());
+    xfparams->LinkEndChild(xtoken);
+  }
+
+  return xfparams;
+}

+ 55 - 0
direct/src/plugin/p3dFileParams.h

@@ -0,0 +1,55 @@
+// Filename: p3dFileParams.h
+// Created by:  drose (23Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 P3DFILEPARAMS_H
+#define P3DFILEPARAMS_H
+
+#include "p3d_plugin_common.h"
+
+#include <tinyxml.h>
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : P3DFileParams
+// Description : Encapsulates the file parameters: the p3d_filename,
+//               and extra tokens.
+////////////////////////////////////////////////////////////////////
+class P3DFileParams {
+public:
+  P3DFileParams();
+  P3DFileParams(const string &p3d_filename, 
+                const P3D_token tokens[], size_t num_tokens);
+
+  void operator = (const P3DFileParams &other);
+
+  inline const string &get_p3d_filename() const;
+  string lookup_token(const string &keyword) const;
+
+  TiXmlElement *make_xml();
+
+private:
+  class Token {
+  public:
+    string _keyword;
+    string _value;
+  };
+  typedef vector<Token> Tokens;
+
+  string _p3d_filename;
+  Tokens _tokens;
+};
+
+#include "p3dFileParams.I"
+
+#endif

+ 10 - 11
direct/src/plugin/p3dInstance.I

@@ -14,24 +14,23 @@
 
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DInstance::get_wparams
+//     Function: P3DInstance::get_fparams
 //       Access: Public
-//  Description: Returns the current window parameters.
+//  Description: Returns the current file parameters.
 ////////////////////////////////////////////////////////////////////
-inline const P3DWindowParams &P3DInstance::
-get_wparams() const {
-  return _wparams;
+inline const P3DFileParams &P3DInstance::
+get_fparams() const {
+  return _fparams;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DInstance::get_p3d_filename
+//     Function: P3DInstance::get_wparams
 //       Access: Public
-//  Description: Returns the p3d filename that was passed to the
-//               constructor.
+//  Description: Returns the current window parameters.
 ////////////////////////////////////////////////////////////////////
-inline const string &P3DInstance::
-get_p3d_filename() const {
-  return _p3d_filename;
+inline const P3DWindowParams &P3DInstance::
+get_wparams() const {
+  return _wparams;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 4 - 52
direct/src/plugin/p3dInstance.cxx

@@ -31,10 +31,8 @@ P3DInstance(P3D_request_ready_func *func,
             const string &p3d_filename, 
             const P3D_token tokens[], size_t num_tokens) :
   _func(func),
-  _p3d_filename(p3d_filename)
+  _fparams(p3d_filename, tokens, num_tokens)
 {
-  fill_tokens(tokens, num_tokens);
-
   _instance_id = _next_instance_id;
   ++_next_instance_id;
 
@@ -241,25 +239,6 @@ feed_url_stream(int unique_id,
   return download_ok;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: P3DInstance::lookup_token
-//       Access: Public
-//  Description: Returns the value associated with the first
-//               appearance of the named token, or empty string if the
-//               token does not appear.
-////////////////////////////////////////////////////////////////////
-string P3DInstance::
-lookup_token(const string &keyword) const {
-  Tokens::const_iterator ti;
-  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
-    if ((*ti)._keyword == keyword) {
-      return (*ti)._value;
-    }
-  }
-
-  return string();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::start_download
 //       Access: Public
@@ -321,36 +300,9 @@ TiXmlElement *P3DInstance::
 make_xml() {
   TiXmlElement *xinstance = new TiXmlElement("instance");
   xinstance->SetAttribute("id", _instance_id);
-  xinstance->SetAttribute("p3d_filename", _p3d_filename.c_str());
-
-  Tokens::const_iterator ti;
-  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
-    const Token &token = (*ti);
-    TiXmlElement *xtoken = new TiXmlElement("token");
-    xtoken->SetAttribute("keyword", token._keyword.c_str());
-    xtoken->SetAttribute("value", token._value.c_str());
-    xinstance->LinkEndChild(xtoken);
-  }
 
-  return xinstance;
-}
+  TiXmlElement *xfparams = _fparams.make_xml();
+  xinstance->LinkEndChild(xfparams);
 
-////////////////////////////////////////////////////////////////////
-//     Function: P3DInstance::fill_tokens
-//       Access: Private
-//  Description: Copies the C-style tokens array into the internal
-//               C++-style _tokens vector.
-////////////////////////////////////////////////////////////////////
-void P3DInstance::
-fill_tokens(const P3D_token tokens[], size_t num_tokens) {
-  for (size_t i = 0; i < num_tokens; ++i) {
-    Token token;
-    if (tokens[i]._keyword != NULL) {
-      token._keyword = tokens[i]._keyword;
-    }
-    if (tokens[i]._value != NULL) {
-      token._value = tokens[i]._value;
-    }
-    _tokens.push_back(token);
-  }
+  return xinstance;
 }

+ 4 - 15
direct/src/plugin/p3dInstance.h

@@ -17,9 +17,9 @@
 
 #include "p3d_plugin_common.h"
 #include "p3dFileDownload.h"
+#include "p3dFileParams.h"
 #include "p3dWindowParams.h"
 
-#include <vector>
 #include <deque>
 #include <map>
 #include <tinyxml.h>
@@ -39,6 +39,8 @@ public:
               const P3D_token tokens[], size_t num_tokens);
   ~P3DInstance();
 
+  inline const P3DFileParams &get_fparams() const;
+
   void set_wparams(const P3DWindowParams &wparams);
   inline const P3DWindowParams &get_wparams() const;
 
@@ -58,12 +60,9 @@ public:
                        const unsigned char *this_data, 
                        size_t this_data_size);
 
-  inline const string &get_p3d_filename() const;
-
   inline int get_instance_id() const;
   inline const string &get_session_key() const;
   inline const string &get_python_version() const;
-  string lookup_token(const string &keyword) const;
 
   void start_download(P3DDownload *download);
   void request_stop();
@@ -71,19 +70,9 @@ public:
   TiXmlElement *make_xml();
 
 private:
-  void fill_tokens(const P3D_token tokens[], size_t num_tokens);
-
-  class Token {
-  public:
-    string _keyword;
-    string _value;
-  };
-  typedef vector<Token> Tokens;
-
   P3D_request_ready_func *_func;
-  string _p3d_filename;
-  Tokens _tokens;
 
+  P3DFileParams _fparams;
   P3DWindowParams _wparams;
 
   int _instance_id;

+ 55 - 14
direct/src/plugin/p3dPythonRun.cxx

@@ -102,8 +102,8 @@ run_python() {
     PyErr_Print();
     return false;
   }
-  _runPackedApp = PyObject_GetAttrString(appmf, "runPackedApp");
-  if (_runPackedApp == NULL) {
+  _setP3DFilename = PyObject_GetAttrString(appmf, "setP3DFilename");
+  if (_setP3DFilename == NULL) {
     PyErr_Print();
     return false;
   }
@@ -155,7 +155,7 @@ handle_command(TiXmlDocument *doc) {
         TiXmlElement *xinstance = xcommand->FirstChildElement("instance");
         if (xinstance != (TiXmlElement *)NULL) {
           P3DCInstance *inst = new P3DCInstance(xinstance);
-          start_instance(inst);
+          start_instance(inst, xinstance);
         }
       } else if (strcmp(cmd, "terminate_instance") == 0) {
         int id;
@@ -284,20 +284,14 @@ join_read_thread() {
 //               Python process.
 ////////////////////////////////////////////////////////////////////
 void P3DPythonRun::
-start_instance(P3DCInstance *inst) {
-  nout << "starting instance " << inst->get_p3d_filename() << "\n";
+start_instance(P3DCInstance *inst, TiXmlElement *xinstance) {
+  nout << "starting instance " << inst << "\n";
   _instances[inst->get_instance_id()] = inst;
 
-  PyObject *tokens = inst->get_py_tokens();
-  
-  PyObject *result = PyObject_CallFunction
-    (_runPackedApp, "sO", inst->get_p3d_filename().c_str(), tokens);
-  Py_DECREF(tokens);
-
-  if (result == NULL) {
-    PyErr_Print();
+  TiXmlElement *xfparams = xinstance->FirstChildElement("fparams");
+  if (xfparams != (TiXmlElement *)NULL) {
+    set_p3d_filename(inst, xfparams);
   }
-  Py_XDECREF(result);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -323,6 +317,53 @@ terminate_instance(int id) {
   terminate_session();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DPythonRun::set_p3d_filename
+//       Access: Private
+//  Description: Sets the startup filename and tokens for the
+//               indicated instance.
+////////////////////////////////////////////////////////////////////
+void P3DPythonRun::
+set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
+  string p3d_filename;
+  const char *p3d_filename_c = xfparams->Attribute("p3d_filename");
+  if (p3d_filename_c != NULL) {
+    p3d_filename = p3d_filename_c;
+  }
+
+  PyObject *token_list = PyList_New(0);
+
+  TiXmlElement *xtoken = xfparams->FirstChildElement("token");
+  while (xtoken != NULL) {
+    string keyword, value;
+    const char *keyword_c = xtoken->Attribute("keyword");
+    if (keyword_c != NULL) {
+      keyword = keyword_c;
+    }
+
+    const char *value_c = xtoken->Attribute("value");
+    if (value_c != NULL) {
+      value = value_c;
+    }
+
+    PyObject *tuple = Py_BuildValue("(ss)", keyword.c_str(), 
+                                    value.c_str());
+    PyList_Append(token_list, tuple);
+    Py_DECREF(tuple);
+
+    xtoken = xtoken->NextSiblingElement("token");
+  }
+  
+  PyObject *result = PyObject_CallFunction
+    (_setP3DFilename, "sO", p3d_filename.c_str(), token_list);
+  Py_DECREF(token_list);
+
+  if (result == NULL) {
+    PyErr_Print();
+  }
+  Py_XDECREF(result);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPythonRun::setup_window
 //       Access: Private

+ 4 - 3
direct/src/plugin/p3dPythonRun.h

@@ -69,10 +69,11 @@ private:
   void spawn_read_thread();
   void join_read_thread();
 
-  void start_instance(P3DCInstance *inst);
+  void start_instance(P3DCInstance *inst, TiXmlElement *xinstance);
   void terminate_instance(int id);
+  void set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams);
   void setup_window(int id, TiXmlElement *xwparams);
-
+  
   void terminate_session();
 
 private:
@@ -93,7 +94,7 @@ private:
   int _py_argc;
   char **_py_argv;
 
-  PyObject *_runPackedApp;
+  PyObject *_setP3DFilename;
   PyObject *_setupWindow;
   PyObject *_taskMgr;
 

+ 1 - 1
direct/src/plugin/p3dSession.cxx

@@ -46,7 +46,7 @@ P3DSession(P3DInstance *inst) {
   _started_read_thread = false;
   _read_thread_continue = false;
 
-  _output_filename = inst->lookup_token("output_filename");
+  _output_filename = inst->get_fparams().lookup_token("output_filename");
 
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
 

+ 1 - 0
direct/src/plugin/p3d_plugin_composite1.cxx

@@ -1,6 +1,7 @@
 #include "p3d_plugin.cxx"
 #include "p3dDownload.cxx"
 #include "p3dFileDownload.cxx"
+#include "p3dFileParams.cxx"
 #include "p3dInstance.cxx"
 #include "p3dInstanceManager.cxx"
 #include "p3dMultifileReader.cxx"

+ 6 - 2
direct/src/plugin_npapi/Sources.pp

@@ -10,15 +10,19 @@
   #define TARGET nppanda3d
   #define LIB_PREFIX
 
+  #define LOCAL_LIBS plugin_common
+
   #define COMBINED_SOURCES \
     $[TARGET]_composite1.cxx
 
   #define SOURCES \
     nppanda3d_common.h \
-    nppanda3d_startup.h
+    ppInstance.h ppInstance.I \
+    startup.h
 
   #define INCLUDED_SOURCES \
-    nppanda3d_startup.cxx
+    ppInstance.cxx \
+    startup.cxx
  
   // Windows-specific options.
   #if $[WINDOWS_PLATFORM]

+ 3 - 2
direct/src/plugin_npapi/nppanda3d_common.h

@@ -54,10 +54,11 @@ extern ofstream logfile;
 #endif  // _WIN32, __APPLE__
 
 #include "npapi.h"
-//#include "npfunctions.h"
 #include "npupp.h"
 
-// Appears in nppanda3d_startup.cxx.
+#include "load_plugin.h"
+
+// Appears in startup.cxx.
 extern NPNetscapeFuncs *browser;
 
 #endif

+ 2 - 1
direct/src/plugin_npapi/nppanda3d_composite1.cxx

@@ -1,3 +1,4 @@
-#include "nppanda3d_startup.cxx"
+#include "ppInstance.cxx"
+#include "startup.cxx"
 
 

+ 14 - 0
direct/src/plugin_npapi/ppInstance.I

@@ -0,0 +1,14 @@
+// Filename: ppInstance.I
+// Created by:  drose (19Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+

+ 134 - 0
direct/src/plugin_npapi/ppInstance.cxx

@@ -0,0 +1,134 @@
+// Filename: ppInstance.cxx
+// Created by:  drose (19Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "ppInstance.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::Constructor
+//       Access: Public
+//  Description: Creates a new instance of a Panda3D plugin window.
+//               The create_data structure is supplied from NPAPI, and
+//               defines the initial parameters specified in the HTML
+//               document.
+////////////////////////////////////////////////////////////////////
+PPInstance::
+PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode, 
+           int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
+  logfile << "constructing " << this << "\n" << flush;
+  _inst = NULL;
+
+  // Copy the tokens and save them within this object.
+  _tokens.reserve(argc);
+  for (int i = 0; i < argc; ++i) {
+    P3D_token token;
+    token._keyword = strdup(argn[i]);
+    token._value = strdup(argv[i]);
+    logfile
+      << " " << i << ": " << token._keyword << " = " << token._value << "\n";
+    _tokens.push_back(token);
+  }
+
+  _npp_mode = mode;
+  _got_window = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PPInstance::
+~PPInstance() {
+  logfile
+    << "destructing " << this << "\n" << flush;
+
+  if (_inst != NULL) {
+    P3D_instance_finish(_inst);
+    _inst = NULL;
+  }
+
+  // Free the tokens we allocated.
+  Tokens::iterator ti;
+  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
+    free((char *)(*ti)._keyword);
+    free((char *)(*ti)._value);
+  }
+  _tokens.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::set_window
+//       Access: Public
+//  Description: Stores or updates the window parameters.
+////////////////////////////////////////////////////////////////////
+void PPInstance::
+set_window(NPWindow *window) {
+  if (window->x == _window.x &&
+      window->y == _window.y &&
+      window->width == _window.width &&
+      window->height == _window.height) {
+    // No changes.
+    return;
+  }
+
+  _window = *window;
+  _got_window = true;
+  
+  if (_inst != NULL) {
+    send_window();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::create_instance
+//       Access: Private
+//  Description: Actually creates the internal P3D_instance object.
+////////////////////////////////////////////////////////////////////
+void PPInstance::
+create_instance() {
+  assert(_inst == NULL);
+  const P3D_token *tokens = NULL;
+  if (!_tokens.empty()) {
+    tokens = &_tokens[0];
+  }
+
+  _inst = P3D_create_instance
+    (NULL, NULL, tokens, _tokens.size());
+
+  if (_inst != NULL && _got_window) {
+    send_window();
+  }
+}
+
+  
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::send_window
+//       Access: Private
+//  Description: Actually issues the window parameters to the internal
+//               P3D_instance object.
+////////////////////////////////////////////////////////////////////
+void PPInstance::
+send_window() {
+  assert(_inst != NULL);
+
+  P3D_window_handle parent_window;
+#ifdef _WIN32
+  parent_window._hwnd = (HWND)(_window.window);
+#endif
+
+  P3D_instance_setup_window
+    (_inst, P3D_WT_embedded,
+     _window.x, _window.y, _window.width, _window.height,
+     parent_window);
+}

+ 54 - 0
direct/src/plugin_npapi/ppInstance.h

@@ -0,0 +1,54 @@
+// Filename: ppInstance.h
+// Created by:  drose (19Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 PPINSTANCE_H
+#define PPINSTANCE_H
+
+#include "nppanda3d_common.h"
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : PPInstance
+// Description : This represents a single instance of the Panda3D
+//               plugin, via the NPAPI interface.  This instance
+//               brokers the communication with the P3D Core API, as
+//               defined in the plugin directory.
+////////////////////////////////////////////////////////////////////
+class PPInstance {
+public:
+  PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode, 
+             int16 argc, char *argn[], char *argv[], NPSavedData *saved);
+  ~PPInstance();
+
+  void set_window(NPWindow *window);
+
+private:
+  void create_instance();
+  void send_window();
+
+private:
+  typedef vector<P3D_token> Tokens;
+  Tokens _tokens;
+  unsigned int _npp_mode;
+
+  bool _got_window;
+  NPWindow _window;
+
+  P3D_instance *_inst;
+};
+
+#include "ppInstance.I"
+
+#endif

+ 18 - 30
direct/src/plugin_npapi/nppanda3d_startup.cxx → direct/src/plugin_npapi/startup.cxx

@@ -1,4 +1,4 @@
-// Filename: nppanda3d_startup.cxx
+// Filename: startup.cxx
 // Created by:  drose (17Jun09)
 //
 ////////////////////////////////////////////////////////////////////
@@ -12,9 +12,7 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#include "nppanda3d_startup.h"
-
-#include "../plugin/load_plugin_src.cxx"
+#include "startup.h"
 
 #ifdef _WIN32
 #include <malloc.h>
@@ -70,7 +68,7 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
   string plugin_location = "/Users/drose/player/direct/built/lib/p3d_plugin.dylib";
 #endif
 
-  if (!load_plugin(plugin_location.c_str())) {
+  if (!load_plugin(plugin_location)) {
     logfile << "couldn't load plugin\n" << flush;
     return NPERR_INVALID_PLUGIN_ERROR;
   }
@@ -136,16 +134,8 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
         int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
   logfile << "new instance\n" << flush;
 
-  // Copy the tokens into a temporary array of P3D_token objects.
-  P3D_token *tokens = (P3D_token *)alloca(sizeof(P3D_token) * argc);
-  for (int i = 0; i < argc; ++i) {
-    P3D_token &token = tokens[i];
-    token._keyword = argn[i];
-    token._value = argv[i];
-    logfile << " " << i << ": " << token._keyword << " = " << token._value << "\n";
-  }
-
-  instance->pdata = P3D_create_instance(NULL, NULL, tokens, argc);
+  instance->pdata = new PPInstance(pluginType, instance, mode,
+                                   argc, argn, argv, saved);
 
   return NPERR_NO_ERROR;
 }
@@ -159,7 +149,7 @@ NPError
 NPP_Destroy(NPP instance, NPSavedData **save) {
   logfile << "destroy instance\n" << flush;
   (*save) = NULL;
-  P3D_instance_finish((P3D_instance *)(instance->pdata));
+  delete (PPInstance *)(instance->pdata);
   instance->pdata = NULL;
 
   return NPERR_NO_ERROR;
@@ -179,20 +169,9 @@ NPP_SetWindow(NPP instance, NPWindow *window) {
           << ", " << window->width << ", " << window->height
           << "\n" << flush;
 
-  P3D_instance *inst = (P3D_instance *)(instance->pdata);
+  PPInstance *inst = (PPInstance *)(instance->pdata);
   assert(inst != NULL);
-  
-  P3D_window_handle parent_window;
-#ifdef _WIN32
-  parent_window._hwnd = (HWND)(window->window);
-#endif
-
-  P3D_instance_setup_window
-    (inst, P3D_WT_embedded,
-     window->x, window->y, window->width, window->height,
-     parent_window);
-
-  return NPERR_NO_ERROR;
+  inst->set_window(window);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -208,8 +187,17 @@ NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream,
               NPBool seekable, uint16 *stype) {
   logfile << "NewStream " << type << ", " << stream->url 
           << ", " << stream->end << "\n" << flush;
+  PPInstance *inst = (PPInstance *)(instance->pdata);
+  assert(inst != NULL);
+
+  //inst->new_stream(type, stream, seekable, stype);
+
   *stype = NP_ASFILEONLY;
-  return NPERR_NO_ERROR;
+
+  if (strcmp(type, "application/x-panda3d") == 0) {
+    return NPERR_NO_ERROR;
+  }
+  return NPERR_GENERIC_ERROR;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 3 - 5
direct/src/plugin_npapi/nppanda3d_startup.h → direct/src/plugin_npapi/startup.h

@@ -1,4 +1,4 @@
-// Filename: nppanda3d_startup.h
+// Filename: startup.h
 // Created by:  drose (19Jun09)
 //
 ////////////////////////////////////////////////////////////////////
@@ -12,13 +12,11 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef NPPANDA3D_STARTUP_H
-#define NPPANDA3D_STARTUP_H
+#ifndef STARTUP_H
+#define STARTUP_H
 
 #include "nppanda3d_common.h"
 
-#include "../plugin/load_plugin_src.h"
-
 extern "C" {
 #ifdef _WIN32
   NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs);

+ 2 - 0
direct/src/plugin_standalone/Sources.pp

@@ -6,6 +6,8 @@
   #define USE_PACKAGES openssl zlib
   #define TARGET panda3d
 
+  #define LOCAL_LIBS plugin_common
+
   #define OTHER_LIBS \
     prc:c dtoolutil:c dtoolbase:c dtool:m \
     interrogatedb:c dconfig:c dtoolconfig:m \

+ 3 - 4
direct/src/plugin_standalone/panda3d.cxx

@@ -34,9 +34,8 @@
 #include "thread.h"
 #include "pset.h"
 
-#include "../plugin/p3d_plugin.h"
-#include "../plugin/load_plugin_src.h"
-#include "../plugin/load_plugin_src.cxx"
+#include "p3d_plugin.h"
+#include "load_plugin.h"
 
 #ifndef HAVE_GETOPT
   #include "gnu_getopt.h"
@@ -283,7 +282,7 @@ usage() {
 
     << "Options:\n\n"
 
-    << "  -p p3d_plugin" << dll_ext << "\n"
+    << "  -p " << get_plugin_basename() << "\n"
     << "    Specify the full path to the particular Panda plugin DLL to\n"
     << "    run.  Normally, this will be found by searching in the usual\n"
     << "    places.\n\n"

+ 14 - 8
direct/src/showbase/RunAppMF.py

@@ -91,17 +91,21 @@ def initPackedAppEnvironment():
     # we plan to mount there.
     vfs.chdir(MultifileRoot)
 
-readyToStart = False
+gotWindow = False
+gotP3DFilename = False
 started = False
 def startIfReady():
-    global readyToStart, started
-    if readyToStart:
+    global gotWindow, gotP3DFilename, started
+    if started:
+        return
+    
+    if gotWindow and gotP3DFilename:
         started = True
         import main
         if hasattr(main, 'main') and callable(main.main):
             main.main()
 
-def runPackedApp(p3dFilename, tokens = []):
+def setP3DFilename(p3dFilename, tokens = []):
     tokenDict = dict(tokens)
     fname = Filename.fromOsSpecific(p3dFilename)
     if not p3dFilename:
@@ -156,6 +160,8 @@ def runPackedApp(p3dFilename, tokens = []):
             data = open(pathname, 'r').read()
             loadPrcFileData(pathname, data)
 
+    global gotP3DFilename
+    gotP3DFilename = True
     startIfReady()
 
 windowPrc = None
@@ -185,8 +191,8 @@ def setupWindow(windowType, x, y, width, height, parent):
         unloadPrcFile(windowPrc)
     windowPrc = loadPrcFileData("setupWindow", data)
 
-    global readyToStart
-    readyToStart = True
+    global gotWindow
+    gotWindow = True
     startIfReady()
 
 def parseSysArgs():
@@ -216,9 +222,9 @@ def parseSysArgs():
         
 
 if __name__ == '__main__':
-    readyToStart = True
+    gotWindow = True
     try:
-        runPackedApp(*parseSysArgs())
+        setP3DFilename(*parseSysArgs())
     except ArgumentError, e:
         print e.args[0]
         sys.exit(1)