Explorar el Código

more download status notifications

David Rose hace 16 años
padre
commit
e0b1994b61

+ 78 - 14
direct/src/plugin/p3dInstance.cxx

@@ -83,6 +83,8 @@ P3DInstance(P3D_request_ready_func *func,
 
 
   // Set some initial properties.
   // Set some initial properties.
   _panda_script_object->set_float_property("downloadProgress", 0.0);
   _panda_script_object->set_float_property("downloadProgress", 0.0);
+  _panda_script_object->set_bool_property("downloadComplete", false);
+  _panda_script_object->set_string_property("status", "initial");
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -166,20 +168,8 @@ set_p3d_filename(const string &p3d_filename) {
 
 
   // Generate a special notification: onpluginload, indicating the
   // Generate a special notification: onpluginload, indicating the
   // plugin has read its parameters and is ready to be queried (even
   // plugin has read its parameters and is ready to be queried (even
-  // if Python has not yet started).  This notification is special
-  // because it generated at the C++ level, here; most of them are
-  // generated by the Python code, once that is running.
-  P3D_request *request = new P3D_request;
-  request->_request_type = P3D_RT_notify;
-  request->_request._notify._message = strdup("onpluginload");
-  add_baked_request(request);
-
-  // Also eval the HTML associated token.
-  string expression = _fparams.lookup_token("onpluginload");
-  if (!expression.empty() && _browser_script_object != NULL) {
-    P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
-    P3D_OBJECT_XDECREF(result);
-  }
+  // if Python has not yet started).
+  send_notify("onpluginload");
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -321,6 +311,30 @@ get_request() {
   P3D_request *request = _baked_requests.front();
   P3D_request *request = _baked_requests.front();
   _baked_requests.pop_front();
   _baked_requests.pop_front();
   _request_pending = !_baked_requests.empty();
   _request_pending = !_baked_requests.empty();
+
+  if (request != NULL) {
+    if (request->_request_type == P3D_RT_notify) {
+      // Also eval the associated HTML token, if any.
+      string message = request->_request._notify._message;
+      string expression = _fparams.lookup_token(message);
+      if (!expression.empty() && _browser_script_object != NULL) {
+        P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
+        P3D_OBJECT_XDECREF(result);
+      }
+
+    } else if (request->_request_type == P3D_RT_stop) {
+      // We also send an implicit message when Python requests itself
+      // to shutdown.
+      _panda_script_object->set_pyobj(NULL);
+      _panda_script_object->set_string_property("status", "stopped");
+
+      string expression = _fparams.lookup_token("onpythonstop");
+      if (!expression.empty() && _browser_script_object != NULL) {
+        P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
+        P3D_OBJECT_XDECREF(result);
+      }
+    }
+  }
   
   
   return request;
   return request;
 }
 }
@@ -720,6 +734,7 @@ make_p3d_request(TiXmlElement *xrequest) {
     if (strcmp(rtype, "notify") == 0) {
     if (strcmp(rtype, "notify") == 0) {
       const char *message = xrequest->Attribute("message");
       const char *message = xrequest->Attribute("message");
       if (message != NULL) {
       if (message != NULL) {
+        // A notify message from Python code.
         request = new P3D_request;
         request = new P3D_request;
         request->_request_type = P3D_RT_notify;
         request->_request_type = P3D_RT_notify;
         request->_request._notify._message = strdup(message);
         request->_request._notify._message = strdup(message);
@@ -816,6 +831,8 @@ handle_notify_request(const string &message) {
       P3D_OBJECT_DECREF(result);
       P3D_OBJECT_DECREF(result);
     }
     }
 
 
+    _panda_script_object->set_string_property("status", "running");
+
   } else if (message == "onwindowopen") {
   } else if (message == "onwindowopen") {
     // The process told us that it just succesfully opened its
     // The process told us that it just succesfully opened its
     // window.  Tear down the splash window.
     // window.  Tear down the splash window.
@@ -825,6 +842,8 @@ handle_notify_request(const string &message) {
       _splash_window = NULL;
       _splash_window = NULL;
     }
     }
 
 
+    _panda_script_object->set_string_property("status", "open");
+
 #ifdef __APPLE__
 #ifdef __APPLE__
     // Start a timer to update the frame repeatedly.  This seems to be
     // Start a timer to update the frame repeatedly.  This seems to be
     // steadier than waiting for nullEvent.
     // steadier than waiting for nullEvent.
@@ -976,6 +995,17 @@ make_splash_window() {
   start_download(download);
   start_download(download);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::start_package_download
+//       Access: Private
+//  Description: Notified when the package download begins.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+start_package_download(P3DPackage *package) {
+  _panda_script_object->set_string_property("status", "downloading");
+  send_notify("ondownloadbegin");
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::install_progress
 //     Function: P3DInstance::install_progress
 //       Access: Private
 //       Access: Private
@@ -990,6 +1020,40 @@ install_progress(P3DPackage *package, double progress) {
   _panda_script_object->set_float_property("downloadProgress", progress);
   _panda_script_object->set_float_property("downloadProgress", progress);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::package_ready
+//       Access: Private
+//  Description: Notified when the package is fully downloaded.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+package_ready(P3DPackage *package, bool success) {
+  if (success) {
+    install_progress(package, 1.0);
+    _panda_script_object->set_bool_property("downloadComplete", true);
+    _panda_script_object->set_string_property("status", "starting");
+    send_notify("ondownloadcomplete");
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::send_notify
+//       Access: Private
+//  Description: Generates a synthetic notify message here at the C++
+//               level.
+//
+//               Most notify messages are generated from within the
+//               Python code, and don't use this method; but a few
+//               have to be sent before Python has started, and those
+//               come through this method.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+send_notify(const string &message) {
+  P3D_request *request = new P3D_request;
+  request->_request_type = P3D_RT_notify;
+  request->_request._notify._message = strdup(message.c_str());
+  add_baked_request(request);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::paint_window
 //     Function: P3DInstance::paint_window
 //       Access: Private
 //       Access: Private

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

@@ -107,11 +107,15 @@ private:
                              const string &property_name, P3D_object *value,
                              const string &property_name, P3D_object *value,
                              bool needs_response, int unique_id);
                              bool needs_response, int unique_id);
   void make_splash_window();
   void make_splash_window();
+  void start_package_download(P3DPackage *package);
   void install_progress(P3DPackage *package, double progress);
   void install_progress(P3DPackage *package, double progress);
+  void package_ready(P3DPackage *package, bool success);
 
 
   void paint_window();
   void paint_window();
   void add_modifier_flags(unsigned int &swb_flags, int modifiers);
   void add_modifier_flags(unsigned int &swb_flags, int modifiers);
 
 
+  void send_notify(const string &message);
+
 #ifdef __APPLE__
 #ifdef __APPLE__
   static void timer_callback(CFRunLoopTimerRef timer, void *info);
   static void timer_callback(CFRunLoopTimerRef timer, void *info);
 #endif  // __APPLE__
 #endif  // __APPLE__

+ 39 - 19
direct/src/plugin/p3dSession.cxx

@@ -235,6 +235,7 @@ start_instance(P3DInstance *inst) {
       _panda3d_callback = new PackageCallback(this);
       _panda3d_callback = new PackageCallback(this);
       _panda3d->set_callback(_panda3d_callback);
       _panda3d->set_callback(_panda3d_callback);
     }
     }
+    inst->start_package_download(_panda3d);
   }
   }
 }
 }
 
 
