diff --git a/direct/src/plugin/load_plugin.cxx b/direct/src/plugin/load_plugin.cxx index 48f93c93ab..221aee2434 100755 --- a/direct/src/plugin/load_plugin.cxx +++ b/direct/src/plugin/load_plugin.cxx @@ -40,6 +40,7 @@ P3D_set_plugin_version_func *P3D_set_plugin_version; P3D_set_super_mirror_func *P3D_set_super_mirror; P3D_new_instance_func *P3D_new_instance; P3D_instance_start_func *P3D_instance_start; +P3D_instance_start_stream_func *P3D_instance_start_stream; P3D_instance_finish_func *P3D_instance_finish; P3D_instance_setup_window_func *P3D_instance_setup_window; @@ -193,6 +194,7 @@ load_plugin(const string &p3d_plugin_filename, P3D_set_super_mirror = (P3D_set_super_mirror_func *)get_func(module, "P3D_set_super_mirror"); P3D_new_instance = (P3D_new_instance_func *)get_func(module, "P3D_new_instance"); P3D_instance_start = (P3D_instance_start_func *)get_func(module, "P3D_instance_start"); + P3D_instance_start_stream = (P3D_instance_start_stream_func *)get_func(module, "P3D_instance_start_stream"); P3D_instance_finish = (P3D_instance_finish_func *)get_func(module, "P3D_instance_finish"); P3D_instance_setup_window = (P3D_instance_setup_window_func *)get_func(module, "P3D_instance_setup_window"); @@ -234,6 +236,7 @@ load_plugin(const string &p3d_plugin_filename, P3D_set_super_mirror == NULL || P3D_new_instance == NULL || P3D_instance_start == NULL || + P3D_instance_start_stream == NULL || P3D_instance_finish == NULL || P3D_instance_setup_window == NULL || @@ -275,6 +278,7 @@ load_plugin(const string &p3d_plugin_filename, << "\nP3D_set_super_mirror = " << P3D_set_super_mirror << "\nP3D_new_instance = " << P3D_new_instance << "\nP3D_instance_start = " << P3D_instance_start + << "\nP3D_instance_start_stream = " << P3D_instance_start_stream << "\nP3D_instance_finish = " << P3D_instance_finish << "\nP3D_instance_setup_window = " << P3D_instance_setup_window @@ -371,6 +375,7 @@ unload_dso() { P3D_set_super_mirror = NULL; P3D_new_instance = NULL; P3D_instance_start = NULL; + P3D_instance_start_stream = NULL; P3D_instance_finish = NULL; P3D_instance_setup_window = NULL; diff --git a/direct/src/plugin/load_plugin.h b/direct/src/plugin/load_plugin.h index 0432411029..8368687b82 100755 --- a/direct/src/plugin/load_plugin.h +++ b/direct/src/plugin/load_plugin.h @@ -26,6 +26,7 @@ extern P3D_set_plugin_version_func *P3D_set_plugin_version; extern P3D_set_super_mirror_func *P3D_set_super_mirror; extern P3D_new_instance_func *P3D_new_instance; extern P3D_instance_start_func *P3D_instance_start; +extern P3D_instance_start_stream_func *P3D_instance_start_stream; extern P3D_instance_finish_func *P3D_instance_finish; extern P3D_instance_setup_window_func *P3D_instance_setup_window; diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 8df74f8634..5f48a05348 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -279,7 +279,8 @@ P3DInstance:: // 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. +// set_p3d_filename() or make_p3d_stream(), 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 @@ -315,6 +316,41 @@ set_p3d_url(const string &p3d_url) { start_download(download); } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstance::make_p3d_stream +// Access: Public +// Description: Indicates an intention to transmit the p3d data as a +// stream. Should return a new unique stream ID to +// receive it. +//////////////////////////////////////////////////////////////////// +int P3DInstance:: +make_p3d_stream(const string &p3d_url) { + // Make a temporary file to receive the instance data. + assert(_temp_p3d_filename == NULL); + _temp_p3d_filename = new P3DTemporaryFile(".p3d"); + _stuff_to_download = true; + + // Maybe it's time to open a splash window now. + make_splash_window(); + + // Mark the time we started downloading, so we'll know when to reveal + // the progress bar. +#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(_temp_p3d_filename->get_filename()); + + _panda_script_object->set_string_property("status", "downloading_instance"); + return start_download(download, false); +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstance::set_p3d_filename // Access: Public @@ -908,9 +944,18 @@ get_packages_failed() const { // This increments the P3DDownload object's reference // count, and will decrement it (and possibly delete the // object) after download_finished() has been called. +// +// add_request should be true to actually request the +// URL from the plugin, or false not to. Normally, this +// should always be set true, except in the one special +// case of make_p3d_stream(), in which case the plugin +// is already prepared to send the stream and doesn't +// need to have it requested. +// +// Returns the unique ID of this stream. //////////////////////////////////////////////////////////////////// -void P3DInstance:: -start_download(P3DDownload *download) { +int P3DInstance:: +start_download(P3DDownload *download, bool add_request) { assert(download->get_download_id() == 0); assert(!download->get_url().empty()); @@ -923,12 +968,16 @@ start_download(P3DDownload *download) { bool inserted = _downloads.insert(Downloads::value_type(download_id, download)).second; assert(inserted); - P3D_request *request = new P3D_request; - request->_request_type = P3D_RT_get_url; - request->_request._get_url._url = strdup(download->get_url().c_str()); - request->_request._get_url._unique_id = download_id; + if (add_request) { + P3D_request *request = new P3D_request; + request->_request_type = P3D_RT_get_url; + request->_request._get_url._url = strdup(download->get_url().c_str()); + request->_request._get_url._unique_id = download_id; + + add_baked_request(request); + } - add_baked_request(request); + return download_id; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index db171f2a20..eda85114e5 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -59,6 +59,7 @@ public: void set_p3d_url(const string &p3d_url); void set_p3d_filename(const string &p3d_filename); + int make_p3d_stream(const string &p3d_url); inline const P3DFileParams &get_fparams() const; void set_wparams(const P3DWindowParams &wparams); @@ -97,7 +98,7 @@ public: bool get_packages_failed() const; inline bool is_trusted() const; - void start_download(P3DDownload *download); + int start_download(P3DDownload *download, bool add_request = true); inline bool is_started() const; inline bool is_failed() const; void request_stop_sub_thread(); diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index 31637d2742..51532dd581 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -425,6 +425,22 @@ set_p3d_filename(P3DInstance *inst, bool is_local, return true; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::make_p3d_stream +// Access: Public +// Description: Indicates an intention to transmit the p3d data as a +// stream. Should return a new unique stream ID to +// receive it. +//////////////////////////////////////////////////////////////////// +int P3DInstanceManager:: +make_p3d_stream(P3DInstance *inst, const string &p3d_url) { + if (inst->is_started()) { + nout << "Instance started twice: " << inst << "\n"; + return -1; + } + return inst->make_p3d_stream(p3d_url); +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::start_instance diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index f3ec327a8e..d58346acf3 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -92,6 +92,7 @@ public: bool set_p3d_filename(P3DInstance *inst, bool is_local, const string &p3d_filename); + int make_p3d_stream(P3DInstance *inst, const string &p3d_url); bool start_instance(P3DInstance *inst); void finish_instance(P3DInstance *inst); P3DAuthSession *authorize_instance(P3DInstance *inst); diff --git a/direct/src/plugin/p3d_plugin.cxx b/direct/src/plugin/p3d_plugin.cxx index 9e34e4739b..8829f5638e 100644 --- a/direct/src/plugin/p3d_plugin.cxx +++ b/direct/src/plugin/p3d_plugin.cxx @@ -151,6 +151,23 @@ P3D_instance_start(P3D_instance *instance, bool is_local, return result; } +int +P3D_instance_start_stream(P3D_instance *instance, const char *p3d_url) { + assert(P3DInstanceManager::get_global_ptr()->is_initialized()); + if (p3d_url == NULL) { + p3d_url = ""; + } + ACQUIRE_LOCK(_api_lock); + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + P3DInstance *inst = inst_mgr->validate_instance(instance); + int result = -1; + if (inst != NULL) { + result = inst_mgr->make_p3d_stream(inst, p3d_url); + } + RELEASE_LOCK(_api_lock); + return result; +} + void P3D_instance_finish(P3D_instance *instance) { assert(P3DInstanceManager::get_global_ptr()->is_initialized()); diff --git a/direct/src/plugin/p3d_plugin.h b/direct/src/plugin/p3d_plugin.h index f573430abc..5f0484a4c1 100644 --- a/direct/src/plugin/p3d_plugin.h +++ b/direct/src/plugin/p3d_plugin.h @@ -313,13 +313,28 @@ P3D_new_instance_func(P3D_request_ready_func *func, 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. + should be downloaded to retrieve the p3d file. Also see + P3D_instance_start_stream(), below. The return value is true on success, false on failure. */ typedef bool P3D_instance_start_func(P3D_instance *instance, bool is_local, const char *p3d_filename); +/* This function is an alternative to P3D_instance_start(); it + indicates an intention to feed the p3d file data to the instance as + a stream. The instance should return a unique integer ID for this + stream, as if the instance had requested the stream via a get_url + request (below). The plugin will then send the p3d file data to + the instance via a series of calls to + P3D_instance_feed_url_stream(), using the unique ID returned by + this function. When the stream has been transmitted successfully, + the instance will automatically start. + + The p3d_url string passed to this function is informational only. + The instance will not explicitly request this URL. */ +typedef int +P3D_instance_start_stream_func(P3D_instance *instance, const char *p3d_url); /* Call this function to interrupt a particular instance and stop it from rendering, for instance when the user navigates away from the @@ -890,6 +905,7 @@ EXPCL_P3D_PLUGIN P3D_set_super_mirror_func P3D_set_super_mirror; EXPCL_P3D_PLUGIN P3D_new_instance_func P3D_new_instance; EXPCL_P3D_PLUGIN P3D_instance_start_func P3D_instance_start; +EXPCL_P3D_PLUGIN P3D_instance_start_stream_func P3D_instance_start_stream; EXPCL_P3D_PLUGIN P3D_instance_finish_func P3D_instance_finish; EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window; diff --git a/direct/src/plugin_npapi/ppDownloadRequest.h b/direct/src/plugin_npapi/ppDownloadRequest.h index ee2fb1f515..9b485b9d13 100644 --- a/direct/src/plugin_npapi/ppDownloadRequest.h +++ b/direct/src/plugin_npapi/ppDownloadRequest.h @@ -28,8 +28,7 @@ public: enum RequestType { RT_contents_file, RT_core_dll, - RT_user, - RT_instance_data + RT_user }; inline PPDownloadRequest(RequestType rtype, int user_id = 0); diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 4f43868824..321e8910f9 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -192,19 +192,12 @@ new_stream(NPMIMEType type, NPStream *stream, bool seekable, uint16 *stype) { // stream we receive is the instance data; any other unsolicited // stream is an 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) { + if (!_got_instance_url && stream->url != NULL && _p3d_inst != NULL) { _got_instance_url = true; _instance_url = stream->url; - if (_p3d_inst != NULL) { - P3D_instance_start(_p3d_inst, false, _instance_url.c_str()); - } + int user_id = P3D_instance_start_stream(_p3d_inst, _instance_url.c_str()); - // We don't want the rest of this stream any more, but we can't - // just return NPERR_GENERIC_ERROR, though--that seems to freak - // out Firefox. - stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_instance_data); + stream->notifyData = new PPDownloadRequest(PPDownloadRequest::RT_user, user_id); *stype = NP_NORMAL; return NPERR_NO_ERROR; @@ -263,13 +256,6 @@ write_stream(NPStream *stream, int offset, int len, void *buffer) { P3D_RC_in_progress, 0, stream->end, buffer, len); return len; - - case PPDownloadRequest::RT_instance_data: - // Here's a stream we don't really want. But stopping it here - // seems to freak out Safari. (And stopping it before it starts - // freaks out Firefox.) Whatever. We'll just quietly ignore the - // data. - return len; default: nout << "Unexpected write_stream on " << stream->url << "\n"; @@ -309,9 +295,6 @@ destroy_stream(NPStream *stream, NPReason reason) { } break; - case PPDownloadRequest::RT_instance_data: - break; - default: nout << "Unexpected destroy_stream on " << stream->url << "\n"; break;