support unknown-sized downloads

This commit is contained in:
David Rose 2009-12-09 15:37:48 +00:00
parent 7d9d27e74f
commit a7ac5345f4
14 changed files with 159 additions and 42 deletions

View File

@ -27,18 +27,33 @@ get_url() const {
// Function: P3DDownload::get_download_progress
// Access: Public
// Description: Returns an indication of the progress through the
// download file, 0.0 to 1.0. Returns 0.0 if the size
// download file, 0.0 to 1.0. Returns 1.0 if the size
// of the file is not known.
////////////////////////////////////////////////////////////////////
inline double P3DDownload::
get_download_progress() const {
if (_total_expected_data == 0) {
return 0.0;
return 1.0;
}
return (double)_total_data / (double)_total_expected_data;
}
////////////////////////////////////////////////////////////////////
// Function: P3DDownload::is_download_progress_known
// Access: Public
// Description: Returns true if the download progress is known, or
// false if it is unknown because the server hasn't told
// us the total size it will be feeding us. If this is
// false, get_download_progress() will generally always
// return 1.0; use get_total_bytes() to measure progress
// in this case.
////////////////////////////////////////////////////////////////////
inline bool P3DDownload::
is_download_progress_known() const {
return _progress_known;
}
////////////////////////////////////////////////////////////////////
// Function: P3DDownload::get_total_data
// Access: Public
@ -49,6 +64,21 @@ get_total_data() const {
return _total_data;
}
////////////////////////////////////////////////////////////////////
// Function: P3DDownload::set_total_expected_data
// Access: Public
// Description: Sets the total number of bytes expected to be
// downloaded. This is used to compute the progress.
// Normally, this can be set from the download server,
// but there may be cases when the download server
// doesn't accurately report it.
////////////////////////////////////////////////////////////////////
inline void P3DDownload::
set_total_expected_data(size_t expected_data) {
_total_expected_data = expected_data;
_progress_known = true;
}
////////////////////////////////////////////////////////////////////
// Function: P3DDownload::get_download_finished
// Access: Public

View File

@ -26,6 +26,7 @@ P3DDownload() {
_total_data = 0;
_total_expected_data = 0;
_last_reported_time = 0;
_progress_known = false;
_canceled = false;
_download_id = 0;
@ -39,7 +40,8 @@ P3DDownload() {
P3DDownload::
P3DDownload(const P3DDownload &copy) :
_url(copy._url),
_total_expected_data(copy._total_expected_data)
_total_expected_data(copy._total_expected_data),
_progress_known(copy._progress_known)
{
_status = P3D_RC_in_progress;
_http_status_code = 0;
@ -132,12 +134,27 @@ feed_url_stream(P3D_result_code result_code,
_total_data += this_data_size;
}
_total_expected_data = max(total_expected_data, _total_data);
total_expected_data = max(total_expected_data, _total_data);
if (total_expected_data > _total_expected_data) {
// If the expected data grows during the download, we don't really
// know how much we're getting.
_progress_known = false;
_total_expected_data = total_expected_data;
}
if (_total_expected_data > 0 &&
(double)_total_data / (double)_total_expected_data < 0.9) {
// But if we're not close to our target yet, let's say we do know
// (at least until we get there and the target moves again).
_progress_known = true;
}
download_progress();
if (_status != P3D_RC_in_progress) {
// We're done.
if (get_download_success()) {
_progress_known = true;
}
download_finished(get_download_success());
}
@ -167,9 +184,13 @@ download_progress() {
time_t now = time(NULL);
if (now - _last_reported_time > 10) {
_last_reported_time = now;
nout << "Downloading " << get_url() << ": "
<< int(get_download_progress() * 1000.0) / 10.0
<< ", " << this << "\n";
nout << "Downloading " << get_url() << ": ";
if (_progress_known) {
nout << int(get_download_progress() * 1000.0) / 10.0 << "%";
} else {
nout << int((double)get_total_data() / 104857.6) / 10.0 << "M";
}
nout << ", " << this << "\n";
}
}
@ -183,7 +204,11 @@ download_progress() {
////////////////////////////////////////////////////////////////////
void P3DDownload::
download_finished(bool success) {
nout << "Downloaded " << get_url() << ": "
<< int(get_download_progress() * 1000.0) / 10.0
<< ", " << this << ", success = " << success << "\n";
nout << "Downloaded " << get_url() << ": ";
if (_progress_known) {
nout << int(get_download_progress() * 1000.0) / 10.0 << "%";
} else {
nout << int((double)get_total_data() / 104857.6) / 10.0 << "M";
}
nout << ", " << this << ", success = " << success << "\n";
}

View File

@ -38,10 +38,12 @@ public:
inline const string &get_url() const;
inline double get_download_progress() const;
inline bool is_download_progress_known() const;
inline bool get_download_finished() const;
inline bool get_download_success() const;
inline bool get_download_terminated() const;
inline size_t get_total_data() const;
inline void set_total_expected_data(size_t expected_data);
void cancel();
void clear();
@ -70,6 +72,7 @@ protected:
size_t _total_data;
size_t _total_expected_data;
time_t _last_reported_time;
bool _progress_known;
private:
bool _canceled;

View File

@ -332,6 +332,9 @@ set_p3d_url(const string &p3d_url) {
InstanceDownload *download = new InstanceDownload(this);
download->set_url(p3d_url);
download->set_filename(_temp_p3d_filename->get_filename());
if (_fparams.has_token("p3d_size")) {
download->set_total_expected_data(_fparams.lookup_token_int("p3d_size"));
}
_panda_script_object->set_string_property("status", "downloading_instance");
start_download(download);
@ -371,6 +374,9 @@ make_p3d_stream(const string &p3d_url) {
InstanceDownload *download = new InstanceDownload(this);
download->set_url(p3d_url);
download->set_filename(_temp_p3d_filename->get_filename());
if (_fparams.has_token("p3d_size")) {
download->set_total_expected_data(_fparams.lookup_token_int("p3d_size"));
}
_panda_script_object->set_string_property("status", "downloading_instance");
return start_download(download, false);
@ -2438,7 +2444,7 @@ report_package_info_ready(P3DPackage *package) {
// put up a progress bar.
make_splash_window();
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_progress(0.0, true, 0);
if (package == _certlist_package) {
_splash_window->set_install_label("Getting Certificates");
} else {
@ -2493,7 +2499,7 @@ report_package_info_ready(P3DPackage *package) {
}
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_progress(0.0, true, 0);
}
_panda_script_object->set_string_property("status", "downloading");
_panda_script_object->set_int_property("numDownloadingPackages", _downloading_packages.size());
@ -2573,7 +2579,7 @@ mark_download_complete() {
// Take down the download progress bar.
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_progress(0.0, true, 0);
_splash_window->set_install_label("");
}
@ -2616,7 +2622,8 @@ ready_to_start() {
// Description: Notified as the instance file is downloaded.
////////////////////////////////////////////////////////////////////
void P3DInstance::
report_instance_progress(double progress) {
report_instance_progress(double progress, bool is_progress_known,
size_t received_data) {
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
@ -2642,7 +2649,7 @@ report_instance_progress(double progress) {
}
if (_splash_window != NULL && _show_dl_instance_progress) {
_splash_window->set_install_progress(progress);
_splash_window->set_install_progress(progress, is_progress_known, received_data);
}
_panda_script_object->set_float_property("instanceDownloadProgress", progress);
}
@ -2662,7 +2669,7 @@ report_package_progress(P3DPackage *package, double progress) {
if (package == _certlist_package || package == _p3dcert_package) {
// This gets its own progress bar.
if (_splash_window != NULL) {
_splash_window->set_install_progress(progress);
_splash_window->set_install_progress(progress, true, 0);
}
return;
}
@ -2679,7 +2686,7 @@ report_package_progress(P3DPackage *package, double progress) {
progress = min(progress, 1.0);
if (_splash_window != NULL) {
_splash_window->set_install_progress(progress);
_splash_window->set_install_progress(progress, true, 0);
}
_panda_script_object->set_float_property("downloadProgress", progress);
@ -2754,7 +2761,7 @@ report_package_done(P3DPackage *package, bool success) {
// Take down the download progress.
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_progress(0.0, true, 0);
_splash_window->set_install_label("");
}
@ -2770,7 +2777,7 @@ report_package_done(P3DPackage *package, bool success) {
// Take down the download progress.
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_progress(0.0, true, 0);
_splash_window->set_install_label("");
}
@ -3143,7 +3150,7 @@ InstanceDownload(P3DInstance *inst) :
void P3DInstance::InstanceDownload::
download_progress() {
P3DFileDownload::download_progress();
_inst->report_instance_progress(get_download_progress());
_inst->report_instance_progress(get_download_progress(), is_download_progress_known(), get_total_data());
}
////////////////////////////////////////////////////////////////////
@ -3159,6 +3166,7 @@ download_finished(bool success) {
P3DFileDownload::download_finished(success);
if (success) {
// We've successfully downloaded the instance data.
_inst->report_instance_progress(1.0, true, 0);
_inst->priv_set_p3d_filename(get_filename());
} else {
// Oops, no joy on the instance data.

View File

@ -187,9 +187,10 @@ private:
void start_next_download();
void mark_download_complete();
void ready_to_start();
void report_instance_progress(double progress);
void report_instance_progress(double progress, bool is_progress_known,
size_t received_data);
void report_package_progress(P3DPackage *package, double progress);
void report_package_done(P3DPackage *package, bool progress);
void report_package_done(P3DPackage *package, bool success);
void set_install_label(const string &install_label);
void paint_window();

View File

@ -185,12 +185,25 @@ set_install_label(const string &install_label) {
// Description: Moves the install progress bar from 0.0 to 1.0.
////////////////////////////////////////////////////////////////////
void P3DOsxSplashWindow::
set_install_progress(double install_progress) {
if ((int)(install_progress * 500.0) != (int)(_install_progress * 500.0)) {
// Only request a refresh if we're changing substantially.
set_install_progress(double install_progress,
bool is_progress_known, size_t received_data) {
// Only request a refresh if we're changing substantially.
if (is_progress_known != _progress_known) {
refresh();
} else if (_progress_known) {
if ((int)(install_progress * 500.0) != (int)(_install_progress * 500.0)) {
refresh();
}
} else {
if ((int)(received_data * _unknown_progress_rate) !=
(int)(_received_data * _unknown_progress_rate)) {
refresh();
}
}
_install_progress = install_progress;
_progress_known = is_progress_known;
_received_data = received_data;
}
////////////////////////////////////////////////////////////////////
@ -343,8 +356,14 @@ paint_window() {
// Draw the progress bar. We don't draw this bar at all unless we
// have nonzero progress.
if (_install_progress != 0.0) {
paint_progress_bar(context);
if (_progress_known) {
if (_install_progress != 0.0) {
paint_progress_bar(context);
}
} else {
if (_received_data != 0) {
paint_progress_bar(context);
}
}
CGContextSynchronize(context);
@ -507,9 +526,27 @@ paint_progress_bar(CGContextRef context) {
CGContextFillPath(context);
// Draw the interior of the progress bar in blue (or the bar color).
int progress_width = (int)((bar_width - 2) * _install_progress);
if (progress_width != 0) {
CGRect prog = { { bar_xf, bar_yf }, { progress_width, bar_height } };
if (_progress_known) {
int progress_width = (int)(bar_width * _install_progress + 0.5);
if (progress_width != 0) {
CGRect prog = { { bar_xf, bar_yf }, { progress_width, bar_height } };
CGContextBeginPath(context);
CGContextSetFillColorWithColor(context, bar);
CGContextAddRect(context, prog);
CGContextFillPath(context);
}
} else {
// Progress is unknown. Draw a moving block, not a progress bar
// filling up.
int block_width = (int)(bar_width * 0.1 + 0.5);
int block_travel = bar_width - block_width;
int progress = (int)(_received_data * _unknown_progress_rate);
progress = progress % (block_travel * 2);
if (progress > block_travel) {
progress = block_travel * 2 - progress;
}
CGRect prog = { { bar_xf + progress, bar_yf }, { block_width, bar_height } };
CGContextBeginPath(context);
CGContextSetFillColorWithColor(context, bar);
CGContextAddRect(context, prog);

View File

@ -38,7 +38,8 @@ public:
virtual void set_image_filename(const string &image_filename,
ImagePlacement image_placement);
virtual void set_install_label(const string &install_label);
virtual void set_install_progress(double install_progress);
virtual void set_install_progress(double install_progress,
bool is_progress_known, size_t received_data);
virtual bool handle_event(const P3D_event_data &event);
@ -81,6 +82,8 @@ private:
string _install_label;
double _install_progress;
bool _progress_known;
size_t _received_data;
// Used to track the mouse within the window in the embedded case.
bool _mouse_active;

View File

@ -39,7 +39,9 @@ METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
longjmp(myerr->setjmp_buffer, 1);
}
// The number of pixels to move the block per byte downloaded, when we
// don't know the actual file size we're downloading.
const double P3DSplashWindow::_unknown_progress_rate = 1.0 / 4096;
////////////////////////////////////////////////////////////////////
// Function: P3DSplashWindow::Constructor
@ -192,7 +194,8 @@ set_install_label(const string &install_label) {
// Description: Moves the install progress bar from 0.0 to 1.0.
////////////////////////////////////////////////////////////////////
void P3DSplashWindow::
set_install_progress(double install_progress) {
set_install_progress(double install_progress,
bool is_progress_known, size_t received_data) {
}
////////////////////////////////////////////////////////////////////

View File

@ -58,7 +58,8 @@ public:
virtual void set_bgcolor(int r, int g, int b);
virtual void set_barcolor(int r, int g, int b);
virtual void set_install_label(const string &install_label);
virtual void set_install_progress(double install_progress);
virtual void set_install_progress(double install_progress,
bool is_progress_known, size_t received_data);
virtual bool handle_event(const P3D_event_data &event);
@ -120,6 +121,8 @@ protected:
bool _mouse_down;
bool _button_depressed;
ButtonState _bstate;
static const double _unknown_progress_rate;
};
#include "p3dSplashWindow.I"

View File

@ -176,7 +176,8 @@ set_install_label(const string &install_label) {
// Description: Moves the install progress bar from 0.0 to 1.0.
////////////////////////////////////////////////////////////////////
void P3DWinSplashWindow::
set_install_progress(double install_progress) {
set_install_progress(double install_progress,
bool is_progress_known, size_t received_data) {
ACQUIRE_LOCK(_install_lock);
_install_progress = install_progress;
RELEASE_LOCK(_install_lock);
@ -776,7 +777,7 @@ paint_progress_bar(HDC dc) {
FillRect(dc, &bar_rect, _bg_brush);
// Draw the interior of the progress bar in blue (or the bar color).
int progress_width = (int)((bar_width - 2) * _drawn_progress);
int progress_width = (int)((bar_width - 2) * _drawn_progress + 0.5);
if (progress_width != 0) {
RECT prog_rect = { bar_x, bar_y, bar_x + progress_width, bar_y + bar_height };
FillRect(dc, &prog_rect, _bar_brush);

View File

@ -40,7 +40,8 @@ public:
virtual void set_image_filename(const string &image_filename,
ImagePlacement image_placement);
virtual void set_install_label(const string &install_label);
virtual void set_install_progress(double install_progress);
virtual void set_install_progress(double install_progress,
bool is_progress_known, size_t received_data);
virtual void request_keyboard_focus();
static void register_window_class();

View File

@ -156,7 +156,8 @@ set_install_label(const string &install_label) {
// Description: Moves the install progress bar from 0.0 to 1.0.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
set_install_progress(double install_progress) {
set_install_progress(double install_progress,
bool is_progress_known, size_t received_data) {
if (_subprocess_pid == -1) {
return;
}
@ -611,7 +612,7 @@ subprocess_run() {
}
if (needs_update_progress) {
int progress_width = (int)((bar_width - 2) * _install_progress);
int progress_width = (int)((bar_width - 2) * _install_progress + 0.5);
XFillRectangle(_display, _window, _bar_context,
bar_x + 1, bar_y + 1,
progress_width + 1, bar_height - 1);

View File

@ -42,7 +42,8 @@ public:
virtual void set_image_filename(const string &image_filename,
ImagePlacement image_placement);
virtual void set_install_label(const string &install_label);
virtual void set_install_progress(double install_progress);
virtual void set_install_progress(double install_progress,
bool is_progress_known, size_t received_data);
virtual void set_button_active(bool flag);

View File

@ -434,7 +434,7 @@ NPP_WriteReady_x(NPP instance, NPStream *stream) {
int32_t
NPP_Write_x(NPP instance, NPStream *stream, int32_t offset,
int32_t len, void *buffer) {
// nout << "Write " << stream->url << ", " << len << " for " << instance << ", " << (PPInstance *)(instance->pdata) << "\n";
// nout << "Write " << stream->url << ", " << offset << ", " << len << " for " << instance << ", " << (PPInstance *)(instance->pdata) << "\n";
PPInstance::generic_browser_call();
PPInstance *inst = (PPInstance *)(instance->pdata);
assert(inst != NULL);