mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 17:35:34 -04:00
more download status notifications
This commit is contained in:
parent
4bac1d3314
commit
e0b1994b61
@ -83,6 +83,8 @@ P3DInstance(P3D_request_ready_func *func,
|
||||
|
||||
// Set some initial properties.
|
||||
_panda_script_object->set_float_property("downloadProgress", 0.0);
|
||||
_panda_script_object->set_bool_property("downloadComplete", false);
|
||||
_panda_script_object->set_string_property("status", "initial");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -166,20 +168,8 @@ set_p3d_filename(const string &p3d_filename) {
|
||||
|
||||
// Generate a special notification: onpluginload, indicating the
|
||||
// plugin has read its parameters and is ready to be queried (even
|
||||
// if Python has not yet started). This notification is special
|
||||
// because it generated at the C++ level, here; most of them are
|
||||
// generated by the Python code, once that is running.
|
||||
P3D_request *request = new P3D_request;
|
||||
request->_request_type = P3D_RT_notify;
|
||||
request->_request._notify._message = strdup("onpluginload");
|
||||
add_baked_request(request);
|
||||
|
||||
// Also eval the HTML associated token.
|
||||
string expression = _fparams.lookup_token("onpluginload");
|
||||
if (!expression.empty() && _browser_script_object != NULL) {
|
||||
P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
|
||||
P3D_OBJECT_XDECREF(result);
|
||||
}
|
||||
// if Python has not yet started).
|
||||
send_notify("onpluginload");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -321,6 +311,30 @@ get_request() {
|
||||
P3D_request *request = _baked_requests.front();
|
||||
_baked_requests.pop_front();
|
||||
_request_pending = !_baked_requests.empty();
|
||||
|
||||
if (request != NULL) {
|
||||
if (request->_request_type == P3D_RT_notify) {
|
||||
// Also eval the associated HTML token, if any.
|
||||
string message = request->_request._notify._message;
|
||||
string expression = _fparams.lookup_token(message);
|
||||
if (!expression.empty() && _browser_script_object != NULL) {
|
||||
P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
|
||||
P3D_OBJECT_XDECREF(result);
|
||||
}
|
||||
|
||||
} else if (request->_request_type == P3D_RT_stop) {
|
||||
// We also send an implicit message when Python requests itself
|
||||
// to shutdown.
|
||||
_panda_script_object->set_pyobj(NULL);
|
||||
_panda_script_object->set_string_property("status", "stopped");
|
||||
|
||||
string expression = _fparams.lookup_token("onpythonstop");
|
||||
if (!expression.empty() && _browser_script_object != NULL) {
|
||||
P3D_object *result = P3D_OBJECT_EVAL(_browser_script_object, expression.c_str());
|
||||
P3D_OBJECT_XDECREF(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
@ -720,6 +734,7 @@ make_p3d_request(TiXmlElement *xrequest) {
|
||||
if (strcmp(rtype, "notify") == 0) {
|
||||
const char *message = xrequest->Attribute("message");
|
||||
if (message != NULL) {
|
||||
// A notify message from Python code.
|
||||
request = new P3D_request;
|
||||
request->_request_type = P3D_RT_notify;
|
||||
request->_request._notify._message = strdup(message);
|
||||
@ -816,6 +831,8 @@ handle_notify_request(const string &message) {
|
||||
P3D_OBJECT_DECREF(result);
|
||||
}
|
||||
|
||||
_panda_script_object->set_string_property("status", "running");
|
||||
|
||||
} else if (message == "onwindowopen") {
|
||||
// The process told us that it just succesfully opened its
|
||||
// window. Tear down the splash window.
|
||||
@ -825,6 +842,8 @@ handle_notify_request(const string &message) {
|
||||
_splash_window = NULL;
|
||||
}
|
||||
|
||||
_panda_script_object->set_string_property("status", "open");
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Start a timer to update the frame repeatedly. This seems to be
|
||||
// steadier than waiting for nullEvent.
|
||||
@ -976,6 +995,17 @@ make_splash_window() {
|
||||
start_download(download);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::start_package_download
|
||||
// Access: Private
|
||||
// Description: Notified when the package download begins.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
start_package_download(P3DPackage *package) {
|
||||
_panda_script_object->set_string_property("status", "downloading");
|
||||
send_notify("ondownloadbegin");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::install_progress
|
||||
// Access: Private
|
||||
@ -990,6 +1020,40 @@ install_progress(P3DPackage *package, double progress) {
|
||||
_panda_script_object->set_float_property("downloadProgress", progress);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::package_ready
|
||||
// Access: Private
|
||||
// Description: Notified when the package is fully downloaded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
package_ready(P3DPackage *package, bool success) {
|
||||
if (success) {
|
||||
install_progress(package, 1.0);
|
||||
_panda_script_object->set_bool_property("downloadComplete", true);
|
||||
_panda_script_object->set_string_property("status", "starting");
|
||||
send_notify("ondownloadcomplete");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::send_notify
|
||||
// Access: Private
|
||||
// Description: Generates a synthetic notify message here at the C++
|
||||
// level.
|
||||
//
|
||||
// Most notify messages are generated from within the
|
||||
// Python code, and don't use this method; but a few
|
||||
// have to be sent before Python has started, and those
|
||||
// come through this method.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstance::
|
||||
send_notify(const string &message) {
|
||||
P3D_request *request = new P3D_request;
|
||||
request->_request_type = P3D_RT_notify;
|
||||
request->_request._notify._message = strdup(message.c_str());
|
||||
add_baked_request(request);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DInstance::paint_window
|
||||
// Access: Private
|
||||
|
@ -107,11 +107,15 @@ private:
|
||||
const string &property_name, P3D_object *value,
|
||||
bool needs_response, int unique_id);
|
||||
void make_splash_window();
|
||||
void start_package_download(P3DPackage *package);
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
void package_ready(P3DPackage *package, bool success);
|
||||
|
||||
void paint_window();
|
||||
void add_modifier_flags(unsigned int &swb_flags, int modifiers);
|
||||
|
||||
void send_notify(const string &message);
|
||||
|
||||
#ifdef __APPLE__
|
||||
static void timer_callback(CFRunLoopTimerRef timer, void *info);
|
||||
#endif // __APPLE__
|
||||
|
@ -235,6 +235,7 @@ start_instance(P3DInstance *inst) {
|
||||
_panda3d_callback = new PackageCallback(this);
|
||||
_panda3d->set_callback(_panda3d_callback);
|
||||
}
|
||||
inst->start_package_download(_panda3d);
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,6 +657,33 @@ install_progress(P3DPackage *package, double progress) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::package_ready
|
||||
// Access: Private
|
||||
// Description: Notified when the package is fully downloaded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSession::
|
||||
package_ready(P3DPackage *package, bool success) {
|
||||
_panda3d_callback = NULL;
|
||||
|
||||
Instances::iterator ii;
|
||||
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
|
||||
P3DInstance *inst = (*ii).second;
|
||||
inst->package_ready(package, success);
|
||||
}
|
||||
|
||||
if (package == _panda3d) {
|
||||
if (success) {
|
||||
start_p3dpython();
|
||||
} else {
|
||||
nout << "Failed to install " << package->get_package_name()
|
||||
<< "_" << package->get_package_version() << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected panda3d package: " << package << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::start_p3dpython
|
||||
// Access: Private
|
||||
@ -1092,30 +1120,6 @@ PackageCallback(P3DSession *session) :
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::PackageCallback::package_ready
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSession::PackageCallback::
|
||||
package_ready(P3DPackage *package, bool success) {
|
||||
if (this == _session->_panda3d_callback) {
|
||||
_session->_panda3d_callback = NULL;
|
||||
if (package == _session->_panda3d) {
|
||||
if (success) {
|
||||
_session->start_p3dpython();
|
||||
} else {
|
||||
nout << "Failed to install " << package->get_package_name()
|
||||
<< "_" << package->get_package_version() << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected panda3d package: " << package << "\n";
|
||||
}
|
||||
} else {
|
||||
nout << "Unexpected callback for P3DSession\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::PackageCallback::install_progress
|
||||
// Access: Public, Virtual
|
||||
@ -1126,5 +1130,21 @@ void P3DSession::PackageCallback::
|
||||
install_progress(P3DPackage *package, double progress) {
|
||||
if (this == _session->_panda3d_callback) {
|
||||
_session->install_progress(package, progress);
|
||||
} else {
|
||||
nout << "Unexpected callback for P3DSession\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: P3DSession::PackageCallback::package_ready
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DSession::PackageCallback::
|
||||
package_ready(P3DPackage *package, bool success) {
|
||||
if (this == _session->_panda3d_callback) {
|
||||
_session->package_ready(package, success);
|
||||
} else {
|
||||
nout << "Unexpected callback for P3DSession\n";
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
|
||||
private:
|
||||
void install_progress(P3DPackage *package, double progress);
|
||||
void package_ready(P3DPackage *package, bool success);
|
||||
void start_p3dpython();
|
||||
|
||||
void spawn_read_thread();
|
||||
|
@ -34,7 +34,7 @@ P3DToplevelObject::
|
||||
~P3DToplevelObject() {
|
||||
set_pyobj(NULL);
|
||||
|
||||
// Just in case there are properties we haven't cleared yet.
|
||||
// Clear the local properties.
|
||||
Properties::const_iterator pi;
|
||||
for (pi = _properties.begin(); pi != _properties.end(); ++pi) {
|
||||
P3D_object *value = (*pi).second;
|
||||
@ -139,32 +139,34 @@ get_property(const string &property) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool P3DToplevelObject::
|
||||
set_property(const string &property, P3D_object *value) {
|
||||
if (_pyobj == NULL) {
|
||||
// Without a pyobj, we just store the value locally.
|
||||
if (value != NULL) {
|
||||
Properties::iterator pi;
|
||||
pi = _properties.insert(Properties::value_type(property, NULL)).first;
|
||||
assert(pi != _properties.end());
|
||||
P3D_object *orig_value = (*pi).second;
|
||||
if (orig_value != value) {
|
||||
P3D_OBJECT_XDECREF(orig_value);
|
||||
(*pi).second = value;
|
||||
P3D_OBJECT_INCREF(value);
|
||||
}
|
||||
} else {
|
||||
// Or delete the property locally.
|
||||
Properties::iterator pi;
|
||||
pi = _properties.find(property);
|
||||
if (pi != _properties.end()) {
|
||||
P3D_object *orig_value = (*pi).second;
|
||||
P3D_OBJECT_DECREF(orig_value);
|
||||
_properties.erase(pi);
|
||||
}
|
||||
// First, we set the property locally.
|
||||
if (value != NULL) {
|
||||
Properties::iterator pi;
|
||||
pi = _properties.insert(Properties::value_type(property, NULL)).first;
|
||||
assert(pi != _properties.end());
|
||||
P3D_object *orig_value = (*pi).second;
|
||||
if (orig_value != value) {
|
||||
P3D_OBJECT_XDECREF(orig_value);
|
||||
(*pi).second = value;
|
||||
P3D_OBJECT_INCREF(value);
|
||||
}
|
||||
} else {
|
||||
// (Or delete the property locally.)
|
||||
Properties::iterator pi;
|
||||
pi = _properties.find(property);
|
||||
if (pi != _properties.end()) {
|
||||
P3D_object *orig_value = (*pi).second;
|
||||
P3D_OBJECT_DECREF(orig_value);
|
||||
_properties.erase(pi);
|
||||
}
|
||||
}
|
||||
|
||||
if (_pyobj == NULL) {
|
||||
// Without a pyobj, that's all we do.
|
||||
return true;
|
||||
}
|
||||
|
||||
// With a pyobj, we pass this request down.
|
||||
// With a pyobj, we also pass this request down.
|
||||
return P3D_OBJECT_SET_PROPERTY(_pyobj, property.c_str(), value);
|
||||
}
|
||||
|
||||
@ -246,9 +248,7 @@ set_pyobj(P3D_object *pyobj) {
|
||||
const string &property_name = (*pi).first;
|
||||
P3D_object *value = (*pi).second;
|
||||
P3D_OBJECT_SET_PROPERTY(_pyobj, property_name.c_str(), value);
|
||||
P3D_OBJECT_DECREF(value);
|
||||
}
|
||||
_properties.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
|
||||
#define LOCK _lock
|
||||
#define INIT_LOCK(lock) { InitializeCriticalSection(&(lock)._l); (lock)._count = 0; }
|
||||
#define ACQUIRE_LOCK(lock) { EnterCriticalSection(&(lock)._l); ++((lock)._count); if ((lock)._count > 1) { nout << "count = " << (lock)._count << "\n"; } }
|
||||
#define ACQUIRE_LOCK(lock) { EnterCriticalSection(&(lock)._l); ++((lock)._count); }
|
||||
#define RELEASE_LOCK(lock) { --((lock)._count); LeaveCriticalSection(&(lock)._l); }
|
||||
#define DESTROY_LOCK(lock) DeleteCriticalSection(&(lock)._l)
|
||||
|
||||
|
@ -70,13 +70,8 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16 mode,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PPInstance::
|
||||
~PPInstance() {
|
||||
#ifdef _WIN32
|
||||
if (_got_window) {
|
||||
// Restore the parent window to its own window handler.
|
||||
HWND hwnd = (HWND)_window.window;
|
||||
SetWindowLongPtr(hwnd, GWL_WNDPROC, _orig_window_proc);
|
||||
}
|
||||
#endif // _WIN32
|
||||
nout << "Destructing PPInstance\n";
|
||||
cleanup_window();
|
||||
|
||||
if (_p3d_inst != NULL) {
|
||||
P3D_instance_finish(_p3d_inst);
|
||||
@ -421,6 +416,7 @@ handle_request(P3D_request *request) {
|
||||
P3D_instance_finish(_p3d_inst);
|
||||
_p3d_inst = NULL;
|
||||
}
|
||||
cleanup_window();
|
||||
// Guess the browser doesn't really care.
|
||||
handled = true;
|
||||
break;
|
||||
@ -1074,9 +1070,29 @@ send_window() {
|
||||
parent_window);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::cleanup_window
|
||||
// Access: Private
|
||||
// Description: Called at instance shutdown, this restores the parent
|
||||
// window to its original state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PPInstance::
|
||||
cleanup_window() {
|
||||
if (_got_window) {
|
||||
#ifdef _WIN32
|
||||
// Restore the parent window to its own window handler.
|
||||
HWND hwnd = (HWND)_window.window;
|
||||
SetWindowLongPtr(hwnd, GWL_WNDPROC, _orig_window_proc);
|
||||
nout << "Restored window handler for " << hwnd << "\n";
|
||||
InvalidateRect(hwnd, NULL, true);
|
||||
#endif // _WIN32
|
||||
_got_window = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPInstance::copy_file
|
||||
// Access: Public
|
||||
// Access: Private
|
||||
// Description: Copies the data in the file named by from_filename
|
||||
// into the file named by to_filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -78,6 +78,7 @@ private:
|
||||
|
||||
void create_instance();
|
||||
void send_window();
|
||||
void cleanup_window();
|
||||
bool copy_file(const string &from_filename, const string &to_filename);
|
||||
|
||||
static void handle_request_loop();
|
||||
|
@ -78,6 +78,9 @@ for opt, arg in opts:
|
||||
freezer.handleCustomPath(module)
|
||||
elif opt == '-h':
|
||||
usage(0)
|
||||
else:
|
||||
print 'illegal option: ' + flag
|
||||
sys.exit(1)
|
||||
|
||||
if not args:
|
||||
usage(0)
|
||||
|
@ -372,20 +372,14 @@ class AppRunner(DirectObject):
|
||||
|
||||
def notifyRequest(self, message):
|
||||
""" Delivers a notify request to the browser. This is a "this
|
||||
happened" type notification; it optionally triggers some
|
||||
JavaScript code execution, and may also trigger some internal
|
||||
automatic actions. (For instance, the plugin takes down the
|
||||
splash window when it sees the onwindowopen notification. """
|
||||
happened" type notification; it also triggers some JavaScript
|
||||
code execution, if indicated in the HTML tags, and may also
|
||||
trigger some internal automatic actions. (For instance, the
|
||||
plugin takes down the splash window when it sees the
|
||||
onwindowopen notification. """
|
||||
|
||||
self.sendRequest('notify', message)
|
||||
|
||||
# Now process any JavaScript that might be waiting for the
|
||||
# event as well. These are the JavaScript expressions that
|
||||
# were specified in the HTML embed or object tag.
|
||||
expression = self.tokenDict.get(message)
|
||||
if expression:
|
||||
self.evalScript(expression)
|
||||
|
||||
def evalScript(self, expression, needsResponse = False):
|
||||
""" Evaluates an arbitrary JavaScript expression in the global
|
||||
DOM space. This may be deferred if necessary if needsResponse
|
||||
|
Loading…
x
Reference in New Issue
Block a user