David Rose 16 years ago
parent
commit
8f96fa71f5

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

@@ -84,6 +84,7 @@ P3DInstance(P3D_request_ready_func *func,
 #endif  // __APPLE__
 #endif  // __APPLE__
 
 
   // Set some initial properties.
   // Set some initial properties.
+  _panda_script_object->set_float_property("instanceDownloadProgress", 0.0);
   _panda_script_object->set_float_property("downloadProgress", 0.0);
   _panda_script_object->set_float_property("downloadProgress", 0.0);
   _panda_script_object->set_string_property("downloadPackageName", "");
   _panda_script_object->set_string_property("downloadPackageName", "");
   _panda_script_object->set_string_property("downloadPackageDisplayName", "");
   _panda_script_object->set_string_property("downloadPackageDisplayName", "");
@@ -147,6 +148,44 @@ P3DInstance::
 }
 }
 
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::set_p3d_url
+//       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.
+//
+//               The instance data at the other end of this URL is
+//               key.  We can't start the instance until we have
+//               downloaded the instance file and examined the
+//               p3d_info.xml, and we know what Python version we need
+//               and so forth.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+set_p3d_url(const string &p3d_url) {
+  // Make a temporary file to receive the instance data.
+  char *name = tempnam(NULL, "p3d_");
+  string filename = name;
+  free(name);
+
+  // Mark the time we started downloading, so we'll know when to set
+  // the install label.
+#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(filename);
+
+  _panda_script_object->set_string_property("status", "downloading_instance");
+  start_download(download);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::set_p3d_filename
 //     Function: P3DInstance::set_p3d_filename
 //       Access: Public
 //       Access: Public
