Browse Source

splash window

David Rose 16 years ago
parent
commit
f38724aa92

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

@@ -77,7 +77,7 @@ receive_data(const unsigned char *this_data, size_t this_data_size) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: P3DDownload::download_finished
+//     Function: P3DFileDownload::download_finished
 //       Access: Protected, Virtual
 //  Description: Intended to be overloaded to generate a callback
 //               when the download finishes, either successfully or

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

@@ -76,6 +76,24 @@ lookup_token(const string &keyword) const {
   return string();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DFileParams::has_token
+//       Access: Public
+//  Description: Returns true if the named token appears in the list,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool P3DFileParams::
+has_token(const string &keyword) const {
+  Tokens::const_iterator ti;
+  for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
+    if ((*ti)._keyword == keyword) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DFileParams::make_xml
 //       Access: Public

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

@@ -35,6 +35,7 @@ public:
 
   inline const string &get_p3d_filename() const;
   string lookup_token(const string &keyword) const;
+  bool has_token(const string &keyword) const;
 
   TiXmlElement *make_xml();
 

+ 75 - 10
direct/src/plugin/p3dInstance.cxx

@@ -113,16 +113,9 @@ set_fparams(const P3DFileParams &fparams) {
   // Maybe create the splash window.
   if (!_instance_window_opened && _got_wparams) {
     if (_splash_window == NULL) {
-      _splash_window = new SplashWindowType(this);
-      //      _splash_window->set_image_filename("c:/Documents and Settings/drose/Desktop/pandalogo.jpg");
+      make_splash_window();
     }
   }
-
-  /*
-  string splash_image_url = _fparams.lookup_token("splash_img");
-  if (!splash_image_url.is_empty()) {
-  }
-  */
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -140,8 +133,7 @@ set_wparams(const P3DWindowParams &wparams) {
   // Update or create the splash window.
   if (!_instance_window_opened && _got_fparams) {
     if (_splash_window == NULL) {
-      _splash_window = new SplashWindowType(this);
-      //      _splash_window->set_image_filename("c:/Documents and Settings/drose/Desktop/pandalogo.jpg");
+      make_splash_window();
     } else {
       _splash_window->set_wparams(_wparams);
     }
@@ -427,6 +419,48 @@ make_xml() {
   return xinstance;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::make_splash_window
+//       Access: Private
+//  Description: Creates the splash window to be displayed at startup.
+//               This method is called as soon as we have received
+//               both _fparams and _wparams.
+////////////////////////////////////////////////////////////////////
+void P3DInstance::
+make_splash_window() {
+  assert(_splash_window == NULL);
+
+  _splash_window = new SplashWindowType(this);
+
+  string splash_image_url = _fparams.lookup_token("splash_img");
+  if (!_fparams.has_token("splash_img")) {
+    // No specific splash image is specified; get the default splash
+    // image.
+    P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+    splash_image_url = inst_mgr->get_download_url();
+    splash_image_url += "coreapi/splash.jpg";
+  }
+
+  if (splash_image_url.empty()) {
+    // No splash image.  Never mind.
+    return;
+  }
+
+  // Make a temporary file to receive the splash image.
+  char *name = tempnam(NULL, "p3d_");
+  string filename = name;
+  free(name);
+
+  nout << "Downloading splash image into " << filename << "\n";
+
+  // Start downloading the requested splash image.
+  SplashDownload *download = new SplashDownload(this);
+  download->set_url(splash_image_url);
+  download->set_filename(filename);
+
+  start_download(download);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DInstance::install_progress
 //       Access: Private
@@ -439,3 +473,34 @@ install_progress(P3DPackage *package, double progress) {
     _splash_window->set_install_progress(progress);
   }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::SplashDownload::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+P3DInstance::SplashDownload::
+SplashDownload(P3DInstance *inst) :
+  _inst(inst)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstance::SplashDownload::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::SplashDownload::
+download_finished(bool success) {
+  P3DFileDownload::download_finished(success);
+  if (success) {
+    // We've successfully downloaded the splash image.  Put it
+    // onscreen if our splash window still exists.
+    if (_inst->_splash_window != NULL) {
+      _inst->_splash_window->set_image_filename(get_filename(), true);
+    }
+  }
+}

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

@@ -74,6 +74,18 @@ public:
   TiXmlElement *make_xml();
 
 private:
+  class SplashDownload : public P3DFileDownload {
+  public:
+    SplashDownload(P3DInstance *inst);
+
+  protected:
+    virtual void download_finished(bool success);
+
+  private:
+    P3DInstance *_inst;
+  };
+
+  void make_splash_window();
   void install_progress(P3DPackage *package, double progress);
 
   P3D_request_ready_func *_func;
@@ -105,6 +117,7 @@ private:
   static int _next_instance_id;
 
   friend class P3DSession;
+  friend class SplashDownload;
 };
 
 #include "p3dInstance.I"

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

@@ -22,7 +22,6 @@
 
 #include <algorithm>
 #include <fstream>
-//#include <fcntl.h>
 
 // The relative breakdown of the full install process.  Each phase is
 // worth this fraction of the total movement of the progress bar.

+ 137 - 2
direct/src/plugin/p3dSplashWindow.cxx

@@ -14,6 +14,31 @@
 
 #include "p3dSplashWindow.h"
 
+
+// Stuff to use libjpeg.
+extern "C" {
+#include <jpeglib.h>
+#include <jerror.h>
+}
+
+#include <setjmp.h>
+
+struct my_error_mgr {
+  struct jpeg_error_mgr pub;
+  jmp_buf setjmp_buffer;
+};
+
+typedef struct my_error_mgr *my_error_ptr;
+
+METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
+  // cinfo->err really points to a my_error_mgr struct, so coerce pointer
+  my_error_ptr myerr = (my_error_ptr) cinfo->err;
+  // Return control to the setjmp point
+  longjmp(myerr->setjmp_buffer, 1);
+}
+
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DSplashWindow::Constructor
 //       Access: Public
@@ -54,10 +79,16 @@ set_wparams(const P3DWindowParams &wparams) {
 //     Function: P3DSplashWindow::set_image_filename
 //       Access: Public, Virtual
 //  Description: Specifies the name of a JPEG image file that is
-//               displayed in the center of the splash window.
+//               displayed in the center of the splash window.  If
+//               image_filename_temp is true, the file is immediately
+//               deleted after it has been read.
 ////////////////////////////////////////////////////////////////////
 void P3DSplashWindow::
-set_image_filename(const string &image_filename) {
+set_image_filename(const string &image_filename,
+                   bool image_filename_temp) {
+  if (image_filename_temp) {
+    unlink(image_filename.c_str());
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -79,3 +110,107 @@ void P3DSplashWindow::
 set_install_progress(double install_progress) {
 }
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DSplashWindow::read_image
+//       Access: Protected
+//  Description: Reads the image filename and sets image parameters
+//               height, width, num_channels, row_stride, and data.
+//               Returns true on success, false on failure.  If
+//               image_filename_temp is true, the file will be deleted
+//               after reading.
+////////////////////////////////////////////////////////////////////
+bool P3DSplashWindow::
+read_image(const string &image_filename, bool image_filename_temp,
+           int &height, int &width, int &num_channels, int &row_stride,
+           string &data) {
+  height = 0;
+  width = 0;
+  num_channels = 0;
+  row_stride = 0;
+  data.clear();
+
+  // We currently only support JPEG images.  Maybe that's all we'll
+  // ever support.
+  FILE *fp = fopen(image_filename.c_str(), "rb");
+  if (fp == NULL) {
+    nout << "Couldn't open splash file image: " << image_filename << "\n"
+         << flush;
+    if (image_filename_temp) {
+      unlink(image_filename.c_str());
+    }
+    return false;
+  }
+
+  // We set up the normal JPEG error routines, then override error_exit.
+  struct jpeg_decompress_struct cinfo;
+
+  struct my_error_mgr jerr;
+  cinfo.err = jpeg_std_error(&jerr.pub);
+  jerr.pub.error_exit = my_error_exit;
+
+  JSAMPLE *buffer = NULL;
+  
+  // Establish the setjmp return context for my_error_exit to use
+  if (setjmp(jerr.setjmp_buffer)) {
+    // If we get here, the JPEG code has signaled an error.
+    nout << "JPEG error decoding " << image_filename << "\n"
+         << flush;
+
+    // We need to clean up the JPEG object, close the input file, and return.
+    jpeg_destroy_decompress(&cinfo);
+    fclose(fp);
+
+    if (buffer != NULL) {
+      delete[] buffer;
+    }
+
+    if (image_filename_temp) {
+      unlink(image_filename.c_str());
+    }
+    return false;
+  }
+
+  /* Now we can initialize the JPEG decompression object. */
+  jpeg_create_decompress(&cinfo);
+  jpeg_stdio_src(&cinfo, fp);
+
+  jpeg_read_header(&cinfo, true);
+
+  cinfo.scale_num = 1;
+  cinfo.scale_denom = 1;
+
+  jpeg_start_decompress(&cinfo);
+
+  width = cinfo.output_width;
+  height = cinfo.output_height;
+  num_channels = cinfo.output_components;
+
+  row_stride = width * num_channels;
+
+  // We'll pad row_stride out to word alignment.  Windows requires this.
+  row_stride = 4 * ((row_stride + 3) / 4);
+
+  size_t buffer_size = height * row_stride;
+  buffer = new JSAMPLE[buffer_size];
+  JSAMPLE *buffer_end = buffer + buffer_size;
+
+  JSAMPLE *rowptr = buffer;
+  while (cinfo.output_scanline < cinfo.output_height) {
+    assert(rowptr + row_stride <= buffer_end);
+    jpeg_read_scanlines(&cinfo, &rowptr, 1);
+    rowptr += row_stride;
+  }
+
+  jpeg_finish_decompress(&cinfo);
+
+  fclose(fp);
+  if (image_filename_temp) {
+    unlink(image_filename.c_str());
+  }
+
+  data.append((const char *)buffer, buffer_size);
+  delete[] buffer;
+
+  return true;
+}

+ 9 - 1
direct/src/plugin/p3dSplashWindow.h

@@ -42,10 +42,18 @@ public:
   virtual void set_wparams(const P3DWindowParams &wparams);
   inline const P3DWindowParams &get_wparams() const;
 
-  virtual void set_image_filename(const string &image_filename);
+  virtual void set_image_filename(const string &image_filename,
+                                  bool image_filename_temp);
   virtual void set_install_label(const string &install_label);
   virtual void set_install_progress(double install_progress);
 
+  void setup_splash_image();
+
+protected:
+  bool read_image(const string &image_filename, bool image_filename_temp,
+                  int &height, int &width, int &num_channels, int &row_stride,
+                  string &data);
+
 protected:
   P3DInstance *_inst;
   P3DFileParams _fparams;

+ 17 - 86
direct/src/plugin/p3dWinSplashWindow.cxx

@@ -16,31 +16,6 @@
 
 #ifdef _WIN32
 
-
-// Stuff to use libjpeg.
-extern "C" {
-#include <jpeglib.h>
-#include <jerror.h>
-}
-
-#include <setjmp.h>
-
-struct my_error_mgr {
-  struct jpeg_error_mgr pub;
-  jmp_buf setjmp_buffer;
-};
-
-typedef struct my_error_mgr *my_error_ptr;
-
-METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
-  // cinfo->err really points to a my_error_mgr struct, so coerce pointer
-  my_error_ptr myerr = (my_error_ptr) cinfo->err;
-  // Return control to the setjmp point
-  longjmp(myerr->setjmp_buffer, 1);
-}
-
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DWinSplashWindow::Constructor
 //       Access: Public
@@ -59,6 +34,7 @@ P3DWinSplashWindow(P3DInstance *inst) :
   _thread_running = false;
   _got_install = false;
   _image_filename_changed = false;
+  _image_filename_temp = false;
   _install_label_changed = false;
   _install_progress = 0.0;
 
@@ -82,14 +58,17 @@ P3DWinSplashWindow::
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DWinSplashWindow::set_image_filename
 //       Access: Public, Virtual
-//  Description: Specifies the name of a JPEG image file that is
-//               displayed in the center of the splash window.
+//               displayed in the center of the splash window.  If
+//               image_filename_temp is true, the file is immediately
+//               deleted after it has been read.
 ////////////////////////////////////////////////////////////////////
 void P3DWinSplashWindow::
-set_image_filename(const string &image_filename) {
+set_image_filename(const string &image_filename,
+                   bool image_filename_temp) {
   ACQUIRE_LOCK(_install_lock);
   if (_image_filename != image_filename) {
     _image_filename = image_filename;
+    _image_filename_temp = image_filename_temp;
     _image_filename_changed = true;
   }
   RELEASE_LOCK(_install_lock);
@@ -209,7 +188,7 @@ thread_run() {
       ACQUIRE_LOCK(_install_lock);
       double install_progress = _install_progress;
       if (_image_filename_changed) {
-        update_image_filename(_image_filename);
+        update_image_filename(_image_filename, _image_filename_temp);
       }
       _image_filename_changed = false;
       if (_install_label_changed && _progress_bar != NULL) {
@@ -439,7 +418,7 @@ update_install_label(const string &install_label) {
 //               sub-thread.
 ////////////////////////////////////////////////////////////////////
 void P3DWinSplashWindow::
-update_image_filename(const string &image_filename) {
+update_image_filename(const string &image_filename, bool image_filename_temp) {
   // Clear the old image.
   if (_bitmap != NULL) {
     DeleteObject(_bitmap);
@@ -450,70 +429,22 @@ update_image_filename(const string &image_filename) {
   // window.
   InvalidateRect(_hwnd, NULL, TRUE);
 
-  FILE *fp = fopen(image_filename.c_str(), "rb");
-  if (fp == NULL) {
-    nout << "Couldn't open splash file image: " << image_filename << "\n"
-         << flush;
+  // Go read the image.
+  string data;
+  int num_channels, row_stride;
+  if (!read_image(image_filename, image_filename_temp, 
+                  _bitmap_height, _bitmap_width, num_channels, row_stride,
+                  data)) {
     return;
   }
 
-  // We set up the normal JPEG error routines, then override error_exit.
-  struct jpeg_decompress_struct cinfo;
-
-  struct my_error_mgr jerr;
-  cinfo.err = jpeg_std_error(&jerr.pub);
-  jerr.pub.error_exit = my_error_exit;
-  
-  // Establish the setjmp return context for my_error_exit to use
-  if (setjmp(jerr.setjmp_buffer)) {
-    // If we get here, the JPEG code has signaled an error.
-    nout << "JPEG error decoding " << image_filename << "\n"
-         << flush;
-
-    // We need to clean up the JPEG object, close the input file, and return.
-    jpeg_destroy_decompress(&cinfo);
-    fclose(fp);
-    return;
-  }
-
-  /* Now we can initialize the JPEG decompression object. */
-  jpeg_create_decompress(&cinfo);
-  jpeg_stdio_src(&cinfo, fp);
-
-  jpeg_read_header(&cinfo, true);
-
-  cinfo.scale_num = 1;
-  cinfo.scale_denom = 1;
-
-  jpeg_start_decompress(&cinfo);
-
-  _bitmap_width = cinfo.output_width;
-  _bitmap_height = cinfo.output_height;
-
-  int row_stride = _bitmap_width * cinfo.output_components;
-  // We have to pad row_stride out to DWORD alignment.
-  row_stride = 4 * ((row_stride + 3) / 4);
-
-  size_t buffer_size = _bitmap_height * row_stride;
-  JSAMPLE *buffer = new JSAMPLE[buffer_size];
-  JSAMPLE *buffer_end = buffer + buffer_size;
-
-  JSAMPLE *rowptr = buffer;
-  while (cinfo.output_scanline < cinfo.output_height) {
-    assert(rowptr + row_stride <= buffer_end);
-    jpeg_read_scanlines(&cinfo, &rowptr, 1);
-    rowptr += row_stride;
-  }
-
-  jpeg_finish_decompress(&cinfo);
-
   // Now load the image.
   BITMAPINFOHEADER bmih;
   bmih.biSize = sizeof(bmih);
   bmih.biWidth = _bitmap_width;
   bmih.biHeight = -_bitmap_height;
   bmih.biPlanes = 1;
-  bmih.biBitCount = 8 * cinfo.output_components;
+  bmih.biBitCount = 8 * num_channels;
   bmih.biCompression = BI_RGB;
   bmih.biSizeImage = 0;
   bmih.biXPelsPerMeter = 0;
@@ -525,7 +456,7 @@ update_image_filename(const string &image_filename) {
   memcpy(&bmi, &bmih, sizeof(bmih));
 
   HDC dc = GetDC(_hwnd);
-  _bitmap = CreateDIBitmap(dc, &bmih, CBM_INIT, buffer, &bmi, 0);
+  _bitmap = CreateDIBitmap(dc, &bmih, CBM_INIT, data.data(), &bmi, 0);
   ReleaseDC(_hwnd, dc);
 
   nout << "Loaded splash file image: " << image_filename << "\n"

+ 5 - 2
direct/src/plugin/p3dWinSplashWindow.h

@@ -34,7 +34,8 @@ public:
   P3DWinSplashWindow(P3DInstance *inst);
   virtual ~P3DWinSplashWindow();
 
-  virtual void set_image_filename(const string &image_filename);
+  virtual void set_image_filename(const string &image_filename,
+                                  bool image_filename_temp);
   virtual void set_install_label(const string &install_label);
   virtual void set_install_progress(double install_progress);
 
@@ -50,7 +51,8 @@ private:
   void make_window();
   void make_progress_bar();
   void update_install_label(const string &install_label);
-  void update_image_filename(const string &image_filename);
+  void update_image_filename(const string &image_filename, 
+                             bool image_filename_temp);
   void close_window();
 
   LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@@ -60,6 +62,7 @@ private:
   bool _got_install;
   bool _image_filename_changed;
   string _image_filename;
+  bool _image_filename_temp;
   bool _install_label_changed;
   string _install_label;
   double _install_progress;