diff --git a/direct/src/plugin/p3dDownload.I b/direct/src/plugin/p3dDownload.I index 9be17824f4..812b6e862f 100755 --- a/direct/src/plugin/p3dDownload.I +++ b/direct/src/plugin/p3dDownload.I @@ -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 diff --git a/direct/src/plugin/p3dDownload.cxx b/direct/src/plugin/p3dDownload.cxx index 293f26cbe7..9dd20e6f93 100755 --- a/direct/src/plugin/p3dDownload.cxx +++ b/direct/src/plugin/p3dDownload.cxx @@ -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 ©) : _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"; } diff --git a/direct/src/plugin/p3dDownload.h b/direct/src/plugin/p3dDownload.h index ba89fc8956..0dd2494a1f 100755 --- a/direct/src/plugin/p3dDownload.h +++ b/direct/src/plugin/p3dDownload.h @@ -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; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 41c089b136..e9776f372e 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -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. diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index e710172349..a0ae90b236 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -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(); diff --git a/direct/src/plugin/p3dOsxSplashWindow.cxx b/direct/src/plugin/p3dOsxSplashWindow.cxx index 5583aa2e7a..3ce82dd98b 100644 --- a/direct/src/plugin/p3dOsxSplashWindow.cxx +++ b/direct/src/plugin/p3dOsxSplashWindow.cxx @@ -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,15 +526,33 @@ 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); CGContextFillPath(context); } - + // Draw the black stroke around the progress bar. CGContextBeginPath(context); CGContextSetLineWidth(context, 1); diff --git a/direct/src/plugin/p3dOsxSplashWindow.h b/direct/src/plugin/p3dOsxSplashWindow.h index a8ab0eeb1a..6523798dc9 100644 --- a/direct/src/plugin/p3dOsxSplashWindow.h +++ b/direct/src/plugin/p3dOsxSplashWindow.h @@ -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; diff --git a/direct/src/plugin/p3dSplashWindow.cxx b/direct/src/plugin/p3dSplashWindow.cxx index 933e037c31..7114103f96 100755 --- a/direct/src/plugin/p3dSplashWindow.cxx +++ b/direct/src/plugin/p3dSplashWindow.cxx @@ -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) { } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dSplashWindow.h b/direct/src/plugin/p3dSplashWindow.h index 8b609441ff..9b41386b85 100755 --- a/direct/src/plugin/p3dSplashWindow.h +++ b/direct/src/plugin/p3dSplashWindow.h @@ -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" diff --git a/direct/src/plugin/p3dWinSplashWindow.cxx b/direct/src/plugin/p3dWinSplashWindow.cxx index 9f4af62bda..672d174c2b 100755 --- a/direct/src/plugin/p3dWinSplashWindow.cxx +++ b/direct/src/plugin/p3dWinSplashWindow.cxx @@ -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); diff --git a/direct/src/plugin/p3dWinSplashWindow.h b/direct/src/plugin/p3dWinSplashWindow.h index add0eccc21..7af10732dc 100755 --- a/direct/src/plugin/p3dWinSplashWindow.h +++ b/direct/src/plugin/p3dWinSplashWindow.h @@ -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(); diff --git a/direct/src/plugin/p3dX11SplashWindow.cxx b/direct/src/plugin/p3dX11SplashWindow.cxx index 113ff89b37..3d5ae4462c 100755 --- a/direct/src/plugin/p3dX11SplashWindow.cxx +++ b/direct/src/plugin/p3dX11SplashWindow.cxx @@ -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); diff --git a/direct/src/plugin/p3dX11SplashWindow.h b/direct/src/plugin/p3dX11SplashWindow.h index 7f9b97f65d..444c47b64c 100755 --- a/direct/src/plugin/p3dX11SplashWindow.h +++ b/direct/src/plugin/p3dX11SplashWindow.h @@ -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); diff --git a/direct/src/plugin_npapi/startup.cxx b/direct/src/plugin_npapi/startup.cxx index 42fb98cd7a..d61762d249 100644 --- a/direct/src/plugin_npapi/startup.cxx +++ b/direct/src/plugin_npapi/startup.cxx @@ -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);