mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
attempts to make windows plugin more stable
This commit is contained in:
parent
850773c4eb
commit
d5b4f7810e
@ -22,8 +22,9 @@
|
|||||||
fileSpec.cxx fileSpec.h fileSpec.I \
|
fileSpec.cxx fileSpec.h fileSpec.I \
|
||||||
find_root_dir.cxx find_root_dir.h \
|
find_root_dir.cxx find_root_dir.h \
|
||||||
get_tinyxml.h \
|
get_tinyxml.h \
|
||||||
|
binaryXml.cxx binaryXml.h \
|
||||||
handleStream.cxx handleStream.h handleStream.I \
|
handleStream.cxx handleStream.h handleStream.I \
|
||||||
handleStreamBuf.cxx handleStreamBuf.h \
|
handleStreamBuf.cxx handleStreamBuf.h handleStreamBuf.I \
|
||||||
mkdir_complete.cxx mkdir_complete.h \
|
mkdir_complete.cxx mkdir_complete.h \
|
||||||
p3d_lock.h p3d_plugin.h \
|
p3d_lock.h p3d_plugin.h \
|
||||||
p3d_plugin_config.h \
|
p3d_plugin_config.h \
|
||||||
@ -98,14 +99,17 @@
|
|||||||
pipeline:c event:c nativenet:c panda:m
|
pipeline:c event:c nativenet:c panda:m
|
||||||
|
|
||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
|
binaryXml.cxx binaryXml.h \
|
||||||
handleStream.cxx handleStream.h handleStream.I \
|
handleStream.cxx handleStream.h handleStream.I \
|
||||||
handleStreamBuf.cxx handleStreamBuf.h \
|
handleStreamBuf.cxx handleStreamBuf.h handleStreamBuf.I \
|
||||||
p3d_lock.h p3d_plugin.h \
|
p3d_lock.h p3d_plugin.h \
|
||||||
p3d_plugin_config.h \
|
p3d_plugin_config.h \
|
||||||
p3dCInstance.cxx \
|
p3dCInstance.cxx \
|
||||||
p3dCInstance.h p3dCInstance.I \
|
p3dCInstance.h p3dCInstance.I \
|
||||||
p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I
|
p3dPythonRun.cxx p3dPythonRun.h p3dPythonRun.I
|
||||||
|
|
||||||
|
#define WIN_SYS_LIBS user32.lib
|
||||||
|
|
||||||
#end bin_target
|
#end bin_target
|
||||||
|
|
||||||
#begin static_lib_target
|
#begin static_lib_target
|
||||||
|
142
direct/src/plugin/binaryXml.cxx
Normal file
142
direct/src/plugin/binaryXml.cxx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Filename: binaryXml.cxx
|
||||||
|
// Created by: drose (13Jul09)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "binaryXml.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// Actually, we haven't implemented the binary I/O for XML files yet.
|
||||||
|
// We just map these directly to the classic formatted I/O for now.
|
||||||
|
|
||||||
|
static const bool debug_xml_output = true;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: write_xml
|
||||||
|
// Description: Writes the indicated TinyXml document to the given
|
||||||
|
// stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
write_xml(HandleStream &out, TiXmlDocument *doc, ostream &logfile) {
|
||||||
|
ostringstream strm;
|
||||||
|
strm << *doc;
|
||||||
|
string data = strm.str();
|
||||||
|
|
||||||
|
size_t length = data.length();
|
||||||
|
out.write((char *)&length, sizeof(length));
|
||||||
|
out.write(data.data(), length);
|
||||||
|
out << flush;
|
||||||
|
|
||||||
|
if (debug_xml_output) {
|
||||||
|
logfile << "sent: " << data << "\n" << flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: read_xml
|
||||||
|
// Description: Reads a TinyXml document from the given stream, and
|
||||||
|
// returns it. If the document is not yet available,
|
||||||
|
// blocks until it is, or until there is an error
|
||||||
|
// condition on the input.
|
||||||
|
//
|
||||||
|
// The return value is NULL if there is an error, or the
|
||||||
|
// newly-allocated document if it is successfully read.
|
||||||
|
// If not NULL, the document has been allocated with
|
||||||
|
// new, and should be eventually freed by the caller
|
||||||
|
// with delete.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TiXmlDocument *
|
||||||
|
read_xml(HandleStream &in, ostream &logfile) {
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle = in.get_handle();
|
||||||
|
|
||||||
|
size_t length;
|
||||||
|
DWORD bytes_read = 0;
|
||||||
|
logfile << "ReadFile\n" << flush;
|
||||||
|
BOOL success = ReadFile(handle, &length, sizeof(length), &bytes_read, NULL);
|
||||||
|
logfile << "done ReadFile\n" << flush;
|
||||||
|
if (!success) {
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (error != ERROR_HANDLE_EOF && error != ERROR_BROKEN_PIPE) {
|
||||||
|
logfile << "Error reading " << sizeof(length)
|
||||||
|
<< " bytes, windows error code 0x" << hex
|
||||||
|
<< error << dec << ".\n";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
assert(bytes_read == sizeof(length));
|
||||||
|
|
||||||
|
if (debug_xml_output) {
|
||||||
|
ostringstream logout;
|
||||||
|
logout << "reading " << length << " bytes\n";
|
||||||
|
logfile << logout.str() << flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buffer = new char[length];
|
||||||
|
|
||||||
|
bytes_read = 0;
|
||||||
|
success = ReadFile(handle, buffer, length, &bytes_read, NULL);
|
||||||
|
if (!success) {
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (error != ERROR_HANDLE_EOF && error != ERROR_BROKEN_PIPE) {
|
||||||
|
logfile << "Error reading " << length
|
||||||
|
<< " bytes, windows error code 0x" << hex
|
||||||
|
<< error << dec << ".\n";
|
||||||
|
}
|
||||||
|
delete[] buffer;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
assert(bytes_read == length);
|
||||||
|
|
||||||
|
string data(buffer, length);
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
#else
|
||||||
|
size_t length;
|
||||||
|
in.read((char *)&length, sizeof(length));
|
||||||
|
if (in.gcount() != sizeof(length)) {
|
||||||
|
logfile << "read " << in.gcount() << " bytes instead of " << sizeof(length)
|
||||||
|
<< "\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug_xml_output) {
|
||||||
|
ostringstream logout;
|
||||||
|
logout << "reading " << length << " bytes\n";
|
||||||
|
logfile << logout.str() << flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buffer = new char[length];
|
||||||
|
in.read(buffer, length);
|
||||||
|
if (in.gcount() != length) {
|
||||||
|
delete[] buffer;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
string data(buffer, length);
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
istringstream strm(data);
|
||||||
|
TiXmlDocument *doc = new TiXmlDocument;
|
||||||
|
strm >> *doc;
|
||||||
|
|
||||||
|
if (debug_xml_output) {
|
||||||
|
ostringstream logout;
|
||||||
|
logout << "received: " << *doc << "\n";
|
||||||
|
logfile << logout.str() << flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
32
direct/src/plugin/binaryXml.h
Normal file
32
direct/src/plugin/binaryXml.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Filename: binaryXml.h
|
||||||
|
// Created by: drose (13Jul09)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef BINARYXML_H
|
||||||
|
#define BINARYXML_H
|
||||||
|
|
||||||
|
#include "get_tinyxml.h"
|
||||||
|
#include "handleStream.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// A pair of functions to input and output the TinyXml constructs on
|
||||||
|
// the indicated streams. We could, of course, use the TinyXml output
|
||||||
|
// operators, but this is a smidge more efficient and gives us more
|
||||||
|
// control.
|
||||||
|
|
||||||
|
void write_xml(HandleStream &out, TiXmlDocument *doc, ostream &logfile);
|
||||||
|
TiXmlDocument *read_xml(HandleStream &in, ostream &logfile);
|
||||||
|
|
||||||
|
#endif
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HandleStream::Constructor
|
// Function: HandleStream::Constructor
|
||||||
// Access: Published
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
inline HandleStream::
|
inline HandleStream::
|
||||||
@ -23,7 +23,7 @@ HandleStream() : iostream(&_buf) {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HandleStream::Destructor
|
// Function: HandleStream::Destructor
|
||||||
// Access: Published
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
inline HandleStream::
|
inline HandleStream::
|
||||||
@ -33,7 +33,7 @@ inline HandleStream::
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HandleStream::open_read
|
// Function: HandleStream::open_read
|
||||||
// Access: Published
|
// Access: Public
|
||||||
// Description: Attempts to open the given handle for input. The
|
// Description: Attempts to open the given handle for input. The
|
||||||
// stream may not be simultaneously open for input and
|
// stream may not be simultaneously open for input and
|
||||||
// output.
|
// output.
|
||||||
@ -49,7 +49,7 @@ open_read(FHandle handle) {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HandleStream::open_write
|
// Function: HandleStream::open_write
|
||||||
// Access: Published
|
// Access: Public
|
||||||
// Description: Attempts to open the given handle for output. The
|
// Description: Attempts to open the given handle for output. The
|
||||||
// stream may not be simultaneously open for input and
|
// stream may not be simultaneously open for input and
|
||||||
// output.
|
// output.
|
||||||
@ -65,10 +65,21 @@ open_write(FHandle handle) {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: HandleStream::close
|
// Function: HandleStream::close
|
||||||
// Access: Published
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
inline void HandleStream::
|
inline void HandleStream::
|
||||||
close() {
|
close() {
|
||||||
_buf.close();
|
_buf.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: HandleStream::get_handle
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the handle that was passed to open_read() or
|
||||||
|
// open_write().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline FHandle HandleStream::
|
||||||
|
get_handle() const {
|
||||||
|
return _buf.get_handle();
|
||||||
|
}
|
||||||
|
@ -33,6 +33,8 @@ public:
|
|||||||
inline void open_write(FHandle handle);
|
inline void open_write(FHandle handle);
|
||||||
inline void close();
|
inline void close();
|
||||||
|
|
||||||
|
inline FHandle get_handle() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HandleStreamBuf _buf;
|
HandleStreamBuf _buf;
|
||||||
};
|
};
|
||||||
|
@ -12,3 +12,14 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: HandleStreamBuf::get_handle
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the handle that was passed to open_read() or
|
||||||
|
// open_write().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline FHandle HandleStreamBuf::
|
||||||
|
get_handle() const {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
@ -23,7 +23,6 @@ typedef HANDLE FHandle;
|
|||||||
typedef int FHandle;
|
typedef int FHandle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -43,6 +42,8 @@ public:
|
|||||||
bool is_open_write() const;
|
bool is_open_write() const;
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
inline FHandle get_handle() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int overflow(int c);
|
virtual int overflow(int c);
|
||||||
virtual int sync();
|
virtual int sync();
|
||||||
@ -61,4 +62,6 @@ private:
|
|||||||
char *_buffer;
|
char *_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "handleStreamBuf.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -361,6 +361,7 @@ bake_requests() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DInstance::
|
void P3DInstance::
|
||||||
add_raw_request(TiXmlDocument *doc) {
|
add_raw_request(TiXmlDocument *doc) {
|
||||||
|
nout << "add_raw_request " << this << "\n" << flush;
|
||||||
ACQUIRE_LOCK(_request_lock);
|
ACQUIRE_LOCK(_request_lock);
|
||||||
_raw_requests.push_back(doc);
|
_raw_requests.push_back(doc);
|
||||||
_request_pending = true;
|
_request_pending = true;
|
||||||
@ -374,6 +375,7 @@ add_raw_request(TiXmlDocument *doc) {
|
|||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
inst_mgr->signal_request_ready(this);
|
inst_mgr->signal_request_ready(this);
|
||||||
_session->signal_request_ready(this);
|
_session->signal_request_ready(this);
|
||||||
|
nout << "done add_raw_request " << this << "\n" << flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -640,6 +642,35 @@ request_stop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DInstance::pump_messages
|
||||||
|
// Access: Public
|
||||||
|
// Description: Windows only: pump the message queue on this
|
||||||
|
// instance's parent window, so that any child-window
|
||||||
|
// operations will be able to continue.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void P3DInstance::
|
||||||
|
pump_messages() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (_got_wparams) {
|
||||||
|
HWND hwnd = _wparams.get_parent_window()._hwnd;
|
||||||
|
if (hwnd != NULL) {
|
||||||
|
MSG msg;
|
||||||
|
nout << " peeking " << hwnd << "\n" << flush;
|
||||||
|
|
||||||
|
// It appears to be bad to pump messages for any other
|
||||||
|
// window--Mozilla is apparently not reentrant in this way.
|
||||||
|
if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE | PM_NOYIELD)) {
|
||||||
|
nout << " pumping " << msg.message << "\n" << flush;
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
nout << " done pumping\n" << flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstance::make_xml
|
// Function: P3DInstance::make_xml
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -82,6 +82,7 @@ public:
|
|||||||
void start_download(P3DDownload *download);
|
void start_download(P3DDownload *download);
|
||||||
inline bool is_started() const;
|
inline bool is_started() const;
|
||||||
void request_stop();
|
void request_stop();
|
||||||
|
void pump_messages();
|
||||||
|
|
||||||
TiXmlElement *make_xml();
|
TiXmlElement *make_xml();
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "p3dPythonRun.h"
|
#include "p3dPythonRun.h"
|
||||||
#include "asyncTaskManager.h"
|
#include "asyncTaskManager.h"
|
||||||
|
#include "binaryXml.h"
|
||||||
|
|
||||||
// There is only one P3DPythonRun object in any given process space.
|
// There is only one P3DPythonRun object in any given process space.
|
||||||
// Makes the statics easier to deal with, and we don't need multiple
|
// Makes the statics easier to deal with, and we don't need multiple
|
||||||
@ -299,8 +300,7 @@ handle_command(TiXmlDocument *doc) {
|
|||||||
xresponse->SetAttribute("response_id", want_response_id);
|
xresponse->SetAttribute("response_id", want_response_id);
|
||||||
doc.LinkEndChild(decl);
|
doc.LinkEndChild(decl);
|
||||||
doc.LinkEndChild(xresponse);
|
doc.LinkEndChild(xresponse);
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -473,8 +473,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needs_response) {
|
if (needs_response) {
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,6 +487,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPythonRun::
|
void P3DPythonRun::
|
||||||
check_comm() {
|
check_comm() {
|
||||||
|
nout << ":" << flush;
|
||||||
ACQUIRE_LOCK(_commands_lock);
|
ACQUIRE_LOCK(_commands_lock);
|
||||||
while (!_commands.empty()) {
|
while (!_commands.empty()) {
|
||||||
TiXmlDocument *doc = _commands.front();
|
TiXmlDocument *doc = _commands.front();
|
||||||
@ -532,7 +532,7 @@ task_check_comm(GenericAsyncTask *task, void *user_data) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
TiXmlDocument *P3DPythonRun::
|
TiXmlDocument *P3DPythonRun::
|
||||||
wait_script_response(int response_id) {
|
wait_script_response(int response_id) {
|
||||||
nout << "Waiting script_response " << response_id << "\n";
|
nout << "waiting script_response " << response_id << "\n" << flush;
|
||||||
while (true) {
|
while (true) {
|
||||||
ACQUIRE_LOCK(_commands_lock);
|
ACQUIRE_LOCK(_commands_lock);
|
||||||
|
|
||||||
@ -550,7 +550,7 @@ wait_script_response(int response_id) {
|
|||||||
// This is the response we were waiting for.
|
// This is the response we were waiting for.
|
||||||
_commands.erase(ci);
|
_commands.erase(ci);
|
||||||
RELEASE_LOCK(_commands_lock);
|
RELEASE_LOCK(_commands_lock);
|
||||||
nout << "received script_response: " << *doc << "\n" << flush;
|
nout << "got script_response " << unique_id << "\n" << flush;
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,6 +564,7 @@ wait_script_response(int response_id) {
|
|||||||
// This command will be wanting a response. We'd better
|
// This command will be wanting a response. We'd better
|
||||||
// honor it right away, or we risk deadlock with the browser
|
// honor it right away, or we risk deadlock with the browser
|
||||||
// process and the Python process waiting for each other.
|
// process and the Python process waiting for each other.
|
||||||
|
nout << "honoring response " << want_response_id << "\n" << flush;
|
||||||
_commands.erase(ci);
|
_commands.erase(ci);
|
||||||
RELEASE_LOCK(_commands_lock);
|
RELEASE_LOCK(_commands_lock);
|
||||||
handle_command(doc);
|
handle_command(doc);
|
||||||
@ -580,6 +581,27 @@ wait_script_response(int response_id) {
|
|||||||
|
|
||||||
RELEASE_LOCK(_commands_lock);
|
RELEASE_LOCK(_commands_lock);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Make sure we process the Windows event loop while we're
|
||||||
|
// waiting, or everything that depends on Windows messages will
|
||||||
|
// starve.
|
||||||
|
|
||||||
|
// We appear to be best off with just a single PeekMessage() call
|
||||||
|
// here; the full message pump seems to cause problems.
|
||||||
|
MSG msg;
|
||||||
|
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD);
|
||||||
|
/*
|
||||||
|
if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE | PM_NOYIELD)) {
|
||||||
|
nout << " pumping " << msg.message << "\n" << flush;
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
nout << " done pumping\n" << flush;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
nout << "." << flush;
|
||||||
|
|
||||||
// It hasn't shown up yet. Give the sub-thread a chance to
|
// It hasn't shown up yet. Give the sub-thread a chance to
|
||||||
// process the input and append it to the queue.
|
// process the input and append it to the queue.
|
||||||
Thread::force_yield();
|
Thread::force_yield();
|
||||||
@ -648,8 +670,7 @@ py_request_func(PyObject *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xrequest->SetAttribute("message", message);
|
xrequest->SetAttribute("message", message);
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
|
|
||||||
} else if (strcmp(request_type, "script") == 0) {
|
} else if (strcmp(request_type, "script") == 0) {
|
||||||
// Meddling with a scripting variable on the browser side.
|
// Meddling with a scripting variable on the browser side.
|
||||||
@ -693,8 +714,7 @@ py_request_func(PyObject *args) {
|
|||||||
xrequest->LinkEndChild(xvalue);
|
xrequest->LinkEndChild(xvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
|
|
||||||
} else if (strcmp(request_type, "drop_p3dobj") == 0) {
|
} else if (strcmp(request_type, "drop_p3dobj") == 0) {
|
||||||
// Release a particular P3D_object that we were holding a
|
// Release a particular P3D_object that we were holding a
|
||||||
@ -706,8 +726,7 @@ py_request_func(PyObject *args) {
|
|||||||
nout << "got drop_p3dobj(" << object_id << ")\n" << flush;
|
nout << "got drop_p3dobj(" << object_id << ")\n" << flush;
|
||||||
|
|
||||||
xrequest->SetAttribute("object_id", object_id);
|
xrequest->SetAttribute("object_id", object_id);
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
string message = string("Unsupported request type: ") + string(request_type);
|
string message = string("Unsupported request type: ") + string(request_type);
|
||||||
@ -1150,10 +1169,8 @@ xml_to_pyobj(TiXmlElement *xvalue) {
|
|||||||
void P3DPythonRun::
|
void P3DPythonRun::
|
||||||
rt_thread_run() {
|
rt_thread_run() {
|
||||||
while (_read_thread_continue) {
|
while (_read_thread_continue) {
|
||||||
TiXmlDocument *doc = new TiXmlDocument;
|
TiXmlDocument *doc = read_xml(_pipe_read, nout);
|
||||||
|
if (doc == NULL) {
|
||||||
_pipe_read >> *doc;
|
|
||||||
if (!_pipe_read || _pipe_read.eof()) {
|
|
||||||
// Some error on reading. Abort.
|
// Some error on reading. Abort.
|
||||||
_program_continue = false;
|
_program_continue = false;
|
||||||
return;
|
return;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "p3dIntObject.h"
|
#include "p3dIntObject.h"
|
||||||
#include "p3dFloatObject.h"
|
#include "p3dFloatObject.h"
|
||||||
#include "p3dPythonObject.h"
|
#include "p3dPythonObject.h"
|
||||||
|
#include "binaryXml.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -94,8 +95,7 @@ shutdown() {
|
|||||||
xcommand->SetAttribute("cmd", "exit");
|
xcommand->SetAttribute("cmd", "exit");
|
||||||
doc.LinkEndChild(decl);
|
doc.LinkEndChild(decl);
|
||||||
doc.LinkEndChild(xcommand);
|
doc.LinkEndChild(xcommand);
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
|
|
||||||
// Also close the pipe, to help underscore the point.
|
// Also close the pipe, to help underscore the point.
|
||||||
_pipe_write.close();
|
_pipe_write.close();
|
||||||
@ -226,8 +226,7 @@ void P3DSession::
|
|||||||
send_command(TiXmlDocument *command) {
|
send_command(TiXmlDocument *command) {
|
||||||
if (_p3dpython_running) {
|
if (_p3dpython_running) {
|
||||||
// Python is running. Send the command.
|
// Python is running. Send the command.
|
||||||
nout << "sent: " << *command << "\n" << flush;
|
write_xml(_pipe_write, command, nout);
|
||||||
_pipe_write << *command << flush;
|
|
||||||
delete command;
|
delete command;
|
||||||
} else {
|
} else {
|
||||||
// Python not yet running. Queue up the command instead.
|
// Python not yet running. Queue up the command instead.
|
||||||
@ -265,13 +264,14 @@ command_and_response(TiXmlDocument *command) {
|
|||||||
assert(xcommand != NULL);
|
assert(xcommand != NULL);
|
||||||
xcommand->SetAttribute("want_response_id", response_id);
|
xcommand->SetAttribute("want_response_id", response_id);
|
||||||
|
|
||||||
nout << "sent: " << *command << "\n" << flush;
|
write_xml(_pipe_write, command, nout);
|
||||||
_pipe_write << *command << flush;
|
|
||||||
delete command;
|
delete command;
|
||||||
|
|
||||||
// Now block, waiting for a response to be delivered. We assume
|
// Now block, waiting for a response to be delivered. We assume
|
||||||
// only one thread will be waiting at a time.
|
// only one thread will be waiting at a time.
|
||||||
nout << "waiting for response " << response_id << "\n" << flush;
|
nout << "waiting for response " << response_id << "\n" << flush;
|
||||||
|
int tick_start = GetTickCount();
|
||||||
|
|
||||||
_response_ready.acquire();
|
_response_ready.acquire();
|
||||||
Responses::iterator ri = _responses.find(response_id);
|
Responses::iterator ri = _responses.find(response_id);
|
||||||
while (ri == _responses.end()) {
|
while (ri == _responses.end()) {
|
||||||
@ -296,6 +296,7 @@ command_and_response(TiXmlDocument *command) {
|
|||||||
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
|
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
|
||||||
P3DInstance *inst = (*ii).second;
|
P3DInstance *inst = (*ii).second;
|
||||||
inst->bake_requests();
|
inst->bake_requests();
|
||||||
|
inst->pump_messages();
|
||||||
}
|
}
|
||||||
_response_ready.acquire();
|
_response_ready.acquire();
|
||||||
|
|
||||||
@ -312,9 +313,18 @@ command_and_response(TiXmlDocument *command) {
|
|||||||
// particular, the CreateWindow() call within the subprocess--will
|
// particular, the CreateWindow() call within the subprocess--will
|
||||||
// starve, and we could end up with deadlock.
|
// starve, and we could end up with deadlock.
|
||||||
|
|
||||||
// A single PeekMessage() seems to be sufficient.
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD);
|
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD);
|
||||||
|
/*
|
||||||
|
MSG msg;
|
||||||
|
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) {
|
||||||
|
// nout << " pumping " << msg.message << "\n" << flush;
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
// nout << " done pumping\n" << flush;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
// We wait with a timeout, so we can go back and spin the event
|
// We wait with a timeout, so we can go back and spin the event
|
||||||
@ -529,8 +539,7 @@ drop_pyobj(int object_id) {
|
|||||||
xcommand->SetAttribute("object_id", object_id);
|
xcommand->SetAttribute("object_id", object_id);
|
||||||
doc.LinkEndChild(decl);
|
doc.LinkEndChild(decl);
|
||||||
doc.LinkEndChild(xcommand);
|
doc.LinkEndChild(xcommand);
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc << flush;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,20 +666,16 @@ start_p3dpython() {
|
|||||||
xcommand->SetAttribute("session_id", _session_id);
|
xcommand->SetAttribute("session_id", _session_id);
|
||||||
doc.LinkEndChild(decl);
|
doc.LinkEndChild(decl);
|
||||||
doc.LinkEndChild(xcommand);
|
doc.LinkEndChild(xcommand);
|
||||||
nout << "sent: " << doc << "\n" << flush;
|
write_xml(_pipe_write, &doc, nout);
|
||||||
_pipe_write << doc;
|
|
||||||
|
|
||||||
// Also feed it any commands we may have queued up from before the
|
// Also feed it any commands we may have queued up from before the
|
||||||
// process was started.
|
// process was started.
|
||||||
Commands::iterator ci;
|
Commands::iterator ci;
|
||||||
for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
|
for (ci = _commands.begin(); ci != _commands.end(); ++ci) {
|
||||||
nout << "sent: " << *(*ci) << "\n" << flush;
|
write_xml(_pipe_write, (*ci), nout);
|
||||||
_pipe_write << *(*ci);
|
|
||||||
delete (*ci);
|
delete (*ci);
|
||||||
}
|
}
|
||||||
_commands.clear();
|
_commands.clear();
|
||||||
|
|
||||||
_pipe_write << flush;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -715,10 +720,8 @@ join_read_thread() {
|
|||||||
void P3DSession::
|
void P3DSession::
|
||||||
rt_thread_run() {
|
rt_thread_run() {
|
||||||
while (_read_thread_continue) {
|
while (_read_thread_continue) {
|
||||||
TiXmlDocument *doc = new TiXmlDocument;
|
TiXmlDocument *doc = read_xml(_pipe_read, nout);
|
||||||
|
if (doc == NULL) {
|
||||||
_pipe_read >> *doc;
|
|
||||||
if (!_pipe_read || _pipe_read.eof()) {
|
|
||||||
// Some error on reading. Abort.
|
// Some error on reading. Abort.
|
||||||
rt_terminate();
|
rt_terminate();
|
||||||
return;
|
return;
|
||||||
@ -727,6 +730,8 @@ rt_thread_run() {
|
|||||||
// Successfully read an XML document.
|
// Successfully read an XML document.
|
||||||
rt_handle_request(doc);
|
rt_handle_request(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logfile << "Exiting rt_thread_run in " << this << "\n" << flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -737,6 +742,7 @@ rt_thread_run() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DSession::
|
void P3DSession::
|
||||||
rt_handle_request(TiXmlDocument *doc) {
|
rt_handle_request(TiXmlDocument *doc) {
|
||||||
|
nout << "rt_handle_request in " << this << "\n" << flush;
|
||||||
TiXmlElement *xresponse = doc->FirstChildElement("response");
|
TiXmlElement *xresponse = doc->FirstChildElement("response");
|
||||||
if (xresponse != (TiXmlElement *)NULL) {
|
if (xresponse != (TiXmlElement *)NULL) {
|
||||||
int response_id;
|
int response_id;
|
||||||
@ -748,6 +754,7 @@ rt_handle_request(TiXmlDocument *doc) {
|
|||||||
assert(inserted);
|
assert(inserted);
|
||||||
_response_ready.notify();
|
_response_ready.notify();
|
||||||
_response_ready.release();
|
_response_ready.release();
|
||||||
|
nout << "done a, rt_handle_request in " << this << "\n" << flush;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -772,6 +779,7 @@ rt_handle_request(TiXmlDocument *doc) {
|
|||||||
if (doc != NULL) {
|
if (doc != NULL) {
|
||||||
delete doc;
|
delete doc;
|
||||||
}
|
}
|
||||||
|
nout << "done rt_handle_request in " << this << "\n" << flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -200,7 +200,14 @@ stop_thread() {
|
|||||||
// Post a silly message to spin the message loop.
|
// Post a silly message to spin the message loop.
|
||||||
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
PostThreadMessage(_thread_id, WM_USER, 0, 0);
|
||||||
|
|
||||||
WaitForSingleObject(_thread, INFINITE);
|
// We can't actually wait for the thread to finish, since there
|
||||||
|
// might a deadlock there: the thread can't finish deleting its
|
||||||
|
// window unless we're pumping the message loop for the parent,
|
||||||
|
// which won't happen if we're sitting here waiting. No worries; we
|
||||||
|
// don't *really* need to wait for the thread.
|
||||||
|
|
||||||
|
// WaitForSingleObject(_thread, INFINITE);
|
||||||
|
|
||||||
CloseHandle(_thread);
|
CloseHandle(_thread);
|
||||||
_thread = NULL;
|
_thread = NULL;
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,25 @@
|
|||||||
// Windows case
|
// Windows case
|
||||||
|
|
||||||
// Locks are straightforward.
|
// Locks are straightforward.
|
||||||
|
class _lock {
|
||||||
|
public:
|
||||||
|
CRITICAL_SECTION _l;
|
||||||
|
int _count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#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 RELEASE_LOCK(lock) { --((lock)._count); LeaveCriticalSection(&(lock)._l); }
|
||||||
|
#define DESTROY_LOCK(lock) DeleteCriticalSection(&(lock)._l)
|
||||||
|
|
||||||
|
/*
|
||||||
#define LOCK CRITICAL_SECTION
|
#define LOCK CRITICAL_SECTION
|
||||||
#define INIT_LOCK(lock) InitializeCriticalSection(&(lock))
|
#define INIT_LOCK(lock) InitializeCriticalSection(&(lock))
|
||||||
#define ACQUIRE_LOCK(lock) EnterCriticalSection(&(lock))
|
#define ACQUIRE_LOCK(lock) EnterCriticalSection(&(lock))
|
||||||
#define RELEASE_LOCK(lock) LeaveCriticalSection(&(lock))
|
#define RELEASE_LOCK(lock) LeaveCriticalSection(&(lock))
|
||||||
#define DESTROY_LOCK(lock) DeleteCriticalSection(&(lock))
|
#define DESTROY_LOCK(lock) DeleteCriticalSection(&(lock))
|
||||||
|
*/
|
||||||
|
|
||||||
// Threads.
|
// Threads.
|
||||||
#define THREAD HANDLE
|
#define THREAD HANDLE
|
||||||
|
@ -62,6 +62,13 @@ extern ofstream logfile;
|
|||||||
|
|
||||||
#include "load_plugin.h"
|
#include "load_plugin.h"
|
||||||
|
|
||||||
|
// Uncomment the following to enable use of the PluginThreadAsyncCall
|
||||||
|
// function. (It's commented out for now to assist development of the
|
||||||
|
// case in which this is not available.)
|
||||||
|
#if defined(NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL) && NP_VERSION_MINOR >= NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL
|
||||||
|
#define HAS_PLUGIN_THREAD_ASYNC_CALL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// Appears in startup.cxx.
|
// Appears in startup.cxx.
|
||||||
extern NPNetscapeFuncs *browser;
|
extern NPNetscapeFuncs *browser;
|
||||||
|
|
||||||
|
@ -436,31 +436,6 @@ handle_request(P3D_request *request) {
|
|||||||
P3D_request_finish(request, handled);
|
P3D_request_finish(request, handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PPInstance::handle_request_loop
|
|
||||||
// Access: Public, Static
|
|
||||||
// Description: Checks for any new requests from the plugin, and
|
|
||||||
// dispatches them to the appropriate PPInstance. This
|
|
||||||
// function is called only in the main thread.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void PPInstance::
|
|
||||||
handle_request_loop() {
|
|
||||||
if (!is_plugin_loaded()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
P3D_instance *p3d_inst = P3D_check_request(false);
|
|
||||||
while (p3d_inst != (P3D_instance *)NULL) {
|
|
||||||
P3D_request *request = P3D_instance_get_request(p3d_inst);
|
|
||||||
if (request != (P3D_request *)NULL) {
|
|
||||||
PPInstance *inst = (PPInstance *)(p3d_inst->_user_data);
|
|
||||||
assert(inst != NULL);
|
|
||||||
inst->handle_request(request);
|
|
||||||
}
|
|
||||||
p3d_inst = P3D_check_request(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPInstance::handle_event
|
// Function: PPInstance::handle_event
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -469,8 +444,12 @@ handle_request_loop() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PPInstance::
|
void PPInstance::
|
||||||
handle_event(void *event) {
|
handle_event(void *event) {
|
||||||
// This is a good time to check for new requests.
|
#ifndef HAS_PLUGIN_THREAD_ASYNC_CALL
|
||||||
|
// If we can't ask Mozilla to call us back using
|
||||||
|
// NPN_PluginThreadAsyncCall(), then we'll take advantage of the
|
||||||
|
// event loop to do it now.
|
||||||
handle_request_loop();
|
handle_request_loop();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (_p3d_inst == NULL) {
|
if (_p3d_inst == NULL) {
|
||||||
// Ignore events that come in before we've launched the instance.
|
// Ignore events that come in before we've launched the instance.
|
||||||
@ -631,14 +610,24 @@ request_ready(P3D_instance *instance) {
|
|||||||
// << " thread = " << GetCurrentThreadId()
|
// << " thread = " << GetCurrentThreadId()
|
||||||
<< "\n" << flush;
|
<< "\n" << flush;
|
||||||
|
|
||||||
|
PPInstance *inst = (PPInstance *)(instance->_user_data);
|
||||||
|
assert(inst != NULL);
|
||||||
|
|
||||||
|
#ifdef HAS_PLUGIN_THREAD_ASYNC_CALL
|
||||||
|
// Since we are running at least Gecko 1.9, and we have this very
|
||||||
|
// useful function, let's use it to ask the browser to call us back
|
||||||
|
// in the main thread.
|
||||||
|
browser->pluginthreadasynccall(inst->_npp_instance, browser_sync_callback, NULL);
|
||||||
|
#else // HAS_PLUGIN_THREAD_ASYNC_CALL
|
||||||
|
|
||||||
|
// If we're using an older version of Gecko, we have to do this some
|
||||||
|
// other, OS-dependent way.
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Since we might be in a sub-thread at this point, use a Windows
|
// Use a Windows message to forward this event to the main thread.
|
||||||
// message to forward this event to the main thread.
|
|
||||||
|
|
||||||
// Get the window handle for the window associated with this
|
// Get the window handle for the window associated with this
|
||||||
// instance.
|
// instance.
|
||||||
PPInstance *inst = (PPInstance *)(instance->_user_data);
|
|
||||||
assert(inst != NULL);
|
|
||||||
const NPWindow *win = inst->get_window();
|
const NPWindow *win = inst->get_window();
|
||||||
if (win != NULL && win->type == NPWindowTypeWindow) {
|
if (win != NULL && win->type == NPWindowTypeWindow) {
|
||||||
PostMessage((HWND)(win->window), WM_USER, 0, 0);
|
PostMessage((HWND)(win->window), WM_USER, 0, 0);
|
||||||
@ -656,6 +645,8 @@ request_ready(P3D_instance *instance) {
|
|||||||
handle_request_loop();
|
handle_request_loop();
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
|
#endif // HAS_PLUGIN_THREAD_ASYNC_CALL
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1101,6 +1092,45 @@ output_np_variant(ostream &out, const NPVariant &result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPInstance::handle_request_loop
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Checks for any new requests from the plugin, and
|
||||||
|
// dispatches them to the appropriate PPInstance. This
|
||||||
|
// function is called only in the main thread.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPInstance::
|
||||||
|
handle_request_loop() {
|
||||||
|
if (!is_plugin_loaded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
P3D_instance *p3d_inst = P3D_check_request(false);
|
||||||
|
while (p3d_inst != (P3D_instance *)NULL) {
|
||||||
|
P3D_request *request = P3D_instance_get_request(p3d_inst);
|
||||||
|
if (request != (P3D_request *)NULL) {
|
||||||
|
PPInstance *inst = (PPInstance *)(p3d_inst->_user_data);
|
||||||
|
assert(inst != NULL);
|
||||||
|
inst->handle_request(request);
|
||||||
|
}
|
||||||
|
p3d_inst = P3D_check_request(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPInstance::browser_sync_callback
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: This callback hook is passed to
|
||||||
|
// NPN_PluginThreadAsyncCall() (if that function is
|
||||||
|
// available) to forward a request to the main thread.
|
||||||
|
// The callback is actually called in the main thread.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPInstance::
|
||||||
|
browser_sync_callback(void *) {
|
||||||
|
logfile << "browser_sync_callback\n";
|
||||||
|
handle_request_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1113,14 +1143,12 @@ output_np_variant(ostream &out, const NPVariant &result) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
LONG PPInstance::
|
LONG PPInstance::
|
||||||
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
|
#ifndef HAS_PLUGIN_THREAD_ASYNC_CALL
|
||||||
// Since we're here in the main thread, call handle_request_loop()
|
// Since we're here in the main thread, call handle_request_loop()
|
||||||
// to see if there are any new requests to be serviced by the main
|
// to see if there are any new requests to be serviced by the main
|
||||||
// thread.
|
// thread.
|
||||||
|
|
||||||
// This might end up recursing repeatedly into
|
|
||||||
// handle_request_loop(). Not sure if this is bad or not.
|
|
||||||
// *Something* appears to be a little unstable.
|
|
||||||
handle_request_loop();
|
handle_request_loop();
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_ERASEBKGND:
|
case WM_ERASEBKGND:
|
||||||
@ -1129,6 +1157,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
|
case WM_USER:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ public:
|
|||||||
void stream_as_file(NPStream *stream, const char *fname);
|
void stream_as_file(NPStream *stream, const char *fname);
|
||||||
|
|
||||||
void handle_request(P3D_request *request);
|
void handle_request(P3D_request *request);
|
||||||
static void handle_request_loop();
|
|
||||||
|
|
||||||
void handle_event(void *event);
|
void handle_event(void *event);
|
||||||
|
|
||||||
@ -78,6 +77,9 @@ private:
|
|||||||
void create_instance();
|
void create_instance();
|
||||||
void send_window();
|
void send_window();
|
||||||
|
|
||||||
|
static void handle_request_loop();
|
||||||
|
static void browser_sync_callback(void *);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static LONG
|
static LONG
|
||||||
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||||
|
@ -329,7 +329,7 @@ NPP_Print(NPP instance, NPPrint *platformPrint) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int16
|
int16
|
||||||
NPP_HandleEvent(NPP instance, void *event) {
|
NPP_HandleEvent(NPP instance, void *event) {
|
||||||
// logfile << "HandleEvent\n" << flush;
|
logfile << "HandleEvent\n" << flush;
|
||||||
|
|
||||||
PPInstance *inst = (PPInstance *)(instance->pdata);
|
PPInstance *inst = (PPInstance *)(instance->pdata);
|
||||||
assert(inst != NULL);
|
assert(inst != NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user