@@ -656,6 +657,33 @@ install_progress(P3DPackage *package, double progress) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSession::package_ready
+//       Access: Private
+//  Description: Notified when the package is fully downloaded.
+////////////////////////////////////////////////////////////////////
+void P3DSession::
+package_ready(P3DPackage *package, bool success) {
+  _panda3d_callback = NULL;
+
+  Instances::iterator ii;
+  for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
+    P3DInstance *inst = (*ii).second;
+    inst->package_ready(package, success);
+  }
+
+  if (package == _panda3d) {
+    if (success) {
+      start_p3dpython();
+    } else {
+      nout << "Failed to install " << package->get_package_name()
+           << "_" << package->get_package_version() << "\n";
+    }
+  } else {
+    nout << "Unexpected panda3d package: " << package << "\n";
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSession::start_p3dpython
 //     Function: P3DSession::start_p3dpython
 //       Access: Private
 //       Access: Private
@@ -1093,38 +1121,30 @@ PackageCallback(P3DSession *session) :
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DSession::PackageCallback::package_ready
+//     Function: P3DSession::PackageCallback::install_progress
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description: This callback is received during the download process
+//               to inform us how much has been installed so far.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DSession::PackageCallback::
 void P3DSession::PackageCallback::
-package_ready(P3DPackage *package, bool success) {
+install_progress(P3DPackage *package, double progress) {
   if (this == _session->_panda3d_callback) {
   if (this == _session->_panda3d_callback) {
-    _session->_panda3d_callback = NULL;
-    if (package == _session->_panda3d) {
-      if (success) {
-        _session->start_p3dpython();
-      } else {
-        nout << "Failed to install " << package->get_package_name()
-             << "_" << package->get_package_version() << "\n";
-      }
-    } else {
-      nout << "Unexpected panda3d package: " << package << "\n";
-    }
+    _session->install_progress(package, progress);
   } else {
   } else {
     nout << "Unexpected callback for P3DSession\n";
     nout << "Unexpected callback for P3DSession\n";
   }
   }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DSession::PackageCallback::install_progress
+//     Function: P3DSession::PackageCallback::package_ready
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: This callback is received during the download process
-//               to inform us how much has been installed so far.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DSession::PackageCallback::
 void P3DSession::PackageCallback::
-install_progress(P3DPackage *package, double progress) {
+package_ready(P3DPackage *package, bool success) {
   if (this == _session->_panda3d_callback) {
   if (this == _session->_panda3d_callback) {
-    _session->install_progress(package, progress);
+    _session->package_ready(package, success);
+  } else {
+    nout << "Unexpected callback for P3DSession\n";
   }
   }
 }
 }

+ 1 - 0
direct/src/plugin/p3dSession.h

@@ -62,6 +62,7 @@ public:
 
 
 private:
 private:
   void install_progress(P3DPackage *package, double progress);
   void install_progress(P3DPackage *package, double progress);
+  void package_ready(P3DPackage *package, bool success);
   void start_p3dpython();
   void start_p3dpython();
 
 
   void spawn_read_thread();
   void spawn_read_thread();

+ 24 - 24
direct/src/plugin/p3dToplevelObject.cxx

@@ -34,7 +34,7 @@ P3DToplevelObject::
 ~P3DToplevelObject() {
 ~P3DToplevelObject() {
   set_pyobj(NULL);
   set_pyobj(NULL);
 
 
-  // Just in case there are properties we haven't cleared yet.
+  // Clear the local properties.
   Properties::const_iterator pi;
   Properties::const_iterator pi;
   for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
   for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
     P3D_object *value = (*pi).second;
     P3D_object *value = (*pi).second;
@@ -139,32 +139,34 @@ get_property(const string &property) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DToplevelObject::
 bool P3DToplevelObject::
 set_property(const string &property, P3D_object *value) {
 set_property(const string &property, P3D_object *value) {
-  if (_pyobj == NULL) {
-    // Without a pyobj, we just store the value locally.
-    if (value != NULL) {
-      Properties::iterator pi;
-      pi = _properties.insert(Properties::value_type(property, NULL)).first;
-      assert(pi != _properties.end());
+  // First, we set the property locally.
+  if (value != NULL) {
+    Properties::iterator pi;
+    pi = _properties.insert(Properties::value_type(property, NULL)).first;
+    assert(pi != _properties.end());
+    P3D_object *orig_value = (*pi).second;
+    if (orig_value != value) {
+      P3D_OBJECT_XDECREF(orig_value);
+      (*pi).second = value;
+      P3D_OBJECT_INCREF(value);
+    }
+  } else {
+    // (Or delete the property locally.)
+    Properties::iterator pi;
+    pi = _properties.find(property);
+    if (pi != _properties.end()) {
       P3D_object *orig_value = (*pi).second;
       P3D_object *orig_value = (*pi).second;
-      if (orig_value != value) {
-        P3D_OBJECT_XDECREF(orig_value);
-        (*pi).second = value;
-        P3D_OBJECT_INCREF(value);
-      }
-    } else {
-      // Or delete the property locally.
-      Properties::iterator pi;
-      pi = _properties.find(property);
-      if (pi != _properties.end()) {
-        P3D_object *orig_value = (*pi).second;
-        P3D_OBJECT_DECREF(orig_value);
-        _properties.erase(pi);
-      }
+      P3D_OBJECT_DECREF(orig_value);
+      _properties.erase(pi);
     }
     }
+  }
+
+  if (_pyobj == NULL) {
+    // Without a pyobj, that's all we do.
     return true;
     return true;
   }
   }
 
 
-  // With a pyobj, we pass this request down.
+  // With a pyobj, we also pass this request down.
   return P3D_OBJECT_SET_PROPERTY(_pyobj, property.c_str(), value);
   return P3D_OBJECT_SET_PROPERTY(_pyobj, property.c_str(), value);
 }
 }
 
 
@@ -246,9 +248,7 @@ set_pyobj(P3D_object *pyobj) {
         const string &property_name = (*pi).first;
         const string &property_name = (*pi).first;
         P3D_object *value = (*pi).second;
         P3D_object *value = (*pi).second;
         P3D_OBJECT_SET_PROPERTY(_pyobj, property_name.c_str(), value);
         P3D_OBJECT_SET_PROPERTY(_pyobj, property_name.c_str(), value);
-        P3D_OBJECT_DECREF(value);
       }
       }
-      _properties.clear();
     }
     }
   }
   }
 }
 }