@@ -158,6 +197,8 @@ set_p3d_filename(const string &p3d_filename) {
   _got_fparams = true;
   _got_fparams = true;
   _fparams.set_p3d_filename(p3d_filename);
   _fparams.set_p3d_filename(p3d_filename);
 
 
+  _panda_script_object->set_float_property("instanceDownloadProgress", 1.0);
+
   // This also sets up some internal data based on the contents of the
   // This also sets up some internal data based on the contents of the
   // above file and the associated tokens.
   // above file and the associated tokens.
 
 
@@ -184,6 +225,9 @@ set_p3d_filename(const string &p3d_filename) {
   // 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).
   // if Python has not yet started).
   send_notify("onpluginload");
   send_notify("onpluginload");
+
+  // Now we're ready to start.
+  inst_mgr->start_instance(this);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1082,6 +1126,7 @@ make_splash_window() {
   assert(_splash_window == NULL);
   assert(_splash_window == NULL);
 
 
   _splash_window = new SplashWindowType(this);
   _splash_window = new SplashWindowType(this);
+  _splash_window->set_install_label(_install_label);
 
 
   string splash_image_url = _fparams.lookup_token("splash_img");
   string splash_image_url = _fparams.lookup_token("splash_img");
   if (!_fparams.has_token("splash_img")) {
   if (!_fparams.has_token("splash_img")) {
@@ -1139,6 +1184,9 @@ report_package_info_ready(P3DPackage *package) {
          << " packages, total " << _total_download_size
          << " packages, total " << _total_download_size
          << " bytes required.\n";
          << " bytes required.\n";
 
 
+    if (_splash_window != NULL) {
+      _splash_window->set_install_progress(0.0);
+    }
     _panda_script_object->set_string_property("status", "downloading");
     _panda_script_object->set_string_property("status", "downloading");
     send_notify("ondownloadbegin");
     send_notify("ondownloadbegin");
 
 
@@ -1170,9 +1218,7 @@ start_next_download() {
       }
       }
       _panda_script_object->set_string_property("downloadPackageName", package->get_package_name());
       _panda_script_object->set_string_property("downloadPackageName", package->get_package_name());
       _panda_script_object->set_string_property("downloadPackageDisplayName", name);
       _panda_script_object->set_string_property("downloadPackageDisplayName", name);
-      if (_splash_window != NULL) {
-        _splash_window->set_install_label("Installing " + name);
-      }
+      set_install_label("Installing " + name);
 
 
       nout << "Downloading " << package->get_package_name()
       nout << "Downloading " << package->get_package_name()
            << ", package " << _download_package_index + 1
            << ", package " << _download_package_index + 1
@@ -1204,10 +1250,48 @@ start_next_download() {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::report_instance_progress
+//       Access: Private
+//  Description: Notified as the instance file is downloaded.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+report_instance_progress(double progress) {
+  if (!_show_dl_instance_progress) {
+    // If we haven't yet set the download label, set it after a full
+    // second has elapsed.  We don't want to set it too soon, because
+    // we're not really sure how long it will take to download (the
+    // instance file might be already in the browser cache).
+#ifdef _WIN32
+    int now = GetTickCount();
+    double elapsed = (double)(now - _start_dl_instance_tick) * 0.001;
+#else
+    struct timeval now;
+    gettimeofday(&now, NULL);
+    double elapsed = (double)(now.tv_sec - _start_dl_instance_timeval.tv_sec) +
+      (double)(now.tv_usec - _start_dl_instance_timeval.tv_usec) / 1000000.0;
+#endif
+
+    // Put up the progress bar after 2 seconds have elapsed, if we've
+    // still got some distance to go; or after 5 seconds have elapsed
+    // regardless.
+    if ((elapsed > 2.0 && progress < 0.7) ||
+        (elapsed > 5.0)) {
+      _show_dl_instance_progress = true;
+    }
+  }
+
+  if (_splash_window != NULL && _show_dl_instance_progress) {
+    _splash_window->set_install_progress(progress);
+  }
+  _panda_script_object->set_float_property("instanceDownloadProgress", progress);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::report_package_progress
 //     Function: P3DInstance::report_package_progress
 //       Access: Private
 //       Access: Private
-//  Description: Notified as a required package is downloaded.
+//  Description: Notified as the packages required by the instance
+//               file are downloaded.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DInstance::
 void P3DInstance::
 report_package_progress(P3DPackage *package, double progress) {
 report_package_progress(P3DPackage *package, double progress) {
@@ -1246,6 +1330,20 @@ report_package_done(P3DPackage *package, bool success) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::set_install_label
+//       Access: Private
+//  Description: Sets the install label that will be displayed on the
+//               splash window, if it is present.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+set_install_label(const string &install_label) {
+  _install_label = install_label;
+  if (_splash_window != NULL) {
+    _splash_window->set_install_label(_install_label);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::send_notify
 //     Function: P3DInstance::send_notify
 //       Access: Private
 //       Access: Private
@@ -1490,3 +1588,42 @@ download_finished(bool success) {
     }
     }
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::InstanceDownload::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DInstance::InstanceDownload::
+InstanceDownload(P3DInstance *inst) :
+  _inst(inst)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::InstanceDownload::download_progress
+//       Access: Protected, Virtual
+//  Description: Intended to be overloaded to generate an occasional
+//               callback as new data comes in.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::InstanceDownload::
+download_progress() {
+  _inst->report_instance_progress(get_download_progress());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::InstanceDownload::download_finished
+//       Access: Protected, Virtual
+//  Description: Intended to be overloaded to generate a callback
+//               when the download finishes, either successfully or
+//               otherwise.  The bool parameter is true if the
+//               download was successful.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::InstanceDownload::
+download_finished(bool success) {
+  P3DFileDownload::download_finished(success);
+  if (success) {
+    // We've successfully downloaded the instance data.
+    _inst->set_p3d_filename(get_filename());
+  }
+}

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

@@ -27,6 +27,10 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 #endif
 
 
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
 #include <deque>
 #include <deque>
 #include <map>
 #include <map>
 
 
@@ -48,6 +52,7 @@ public:
               const P3D_token tokens[], size_t num_tokens, void *user_data);
               const P3D_token tokens[], size_t num_tokens, void *user_data);
   ~P3DInstance();
   ~P3DInstance();
 
 
+  void set_p3d_url(const string &p3d_url);
   void set_p3d_filename(const string &p3d_filename);
   void set_p3d_filename(const string &p3d_filename);
   inline const P3DFileParams &get_fparams() const;
   inline const P3DFileParams &get_fparams() const;
 
 
@@ -95,10 +100,17 @@ private:
   class SplashDownload : public P3DFileDownload {
   class SplashDownload : public P3DFileDownload {
   public:
   public:
     SplashDownload(P3DInstance *inst);
     SplashDownload(P3DInstance *inst);
-
   protected:
   protected:
     virtual void download_finished(bool success);
     virtual void download_finished(bool success);
-
+  private:
+    P3DInstance *_inst;
+  };
+  class InstanceDownload : public P3DFileDownload {
+  public:
+    InstanceDownload(P3DInstance *inst);
+  protected:
+    virtual void download_progress();
+    virtual void download_finished(bool success);
   private:
   private:
     P3DInstance *_inst;
     P3DInstance *_inst;
   };
   };
@@ -114,8 +126,10 @@ private:
   void make_splash_window();
   void make_splash_window();
   void report_package_info_ready(P3DPackage *package);
   void report_package_info_ready(P3DPackage *package);
   void start_next_download();
   void start_next_download();
+  void report_instance_progress(double progress);
   void report_package_progress(P3DPackage *package, double progress);
   void report_package_progress(P3DPackage *package, double progress);
   void report_package_done(P3DPackage *package, bool progress);
   void report_package_done(P3DPackage *package, bool progress);
+  void set_install_label(const string &install_label);
 
 
   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);
@@ -158,8 +172,18 @@ private:
 #endif  // __APPLE__
 #endif  // __APPLE__
 
 
   P3DSplashWindow *_splash_window;
   P3DSplashWindow *_splash_window;
+  string _install_label;
   bool _instance_window_opened;
   bool _instance_window_opened;
 
 
+  // Members for deciding whether and when to display the progress bar
+  // for downloading the initial instance data.
+#ifdef _WIN32
+  int _start_dl_instance_tick;
+#else
+  struct timeval _start_dl_instance_timeval;
+#endif
+  bool _show_dl_instance_progress;
+
   typedef vector<P3DPackage *> Packages;
   typedef vector<P3DPackage *> Packages;
   Packages _packages;
   Packages _packages;
   Packages _downloading_packages;
   Packages _downloading_packages;

+ 21 - 7
direct/src/plugin/p3dInstanceManager.cxx

@@ -216,21 +216,35 @@ create_instance(P3D_request_ready_func *func,
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DInstanceManager::start_instance
+//     Function: P3DInstanceManager::set_p3d_filename
 //       Access: Public
 //       Access: Public
-//  Description: Actually starts the instance running.  Before this
-//               call, the instance is in an indeterminate state.  It
-//               is an error to call this more than once for a
-//               particular instance.
+//  Description: Sets the p3d_filename (or p3d_url) on a particular
+//               instance.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DInstanceManager::
 bool P3DInstanceManager::
-start_instance(P3DInstance *inst, const string &p3d_filename) {
+set_p3d_filename(P3DInstance *inst, bool is_local,
+                 const string &p3d_filename) {
   if (inst->is_started()) {
   if (inst->is_started()) {
     nout << "Instance started twice: " << inst << "\n";
     nout << "Instance started twice: " << inst << "\n";
     return false;
     return false;
   }
   }
-  inst->set_p3d_filename(p3d_filename);
+  if (is_local) {
+    inst->set_p3d_filename(p3d_filename);
+  } else {
+    inst->set_p3d_url(p3d_filename);
+  }
+}
+
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstanceManager::start_instance
+//       Access: Public
+//  Description: Actually starts the instance running on a particular
+//               session.  This is called by the P3DInstance when it
+//               successfully loads its instance file.
+////////////////////////////////////////////////////////////////////
+bool P3DInstanceManager::
+start_instance(P3DInstance *inst) {
   P3DSession *session;
   P3DSession *session;
   Sessions::iterator si = _sessions.find(inst->get_session_key());
   Sessions::iterator si = _sessions.find(inst->get_session_key());
   if (si == _sessions.end()) {
   if (si == _sessions.end()) {

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

@@ -57,7 +57,9 @@ public:
                   const P3D_token tokens[], size_t num_tokens, 
                   const P3D_token tokens[], size_t num_tokens, 
                   void *user_data);
                   void *user_data);
 
 
-  bool start_instance(P3DInstance *inst, const string &p3d_filename);
+  bool set_p3d_filename(P3DInstance *inst, bool is_local,
+                        const string &p3d_filename);
+  bool start_instance(P3DInstance *inst);
   void finish_instance(P3DInstance *inst);
   void finish_instance(P3DInstance *inst);
 
 
   P3DInstance *validate_instance(P3D_instance *instance);
   P3DInstance *validate_instance(P3D_instance *instance);

+ 12 - 9
direct/src/plugin/p3dOsxSplashWindow.cxx

@@ -240,15 +240,16 @@ paint_window() {
              &src_rect, &dest_rect, srcCopy, 0);
              &src_rect, &dest_rect, srcCopy, 0);
   }
   }
 
 
-  if (!_install_label.empty()) {
-    // Draw the progress bar.  We don't draw this bar unless the
-    // install_label has been set nonempty.
-    int bar_width = min((int)(win_width * 0.6), 400);
-    int bar_height = min((int)(win_height * 0.1), 24);
-    int bar_x = (win_width - bar_width) / 2;
-    int bar_y = (win_height - bar_height * 2);
-    
-    int progress = bar_x + 1 + (int)((bar_width - 2) * _install_progress);
+  // Draw the progress bar.  We don't draw this bar at all unless we
+  // have nonzero progress.
+  int bar_width = min((int)(win_width * 0.6), 400);
+  int bar_height = min((int)(win_height * 0.1), 24);
+  int bar_x = (win_width - bar_width) / 2;
+  int bar_y = (win_height - bar_height * 2);
+  
+  int progress_width = (int)((bar_width - 2) * _install_progress);
+  if (progress_width > 0) {
+    int progress = bar_x + 1 + progress_width;
     
     
     Rect rbar = { bar_y, bar_x, bar_y + bar_height, bar_x + bar_width };
     Rect rbar = { bar_y, bar_x, bar_y + bar_height, bar_x + bar_width };
     Rect rneed = { bar_y + 1, progress, bar_y + bar_height - 1, bar_x + bar_width - 1 };
     Rect rneed = { bar_y + 1, progress, bar_y + bar_height - 1, bar_x + bar_width - 1 };
@@ -262,7 +263,9 @@ paint_window() {
     
     
     RGBColor black = { 0, 0, 0 };
     RGBColor black = { 0, 0, 0 };
     RGBForeColor(&black);
     RGBForeColor(&black);
+  }
 
 
+  if (!_install_label.empty()) {
     // Now draw the install_label right above it.
     // Now draw the install_label right above it.
     TextFont(0);
     TextFont(0);
     TextFace(bold);
     TextFace(bold);

+ 4 - 7
direct/src/plugin/p3dWinSplashWindow.cxx

@@ -34,7 +34,6 @@ P3DWinSplashWindow(P3DInstance *inst) :
   _progress_bar = NULL;
   _progress_bar = NULL;
   _text_label = NULL;
   _text_label = NULL;
   _thread_running = false;
   _thread_running = false;
-  _got_install = false;
   _image_filename_changed = false;
   _image_filename_changed = false;
   _image_filename_temp = false;
   _image_filename_temp = false;
   _install_label_changed = false;
   _install_label_changed = false;
@@ -137,8 +136,6 @@ set_install_label(const string &install_label) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DWinSplashWindow::
 void P3DWinSplashWindow::
 set_install_progress(double install_progress) {
 set_install_progress(double install_progress) {
-  _got_install = true;
-
   ACQUIRE_LOCK(_install_lock);
   ACQUIRE_LOCK(_install_lock);
   _install_progress = install_progress;
   _install_progress = install_progress;
   RELEASE_LOCK(_install_lock);
   RELEASE_LOCK(_install_lock);
@@ -265,7 +262,6 @@ thread_run() {
     DispatchMessage(&msg);
     DispatchMessage(&msg);
 
 
     ACQUIRE_LOCK(_install_lock);
     ACQUIRE_LOCK(_install_lock);
-    bool got_install = _got_install;
     double install_progress = _install_progress;
     double install_progress = _install_progress;
     if (_image_filename_changed) {
     if (_image_filename_changed) {
       update_image_filename(_image_filename, _image_filename_temp);
       update_image_filename(_image_filename, _image_filename_temp);
@@ -277,17 +273,18 @@ thread_run() {
     _install_label_changed = false;
     _install_label_changed = false;
     RELEASE_LOCK(_install_lock);
     RELEASE_LOCK(_install_lock);
 
 
-    if (got_install && install_progress != last_progress) {
+    if (install_progress != last_progress) {
+      int progress = (int)(install_progress * 100.0);
       if (_progress_bar == NULL) {
       if (_progress_bar == NULL) {
         // Is it time to create the progress bar?
         // Is it time to create the progress bar?
-        if (!_install_label.empty()) {
+        if (progress != 0) {
           make_progress_bar();
           make_progress_bar();
         }
         }
       } else {
       } else {
         // Update the progress bar.  We do this only within the
         // Update the progress bar.  We do this only within the
         // thread, to ensure we don't get a race condition when
         // thread, to ensure we don't get a race condition when
         // starting or closing the thread.
         // starting or closing the thread.
-        SendMessage(_progress_bar, PBM_SETPOS, (int)(install_progress * 100.0), 0);
+        SendMessage(_progress_bar, PBM_SETPOS, progress, 0);
         
         
         last_progress = install_progress;
         last_progress = install_progress;
       }
       }

+ 5 - 11
direct/src/plugin/p3dX11SplashWindow.cxx

@@ -57,7 +57,6 @@ P3DX11SplashWindow(P3DInstance *inst) :
   _resized_width = 0;
   _resized_width = 0;
   _resized_height = 0;
   _resized_height = 0;
   _graphics_context = None;
   _graphics_context = None;
-  _got_install = false;
   _image_filename_changed = false;
   _image_filename_changed = false;
   _image_filename_temp = false;
   _image_filename_temp = false;
   _install_label_changed = false;
   _install_label_changed = false;
@@ -366,19 +365,17 @@ subprocess_run() {
     _image_filename_changed = false;
     _image_filename_changed = false;
 
 
     if (override || have_event || install_label != prev_label) {
     if (override || have_event || install_label != prev_label) {
-      redraw(install_label);
       override = false;
       override = false;
-
-      // Don't draw the progress bar unless we have some text in
-      // install_label.
-      if (!install_label.empty()) {
+      
+      if (install_progress != 0.0) {
+        redraw(install_label);
         XFillRectangle(_display, _window, _graphics_context, 12, _height - 18,
         XFillRectangle(_display, _window, _graphics_context, 12, _height - 18,
                        (unsigned int)(install_progress * (_width - 24)), 7);
                        (unsigned int)(install_progress * (_width - 24)), 7);
       }
       }
       XFlush(_display);
       XFlush(_display);
 
 
     } else if (install_progress != prev_progress) {
     } else if (install_progress != prev_progress) {
-      if (!install_label.empty()) {
+      if (install_progress != 0.0) {
         XFillRectangle(_display, _window, _graphics_context, 12, _height - 18,
         XFillRectangle(_display, _window, _graphics_context, 12, _height - 18,
                        (unsigned int)(install_progress * (_width - 24)), 7);
                        (unsigned int)(install_progress * (_width - 24)), 7);
       }
       }
@@ -457,7 +454,6 @@ receive_command() {
         double install_progress = 0.0;
         double install_progress = 0.0;
         xcommand->Attribute("install_progress", &install_progress);
         xcommand->Attribute("install_progress", &install_progress);
 
 
-        _got_install = true;
         _install_progress = install_progress;
         _install_progress = install_progress;
       }
       }
     }
     }
@@ -513,7 +509,7 @@ redraw(string label) {
     XClearArea(_display, _window, 10, _height - 20, _width - 20, 10, false);
     XClearArea(_display, _window, 10, _height - 20, _width - 20, 10, false);
   }
   }
 
 
-  if (!label.empty()) {
+  if (_install_progress != 0.0) {
     // Draw the rest - the label and the progress bar outline.
     // Draw the rest - the label and the progress bar outline.
     int text_width = label.size() * 6;
     int text_width = label.size() * 6;
     int text_height = 10;
     int text_height = 10;
@@ -587,8 +583,6 @@ setup_gc() {
     return;
     return;
   }
   }
 
 
-  string install_label = _install_label;
-  double install_progress = _install_progress;
   _install_label_changed = false;
   _install_label_changed = false;
   
   
   XFontStruct* fs = XLoadQueryFont(_display, "6x13");
   XFontStruct* fs = XLoadQueryFont(_display, "6x13");

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

@@ -70,7 +70,6 @@ private:
   int _width, _height;
   int _width, _height;
   
   
   bool _own_display;
   bool _own_display;
-  bool _got_install;
   bool _image_filename_changed;
   bool _image_filename_changed;
   string _image_filename;
   string _image_filename;
   bool _image_filename_temp;
   bool _image_filename_temp;

+ 6 - 2
direct/src/plugin/p3d_plugin.cxx

@@ -116,7 +116,8 @@ P3D_new_instance(P3D_request_ready_func *func,
 }
 }
 
 
 bool
 bool
-P3D_instance_start(P3D_instance *instance, const char *p3d_filename) {
+P3D_instance_start(P3D_instance *instance, bool is_local, 
+                   const char *p3d_filename) {
   nout << "instance_start\n";
   nout << "instance_start\n";
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   if (p3d_filename == NULL) {
   if (p3d_filename == NULL) {
@@ -127,7 +128,10 @@ P3D_instance_start(P3D_instance *instance, const char *p3d_filename) {
   P3DInstance *inst = inst_mgr->validate_instance(instance);
   P3DInstance *inst = inst_mgr->validate_instance(instance);
   bool result = false;
   bool result = false;
   if (inst != NULL) {
   if (inst != NULL) {
-    result = inst_mgr->start_instance(inst, p3d_filename);
+    // We don't actually start it immediately; the instance will have
+    // to download the p3d url and read it, reading the python
+    // version, before it can start.
+    result = inst_mgr->set_p3d_filename(inst, is_local, p3d_filename);
   }
   }
   RELEASE_LOCK(_api_lock);
   RELEASE_LOCK(_api_lock);
   return result;
   return result;

+ 6 - 6
direct/src/plugin/p3d_plugin.h

@@ -79,7 +79,7 @@ extern "C" {
    (below). This number will be incremented whenever there are changes
    (below). This number will be incremented whenever there are changes
    to any of the interface specifications defined in this header
    to any of the interface specifications defined in this header
    file. */
    file. */
-#define P3D_API_VERSION 6
+#define P3D_API_VERSION 7
 
 
 /************************ GLOBAL FUNCTIONS **************************/
 /************************ GLOBAL FUNCTIONS **************************/
 
 
@@ -240,14 +240,14 @@ P3D_new_instance_func(P3D_request_ready_func *func,
    P3D_new_instance(); it actually starts the instance running.
    P3D_new_instance(); it actually starts the instance running.
    Before this call, the instance will be in an indeterminate state.
    Before this call, the instance will be in an indeterminate state.
 
 
-   For p3d_filename pass the name of a file on disk that contains the
-   contents of the p3d file that should be launched within the
-   instance.  If this is empty or NULL, the "src" token (below) will
-   be downloaded instead.
+   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.
 
 
    The return value is true on success, false on failure. */
    The return value is true on success, false on failure. */
 typedef bool
 typedef bool
-P3D_instance_start_func(P3D_instance *instance, const char *p3d_filename);
+P3D_instance_start_func(P3D_instance *instance, bool is_local,
+                        const char *p3d_filename);
 
 
 
 
 /* Call this function to interrupt a particular instance and stop it
 /* Call this function to interrupt a particular instance and stop it

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

@@ -28,7 +28,6 @@ public:
   enum RequestType {
   enum RequestType {
     RT_contents_file,
     RT_contents_file,
     RT_core_dll,
     RT_core_dll,
-    RT_instance_data,
     RT_user
     RT_user
   };
   };
 
 

+ 14 - 22
direct/src/plugin_npapi/ppInstance.cxx

@@ -61,8 +61,7 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
 
 
   _root_dir = find_root_dir();
   _root_dir = find_root_dir();
 
 
-  _started_instance_data = false;
-  _got_instance_data = false;
+  _got_instance_url = false;
   _got_window = false;
   _got_window = false;
   _python_window_open = false;
   _python_window_open = false;
 }
 }
@@ -180,15 +179,18 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) {
     // This is an unsolicited stream.  Assume the first unsolicited
     // This is an unsolicited stream.  Assume the first unsolicited
     // stream we receive is the instance data; any other unsolicited
     // stream we receive is the instance data; any other unsolicited
     // stream is an error.
     // stream is an error.
-    if (!_started_instance_data) {
-      stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_instance_data);
-      *stype = NP_ASFILEONLY;
-      _started_instance_data = true;
-      return NPERR_NO_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) {
+      _got_instance_url = true;
+      _instance_url = stream->url;
+      if (_p3d_inst != NULL) {
+        P3D_instance_start(_p3d_inst, false, _instance_url.c_str());
+      }
     }
     }
 
 
-    // This is an unexpected unsolicited stream.  (Firefox seems to
-    // give us the instance data twice for some reason.)
+    // Don't finish downloading the unsolicited stream.
     return NPERR_GENERIC_ERROR;
     return NPERR_GENERIC_ERROR;
   }
   }
 
 
@@ -793,17 +795,6 @@ downloaded_file(PPDownloadRequest *req, const string &filename) {
     downloaded_plugin(filename);
     downloaded_plugin(filename);
     break;
     break;
 
 
-  case PPDownloadRequest::RT_instance_data:
-    // This is the instance data, e.g. the p3d filename.  Now we can
-    // launch the instance.
-    _got_instance_data = true;
-    _p3d_filename = filename;
-
-    if (_p3d_inst != NULL) {
-      P3D_instance_start(_p3d_inst, _p3d_filename.c_str());
-    }
-    break;
-
   case PPDownloadRequest::RT_user:
   case PPDownloadRequest::RT_user:
     // Normally, RT_user requests won't come here, unless we
     // Normally, RT_user requests won't come here, unless we
     // short-circuited the browser by "downloading" a file:// url.  In
     // short-circuited the browser by "downloading" a file:// url.  In
@@ -987,8 +978,8 @@ create_instance() {
       _script_object->set_p3d_object(obj);
       _script_object->set_p3d_object(obj);
     }
     }
 
 
-    if (_got_instance_data) {
-      P3D_instance_start(_p3d_inst, _p3d_filename.c_str());
+    if (_got_instance_url) {
+      P3D_instance_start(_p3d_inst, false, _instance_url.c_str());
     }
     }
 
 
     if (_got_window) {
     if (_got_window) {
@@ -1314,6 +1305,7 @@ is_done() const {
 void PPInstance::StreamingFileData::
 void PPInstance::StreamingFileData::
 thread_run() {
 thread_run() {
   static const size_t buffer_size = 81920;
   static const size_t buffer_size = 81920;
+  //static const size_t buffer_size = 512;
   char buffer[buffer_size];
   char buffer[buffer_size];
 
 
   _file.read(buffer, buffer_size);
   _file.read(buffer, buffer_size);

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

@@ -98,9 +98,8 @@ private:
   string _root_dir;
   string _root_dir;
   FileSpec _core_api_dll;
   FileSpec _core_api_dll;
 
 
-  bool _started_instance_data;
-  bool _got_instance_data;
-  string _p3d_filename;
+  bool _got_instance_url;
+  string _instance_url;
 
 
   // This class is used for feeding local files (accessed via a
   // This class is used for feeding local files (accessed via a
   // "file://" url) into the core API.
   // "file://" url) into the core API.

+ 1 - 1
direct/src/plugin_standalone/panda3d.cxx

@@ -632,7 +632,7 @@ create_instance(const string &arg, P3D_window_type window_type,
   if (inst != NULL) {
   if (inst != NULL) {
     P3D_instance_setup_window
     P3D_instance_setup_window
       (inst, window_type, win_x, win_y, win_width, win_height, parent_window);
       (inst, window_type, win_x, win_y, win_width, win_height, parent_window);
-    P3D_instance_start(inst, os_p3d_filename.c_str());
+    P3D_instance_start(inst, true, os_p3d_filename.c_str());
   }
   }
 
 
   return inst;
   return inst;