Browse Source

P3D_instance_start_stream()

David Rose 16 years ago
parent
commit
fbb5c7ce0d

+ 5 - 0
direct/src/plugin/load_plugin.cxx

@@ -40,6 +40,7 @@ P3D_set_plugin_version_func *P3D_set_plugin_version;
 P3D_set_super_mirror_func *P3D_set_super_mirror;
 P3D_new_instance_func *P3D_new_instance;
 P3D_instance_start_func *P3D_instance_start;
+P3D_instance_start_stream_func *P3D_instance_start_stream;
 P3D_instance_finish_func *P3D_instance_finish;
 P3D_instance_setup_window_func *P3D_instance_setup_window;
 
@@ -193,6 +194,7 @@ load_plugin(const string &p3d_plugin_filename,
   P3D_set_super_mirror = (P3D_set_super_mirror_func *)get_func(module, "P3D_set_super_mirror");  
   P3D_new_instance = (P3D_new_instance_func *)get_func(module, "P3D_new_instance");  
   P3D_instance_start = (P3D_instance_start_func *)get_func(module, "P3D_instance_start");  
+  P3D_instance_start_stream = (P3D_instance_start_stream_func *)get_func(module, "P3D_instance_start_stream");  
   P3D_instance_finish = (P3D_instance_finish_func *)get_func(module, "P3D_instance_finish");  
   P3D_instance_setup_window = (P3D_instance_setup_window_func *)get_func(module, "P3D_instance_setup_window");  
 
@@ -234,6 +236,7 @@ load_plugin(const string &p3d_plugin_filename,
       P3D_set_super_mirror == NULL ||
       P3D_new_instance == NULL ||
       P3D_instance_start == NULL ||
+      P3D_instance_start_stream == NULL ||
       P3D_instance_finish == NULL ||
       P3D_instance_setup_window == NULL ||
 
@@ -275,6 +278,7 @@ load_plugin(const string &p3d_plugin_filename,
       << "\nP3D_set_super_mirror = " << P3D_set_super_mirror
       << "\nP3D_new_instance = " << P3D_new_instance
       << "\nP3D_instance_start = " << P3D_instance_start
+      << "\nP3D_instance_start_stream = " << P3D_instance_start_stream
       << "\nP3D_instance_finish = " << P3D_instance_finish
       << "\nP3D_instance_setup_window = " << P3D_instance_setup_window
       
@@ -371,6 +375,7 @@ unload_dso() {
   P3D_set_super_mirror = NULL;
   P3D_new_instance = NULL;
   P3D_instance_start = NULL;
+  P3D_instance_start_stream = NULL;
   P3D_instance_finish = NULL;
   P3D_instance_setup_window = NULL;
 

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

@@ -26,6 +26,7 @@ extern P3D_set_plugin_version_func *P3D_set_plugin_version;
 extern P3D_set_super_mirror_func *P3D_set_super_mirror;
 extern P3D_new_instance_func *P3D_new_instance;
 extern P3D_instance_start_func *P3D_instance_start;
+extern P3D_instance_start_stream_func *P3D_instance_start_stream;
 extern P3D_instance_finish_func *P3D_instance_finish;
 extern P3D_instance_setup_window_func *P3D_instance_setup_window;
 

+ 57 - 8
direct/src/plugin/p3dInstance.cxx

@@ -279,7 +279,8 @@ P3DInstance::
 //       Access: Public
 //  Description: Specifies a URL that should be contacted to download
 //               the instance data.  Normally this, or
-//               set_p3d_filename(), is only called once.
+//               set_p3d_filename() or make_p3d_stream(), is only
+//               called once.
 //
 //               The instance data at the other end of this URL is
 //               key.  We can't start the instance until we have
@@ -315,6 +316,41 @@ set_p3d_url(const string &p3d_url) {
   start_download(download);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::make_p3d_stream
+//       Access: Public
+//  Description: Indicates an intention to transmit the p3d data as a
+//               stream.  Should return a new unique stream ID to
+//               receive it.
+////////////////////////////////////////////////////////////////////
+int P3DInstance::
+make_p3d_stream(const string &p3d_url) {
+  // Make a temporary file to receive the instance data.
+  assert(_temp_p3d_filename == NULL);
+  _temp_p3d_filename = new P3DTemporaryFile(".p3d");
+  _stuff_to_download = true;
+
+  // Maybe it's time to open a splash window now.
+  make_splash_window();
+
+  // Mark the time we started downloading, so we'll know when to reveal
+  // the progress bar.
+#ifdef _WIN32
+  _start_dl_instance_tick = GetTickCount();
+#else
+  gettimeofday(&_start_dl_instance_timeval, NULL);
+#endif
+  _show_dl_instance_progress = false;
+
+  // Start downloading the data.
+  InstanceDownload *download = new InstanceDownload(this);
+  download->set_url(p3d_url);
+  download->set_filename(_temp_p3d_filename->get_filename());
+
+  _panda_script_object->set_string_property("status", "downloading_instance");
+  return start_download(download, false);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::set_p3d_filename
 //       Access: Public
@@ -908,9 +944,18 @@ get_packages_failed() const {
 //               This increments the P3DDownload object's reference
 //               count, and will decrement it (and possibly delete the
 //               object) after download_finished() has been called.
+//
+//               add_request should be true to actually request the
+//               URL from the plugin, or false not to.  Normally, this
+//               should always be set true, except in the one special
+//               case of make_p3d_stream(), in which case the plugin
+//               is already prepared to send the stream and doesn't
+//               need to have it requested.
+//
+//               Returns the unique ID of this stream.
 ////////////////////////////////////////////////////////////////////
-void P3DInstance::
-start_download(P3DDownload *download) {
+int P3DInstance::
+start_download(P3DDownload *download, bool add_request) {
   assert(download->get_download_id() == 0);
   assert(!download->get_url().empty());
 
@@ -923,12 +968,16 @@ start_download(P3DDownload *download) {
   bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second;
   assert(inserted);
 
-  P3D_request *request = new P3D_request;
-  request->_request_type = P3D_RT_get_url;
-  request->_request._get_url._url = strdup(download->get_url().c_str());
-  request->_request._get_url._unique_id = download_id;
+  if (add_request) {
+    P3D_request *request = new P3D_request;
+    request->_request_type = P3D_RT_get_url;
+    request->_request._get_url._url = strdup(download->get_url().c_str());
+    request->_request._get_url._unique_id = download_id;
+    
+    add_baked_request(request);
+  }
 
-  add_baked_request(request);
+  return download_id;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 1
direct/src/plugin/p3dInstance.h

@@ -59,6 +59,7 @@ public:
 
   void set_p3d_url(const string &p3d_url);
   void set_p3d_filename(const string &p3d_filename);
+  int make_p3d_stream(const string &p3d_url);
   inline const P3DFileParams &get_fparams() const;
 
   void set_wparams(const P3DWindowParams &wparams);
@@ -97,7 +98,7 @@ public:
   bool get_packages_failed() const;
   
   inline bool is_trusted() const;
-  void start_download(P3DDownload *download);
+  int start_download(P3DDownload *download, bool add_request = true);
   inline bool is_started() const;
   inline bool is_failed() const;
   void request_stop_sub_thread();

+ 16 - 0
direct/src/plugin/p3dInstanceManager.cxx

@@ -425,6 +425,22 @@ set_p3d_filename(P3DInstance *inst, bool is_local,
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstanceManager::make_p3d_stream
+//       Access: Public
+//  Description: Indicates an intention to transmit the p3d data as a
+//               stream.  Should return a new unique stream ID to
+//               receive it.
+////////////////////////////////////////////////////////////////////
+int P3DInstanceManager::
+make_p3d_stream(P3DInstance *inst, const string &p3d_url) {
+  if (inst->is_started()) {
+    nout << "Instance started twice: " << inst << "\n";
+    return -1;
+  }
+  return inst->make_p3d_stream(p3d_url);
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstanceManager::start_instance

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

@@ -92,6 +92,7 @@ public:
 
   bool set_p3d_filename(P3DInstance *inst, bool is_local,
                         const string &p3d_filename);
+  int make_p3d_stream(P3DInstance *inst, const string &p3d_url);
   bool start_instance(P3DInstance *inst);
   void finish_instance(P3DInstance *inst);
   P3DAuthSession *authorize_instance(P3DInstance *inst);

+ 17 - 0
direct/src/plugin/p3d_plugin.cxx

@@ -151,6 +151,23 @@ P3D_instance_start(P3D_instance *instance, bool is_local,
   return result;
 }
 
+int
+P3D_instance_start_stream(P3D_instance *instance, const char *p3d_url) {
+  assert(P3DInstanceManager::get_global_ptr()->is_initialized());
+  if (p3d_url == NULL) {
+    p3d_url = "";
+  }
+  ACQUIRE_LOCK(_api_lock);
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+  P3DInstance *inst = inst_mgr->validate_instance(instance);
+  int result = -1;
+  if (inst != NULL) {
+    result = inst_mgr->make_p3d_stream(inst, p3d_url);
+  }
+  RELEASE_LOCK(_api_lock);
+  return result;
+}
+
 void
 P3D_instance_finish(P3D_instance *instance) {
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());

+ 17 - 1
direct/src/plugin/p3d_plugin.h

@@ -313,13 +313,28 @@ P3D_new_instance_func(P3D_request_ready_func *func,
 
    If is_local is true, then p3d_filename contains the name of a local
    p3d file on disk.  If false, then p3d_filename contains a URL that
-   should be downloaded to retrieve the p3d file.
+   should be downloaded to retrieve the p3d file.  Also see
+   P3D_instance_start_stream(), below.
 
    The return value is true on success, false on failure. */
 typedef bool
 P3D_instance_start_func(P3D_instance *instance, bool is_local,
                         const char *p3d_filename);
 
+/* This function is an alternative to P3D_instance_start(); it
+   indicates an intention to feed the p3d file data to the instance as
+   a stream.  The instance should return a unique integer ID for this
+   stream, as if the instance had requested the stream via a get_url
+   request (below).  The plugin will then send the p3d file data to
+   the instance via a series of calls to
+   P3D_instance_feed_url_stream(), using the unique ID returned by
+   this function.  When the stream has been transmitted successfully,
+   the instance will automatically start.
+
+   The p3d_url string passed to this function is informational only.
+   The instance will not explicitly request this URL. */
+typedef int
+P3D_instance_start_stream_func(P3D_instance *instance, const char *p3d_url);
 
 /* Call this function to interrupt a particular instance and stop it
    from rendering, for instance when the user navigates away from the
@@ -890,6 +905,7 @@ EXPCL_P3D_PLUGIN P3D_set_super_mirror_func P3D_set_super_mirror;
 
 EXPCL_P3D_PLUGIN P3D_new_instance_func P3D_new_instance;
 EXPCL_P3D_PLUGIN P3D_instance_start_func P3D_instance_start;
+EXPCL_P3D_PLUGIN P3D_instance_start_stream_func P3D_instance_start_stream;
 EXPCL_P3D_PLUGIN P3D_instance_finish_func P3D_instance_finish;
 EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window;
 

+ 1 - 2
direct/src/plugin_npapi/ppDownloadRequest.h

@@ -28,8 +28,7 @@ public:
   enum RequestType {
     RT_contents_file,
     RT_core_dll,
-    RT_user,
-    RT_instance_data
+    RT_user
   };
 
   inline PPDownloadRequest(RequestType rtype, int user_id = 0);

+ 3 - 20
direct/src/plugin_npapi/ppInstance.cxx

@@ -192,19 +192,12 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
     // stream we receive is the instance data; any other unsolicited
     // stream is an error.
 
-    // We don't let Mozilla finish downloading the instance data, but
-    // we do extract its URL to pass to the instance.
-    if (!_got_instance_url && stream->url != NULL) {
+    if (!_got_instance_url && stream->url != NULL && _p3d_inst != NULL) {
       _got_instance_url = true;
       _instance_url = stream->url;
-      if (_p3d_inst != NULL) {
-        P3D_instance_start(_p3d_inst, false, _instance_url.c_str());
-      } 
+      int user_id = P3D_instance_start_stream(_p3d_inst, _instance_url.c_str());
 
-      // We don't want the rest of this stream any more, but we can't
-      // just return NPERR_GENERIC_ERROR, though--that seems to freak
-      // out Firefox.
-      stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_instance_data);
+      stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_user, user_id);
 
       *stype = NP_NORMAL;
       return NPERR_NO_ERROR;
@@ -263,13 +256,6 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) {
                                  P3D_RC_in_progress, 0,
                                  stream->end, buffer, len);
     return len;
-
-  case PPDownloadRequest::RT_instance_data:
-    // Here's a stream we don't really want.  But stopping it here
-    // seems to freak out Safari.  (And stopping it before it starts
-    // freaks out Firefox.)  Whatever.  We'll just quietly ignore the
-    // data.
-    return len;
     
   default:
     nout << "Unexpected write_stream on " << stream->url << "\n";
@@ -309,9 +295,6 @@ destroy_stream(NPStream *stream, NPReason reason) {
     }
     break;
 
-  case PPDownloadRequest::RT_instance_data:
-    break;
-
   default:
     nout << "Unexpected destroy_stream on " << stream->url << "\n";
     break;