splash window

This commit is contained in:
David Rose 2009-06-30 19:18:22 +00:00
parent 8ae0185678
commit f38724aa92
10 changed files with 276 additions and 103 deletions

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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"

View File

@ -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.

View File

@ -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;
}

View File

@ -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;

View File

@ -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"

View File

@ -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;