+ 1 - 1
direct/src/plugin/p3d_lock.h

@@ -31,7 +31,7 @@ public:
 
 
 #define LOCK _lock
 #define LOCK _lock
 #define INIT_LOCK(lock) { InitializeCriticalSection(&(lock)._l); (lock)._count = 0; }
 #define INIT_LOCK(lock) { InitializeCriticalSection(&(lock)._l); (lock)._count = 0; }
-#define ACQUIRE_LOCK(lock) { EnterCriticalSection(&(lock)._l); ++((lock)._count); if ((lock)._count > 1) { nout << "count = " << (lock)._count << "\n"; } }
+#define ACQUIRE_LOCK(lock) { EnterCriticalSection(&(lock)._l); ++((lock)._count); }
 #define RELEASE_LOCK(lock) { --((lock)._count); LeaveCriticalSection(&(lock)._l); }
 #define RELEASE_LOCK(lock) { --((lock)._count); LeaveCriticalSection(&(lock)._l); }
 #define DESTROY_LOCK(lock) DeleteCriticalSection(&(lock)._l)
 #define DESTROY_LOCK(lock) DeleteCriticalSection(&(lock)._l)
 
 

+ 24 - 8
direct/src/plugin_npapi/ppInstance.cxx

@@ -70,13 +70,8 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PPInstance::
 PPInstance::
 ~PPInstance() {
 ~PPInstance() {
-#ifdef _WIN32
-  if (_got_window) {
-    // Restore the parent window to its own window handler.
-    HWND hwnd = (HWND)_window.window;
-    SetWindowLongPtr(hwnd, GWL_WNDPROC, _orig_window_proc);
-  }
-#endif  // _WIN32
+  nout << "Destructing PPInstance\n";
+  cleanup_window();
 
 
   if (_p3d_inst != NULL) {
   if (_p3d_inst != NULL) {
     P3D_instance_finish(_p3d_inst);
     P3D_instance_finish(_p3d_inst);
@@ -421,6 +416,7 @@ handle_request(P3D_request *request) {
       P3D_instance_finish(_p3d_inst);
       P3D_instance_finish(_p3d_inst);
       _p3d_inst = NULL;
       _p3d_inst = NULL;
     }
     }
+    cleanup_window();
     // Guess the browser doesn't really care.
     // Guess the browser doesn't really care.
     handled = true;
     handled = true;
     break;
     break;
@@ -1074,9 +1070,29 @@ send_window() {
      parent_window);
      parent_window);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PPInstance::cleanup_window
+//       Access: Private
+//  Description: Called at instance shutdown, this restores the parent
+//               window to its original state.
+////////////////////////////////////////////////////////////////////
+void PPInstance::
+cleanup_window() {
+  if (_got_window) {
+#ifdef _WIN32
+    // Restore the parent window to its own window handler.
+    HWND hwnd = (HWND)_window.window;
+    SetWindowLongPtr(hwnd, GWL_WNDPROC, _orig_window_proc);
+    nout << "Restored window handler for " << hwnd << "\n";
+    InvalidateRect(hwnd, NULL, true);
+#endif  // _WIN32
+    _got_window = false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PPInstance::copy_file
 //     Function: PPInstance::copy_file
-//       Access: Public
+//       Access: Private
 //  Description: Copies the data in the file named by from_filename
 //  Description: Copies the data in the file named by from_filename
 //               into the file named by to_filename.
 //               into the file named by to_filename.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -78,6 +78,7 @@ private:
 
 
   void create_instance();
   void create_instance();
   void send_window();
   void send_window();
+  void cleanup_window();
   bool copy_file(const string &from_filename, const string &to_filename);
   bool copy_file(const string &from_filename, const string &to_filename);
 
 
   static void handle_request_loop();
   static void handle_request_loop();

+ 3 - 0
direct/src/showutil/pfreeze.py

@@ -78,6 +78,9 @@ for opt, arg in opts:
             freezer.handleCustomPath(module)
             freezer.handleCustomPath(module)
     elif opt == '-h':
     elif opt == '-h':
         usage(0)
         usage(0)
+    else:
+        print 'illegal option: ' + flag
+        sys.exit(1)
 
 
 if not args:
 if not args:
     usage(0)
     usage(0)

+ 5 - 11
direct/src/showutil/runp3d.py

@@ -372,20 +372,14 @@ class AppRunner(DirectObject):
 
 
     def notifyRequest(self, message):
     def notifyRequest(self, message):
         """ Delivers a notify request to the browser.  This is a "this
         """ Delivers a notify request to the browser.  This is a "this
-        happened" type notification; it optionally triggers some
-        JavaScript code execution, and may also trigger some internal
-        automatic actions.  (For instance, the plugin takes down the
-        splash window when it sees the onwindowopen notification. """
+        happened" type notification; it also triggers some JavaScript
+        code execution, if indicated in the HTML tags, and may also
+        trigger some internal automatic actions.  (For instance, the
+        plugin takes down the splash window when it sees the
+        onwindowopen notification. """
 
 
         self.sendRequest('notify', message)
         self.sendRequest('notify', message)
 
 
-        # Now process any JavaScript that might be waiting for the
-        # event as well.  These are the JavaScript expressions that
-        # were specified in the HTML embed or object tag.
-        expression = self.tokenDict.get(message)
-        if expression:
-            self.evalScript(expression)
-
     def evalScript(self, expression, needsResponse = False):
     def evalScript(self, expression, needsResponse = False):
         """ Evaluates an arbitrary JavaScript expression in the global
         """ Evaluates an arbitrary JavaScript expression in the global
         DOM space.  This may be deferred if necessary if needsResponse
         DOM space.  This may be deferred if necessary if needsResponse