hey its working

This commit is contained in:
David Rose 2009-06-24 05:33:44 +00:00
parent 93f9e9933b
commit 36eb5bc08a
15 changed files with 186 additions and 108 deletions

View File

@ -33,7 +33,8 @@ static const string default_plugin_filename = "p3d_plugin";
P3D_initialize_func *P3D_initialize;
P3D_free_string_func *P3D_free_string;
P3D_create_instance_func *P3D_create_instance;
P3D_new_instance_func *P3D_new_instance;
P3D_instance_start_func *P3D_instance_start;
P3D_instance_finish_func *P3D_instance_finish;
P3D_instance_setup_window_func *P3D_instance_setup_window;
P3D_instance_has_property_func *P3D_instance_has_property;
@ -147,7 +148,8 @@ load_plugin(const string &p3d_plugin_filename) {
// Now get all of the function pointers.
P3D_initialize = (P3D_initialize_func *)GetProcAddress(module, "P3D_initialize");
P3D_free_string = (P3D_free_string_func *)GetProcAddress(module, "P3D_free_string");
P3D_create_instance = (P3D_create_instance_func *)GetProcAddress(module, "P3D_create_instance");
P3D_new_instance = (P3D_new_instance_func *)GetProcAddress(module, "P3D_new_instance");
P3D_instance_start = (P3D_instance_start_func *)GetProcAddress(module, "P3D_instance_start");
P3D_instance_finish = (P3D_instance_finish_func *)GetProcAddress(module, "P3D_instance_finish");
P3D_instance_setup_window = (P3D_instance_setup_window_func *)GetProcAddress(module, "P3D_instance_setup_window");
P3D_instance_has_property = (P3D_instance_has_property_func *)GetProcAddress(module, "P3D_instance_has_property");
@ -170,7 +172,8 @@ load_plugin(const string &p3d_plugin_filename) {
// Now get all of the function pointers.
P3D_initialize = (P3D_initialize_func *)dlsym(module, "P3D_initialize");
P3D_free_string = (P3D_free_string_func *)dlsym(module, "P3D_free_string");
P3D_create_instance = (P3D_create_instance_func *)dlsym(module, "P3D_create_instance");
P3D_new_instance = (P3D_new_instance_func *)dlsym(module, "P3D_new_instance");
P3D_instance_start = (P3D_instance_start_func *)dlsym(module, "P3D_instance_start");
P3D_instance_finish = (P3D_instance_finish_func *)dlsym(module, "P3D_instance_finish");
P3D_instance_setup_window = (P3D_instance_setup_window_func *)dlsym(module, "P3D_instance_setup_window");
P3D_instance_has_property = (P3D_instance_has_property_func *)dlsym(module, "P3D_instance_has_property");
@ -186,7 +189,8 @@ load_plugin(const string &p3d_plugin_filename) {
// Ensure that all of the function pointers have been found.
if (P3D_initialize == NULL ||
P3D_free_string == NULL ||
P3D_create_instance == NULL ||
P3D_new_instance == NULL ||
P3D_instance_start == NULL ||
P3D_instance_finish == NULL ||
P3D_instance_setup_window == NULL ||
P3D_instance_has_property == NULL ||
@ -236,7 +240,8 @@ unload_plugin() {
P3D_initialize = NULL;
P3D_free_string = NULL;
P3D_create_instance = NULL;
P3D_new_instance = NULL;
P3D_instance_start = NULL;
P3D_instance_finish = NULL;
P3D_instance_has_property = NULL;
P3D_instance_get_property = NULL;

View File

@ -22,7 +22,8 @@ using namespace std;
extern P3D_initialize_func *P3D_initialize;
extern P3D_free_string_func *P3D_free_string;
extern P3D_create_instance_func *P3D_create_instance;
extern P3D_new_instance_func *P3D_new_instance;
extern P3D_instance_start_func *P3D_instance_start;
extern P3D_instance_finish_func *P3D_instance_finish;
extern P3D_instance_setup_window_func *P3D_instance_setup_window;
extern P3D_instance_has_property_func *P3D_instance_has_property;

View File

@ -70,3 +70,14 @@ inline const string &P3DInstance::
get_python_version() const {
return _python_version;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::is_started
// Access: Public
// Description: Returns true if this instance has already been
// started within some session, false otherwise.
////////////////////////////////////////////////////////////////////
inline bool P3DInstance::
is_started() const {
return (_session != NULL);
}

View File

@ -29,28 +29,19 @@ int P3DInstance::_next_instance_id = 0;
// Description:
////////////////////////////////////////////////////////////////////
P3DInstance::
P3DInstance(P3D_request_ready_func *func, void *user_data,
const string &p3d_filename,
const P3D_token tokens[], size_t num_tokens) :
_func(func),
_fparams(p3d_filename, tokens, num_tokens)
P3DInstance(P3D_request_ready_func *func, void *user_data) :
_func(func)
{
_user_data = user_data;
_request_pending = false;
_got_fparams = false;
_got_wparams = false;
_instance_id = _next_instance_id;
++_next_instance_id;
INIT_LOCK(_request_lock);
// For the moment, all sessions will be unique.
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
ostringstream strm;
strm << inst_mgr->get_unique_session_index();
_session_key = strm.str();
_python_version = "python24";
_session = NULL;
_requested_stop = false;
}
@ -80,6 +71,29 @@ P3DInstance::
// download is still running? Who will crash when this happens?
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::set_fparams
// Access: Public
// Description: Sets up the initial file parameters for the instance.
// Normally this is only called once.
////////////////////////////////////////////////////////////////////
void P3DInstance::
set_fparams(const P3DFileParams &fparams) {
_got_fparams = true;
_fparams = fparams;
// This also sets up some internal data based on the contents of the
// above file and the associated tokens.
// For the moment, all sessions will be unique.
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
ostringstream strm;
strm << inst_mgr->get_unique_session_index();
_session_key = strm.str();
_python_version = "python24";
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstance::set_wparams
// Access: Public
@ -89,21 +103,23 @@ P3DInstance::
////////////////////////////////////////////////////////////////////
void P3DInstance::
set_wparams(const P3DWindowParams &wparams) {
assert(_session != NULL);
_got_wparams = true;
_wparams = wparams;
TiXmlDocument *doc = new TiXmlDocument;
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", "");
TiXmlElement *xcommand = new TiXmlElement("command");
xcommand->SetAttribute("cmd", "setup_window");
xcommand->SetAttribute("id", get_instance_id());
TiXmlElement *xwparams = _wparams.make_xml();
if (_session != NULL) {
TiXmlDocument *doc = new TiXmlDocument;
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", "");
TiXmlElement *xcommand = new TiXmlElement("command");
xcommand->SetAttribute("cmd", "setup_window");
xcommand->SetAttribute("id", get_instance_id());
TiXmlElement *xwparams = _wparams.make_xml();
doc->LinkEndChild(decl);
doc->LinkEndChild(xcommand);
xcommand->LinkEndChild(xwparams);
doc->LinkEndChild(decl);
doc->LinkEndChild(xcommand);
xcommand->LinkEndChild(xwparams);
_session->send_command(doc);
_session->send_command(doc);
}
}
////////////////////////////////////////////////////////////////////
@ -153,9 +169,7 @@ set_property(const string &property_name, const string &value) {
////////////////////////////////////////////////////////////////////
bool P3DInstance::
has_request() {
nout << "has_request called, getting lock\n" << flush;
ACQUIRE_LOCK(_request_lock);
nout << "got lock\n" << flush;
bool any_requests = !_pending_requests.empty();
RELEASE_LOCK(_request_lock);
return any_requests;
@ -174,11 +188,8 @@ P3D_request *P3DInstance::
get_request() {
P3D_request *result = NULL;
ACQUIRE_LOCK(_request_lock);
nout << "P3DInstance::get_request() called on " << this
<< ", " << _pending_requests.size() << " requests in queue\n";
if (!_pending_requests.empty()) {
result = _pending_requests.front();
nout << "popped request " << result << "\n";
_pending_requests.pop_front();
_request_pending = !_pending_requests.empty();
}
@ -195,7 +206,6 @@ get_request() {
////////////////////////////////////////////////////////////////////
void P3DInstance::
add_request(P3D_request *request) {
nout << "adding request " << request << " in " << this << "\n";
assert(request->_instance == this);
ACQUIRE_LOCK(_request_lock);
@ -204,11 +214,9 @@ add_request(P3D_request *request) {
RELEASE_LOCK(_request_lock);
// Asynchronous notification for anyone who cares.
nout << "request_ready, calling " << (void *)_func << "\n" << flush;
if (_func != NULL) {
_func(this);
}
nout << "done calling " << (void *)_func << "\n" << flush;
// Synchronous notification for pollers.
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
@ -342,11 +350,18 @@ request_stop() {
////////////////////////////////////////////////////////////////////
TiXmlElement *P3DInstance::
make_xml() {
assert(_got_fparams);
TiXmlElement *xinstance = new TiXmlElement("instance");
xinstance->SetAttribute("id", _instance_id);
TiXmlElement *xfparams = _fparams.make_xml();
xinstance->LinkEndChild(xfparams);
if (_got_wparams) {
TiXmlElement *xwparams = _wparams.make_xml();
xinstance->LinkEndChild(xwparams);
}
return xinstance;
}

View File

@ -35,11 +35,10 @@ class P3DPackage;
////////////////////////////////////////////////////////////////////
class P3DInstance : public P3D_instance {
public:
P3DInstance(P3D_request_ready_func *func, void *user_data,
const string &p3d_filename,
const P3D_token tokens[], size_t num_tokens);
P3DInstance(P3D_request_ready_func *func, void *user_data);
~P3DInstance();
void set_fparams(const P3DFileParams &fparams);
inline const P3DFileParams &get_fparams() const;
void set_wparams(const P3DWindowParams &wparams);
@ -68,6 +67,7 @@ public:
void add_package(P3DPackage *package);
void start_download(P3DDownload *download);
inline bool is_started() const;
void request_stop();
TiXmlElement *make_xml();
@ -75,7 +75,10 @@ public:
private:
P3D_request_ready_func *_func;
bool _got_fparams;
P3DFileParams _fparams;
bool _got_wparams;
P3DWindowParams _wparams;
int _instance_id;

View File

@ -112,14 +112,30 @@ initialize() {
// indicated startup information.
////////////////////////////////////////////////////////////////////
P3DInstance *P3DInstanceManager::
create_instance(P3D_request_ready_func *func,
void *user_data,
const string &p3d_filename,
const P3D_token tokens[], size_t num_tokens) {
P3DInstance *inst = new P3DInstance(func, user_data, p3d_filename,
tokens, num_tokens);
create_instance(P3D_request_ready_func *func, void *user_data) {
P3DInstance *inst = new P3DInstance(func, user_data);
_instances.insert(inst);
return inst;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::start_instance
// Access: Public
// Description: Actually starts the instance running. Before this
// call, the instance is in an indeterminate state. It
// is an error to call this more than once for a
// particular instance.
////////////////////////////////////////////////////////////////////
bool P3DInstanceManager::
start_instance(P3DInstance *inst, const string &p3d_filename,
const P3D_token tokens[], size_t num_tokens) {
if (inst->is_started()) {
nout << "Instance started twice: " << inst << "\n";
return false;
}
inst->set_fparams(P3DFileParams(p3d_filename, tokens, num_tokens));
P3DSession *session;
Sessions::iterator si = _sessions.find(inst->get_session_key());
if (si == _sessions.end()) {
@ -132,7 +148,7 @@ create_instance(P3D_request_ready_func *func,
session->start_instance(inst);
return inst;
return inst->is_started();
}
////////////////////////////////////////////////////////////////////
@ -171,16 +187,12 @@ finish_instance(P3DInstance *inst) {
////////////////////////////////////////////////////////////////////
P3DInstance *P3DInstanceManager::
check_request() {
nout << "check_request\n" << flush;
Instances::iterator ii;
for (ii = _instances.begin(); ii != _instances.end(); ++ii) {
P3DInstance *inst = (*ii);
cerr << " checking request for " << inst << "\n" << flush;
if (inst->has_request()) {
cerr << " true\n" << flush;
return inst;
}
cerr << " false\n" << flush;
}
return NULL;

View File

@ -44,13 +44,11 @@ public:
inline const string &get_platform() const;
P3DInstance *
create_instance(P3D_request_ready_func *func,
void *user_data,
const string &p3d_filename,
const P3D_token tokens[], size_t num_tokens);
create_instance(P3D_request_ready_func *func, void *user_data);
void
finish_instance(P3DInstance *inst);
bool start_instance(P3DInstance *inst, const string &p3d_filename,
const P3D_token tokens[], size_t num_tokens);
void finish_instance(P3DInstance *inst);
P3DInstance *check_request();
void wait_request();

View File

@ -292,6 +292,11 @@ start_instance(P3DCInstance *inst, TiXmlElement *xinstance) {
if (xfparams != (TiXmlElement *)NULL) {
set_p3d_filename(inst, xfparams);
}
TiXmlElement *xwparams = xinstance->FirstChildElement("wparams");
if (xwparams != (TiXmlElement *)NULL) {
setup_window(inst, xwparams);
}
}
////////////////////////////////////////////////////////////////////
@ -377,8 +382,17 @@ setup_window(int id, TiXmlElement *xwparams) {
return;
}
// P3DCInstance *inst = (*ii).second;
P3DCInstance *inst = (*ii).second;
setup_window(inst, xwparams);
}
////////////////////////////////////////////////////////////////////
// Function: P3DPythonRun::setup_window
// Access: Private
// Description: Sets the window parameters for the indicated instance.
////////////////////////////////////////////////////////////////////
void P3DPythonRun::
setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
string window_type;
const char *window_type_c = xwparams->Attribute("window_type");
if (window_type_c != NULL) {

View File

@ -73,6 +73,7 @@ private:
void terminate_instance(int id);
void set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams);
void setup_window(int id, TiXmlElement *xwparams);
void setup_window(P3DCInstance *inst, TiXmlElement *xwparams);
void terminate_session();

View File

@ -49,15 +49,15 @@ P3DSession(P3DInstance *inst) {
_output_filename = inst->get_fparams().lookup_token("output_filename");
_panda3d_callback = NULL;
INIT_LOCK(_instances_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
_panda3d = inst_mgr->get_package("panda3d", "dev", "Panda3D");
inst->add_package(_panda3d);
_panda3d_callback = NULL;
_python_root_dir = _panda3d->get_package_dir();
INIT_LOCK(_instances_lock);
inst->add_package(_panda3d);
}

View File

@ -32,11 +32,14 @@
// Posix case
#include <pthread.h>
// We declare this to be a recursive lock, since we might make a
// request_ready call from within the API, which in turn is allowed to
// call back into the API.
#define LOCK pthread_mutex_t
#define INIT_LOCK(lock) { \
pthread_mutexattr_t attr; \
pthread_mutexattr_init(&attr); \
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); \
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
int result = pthread_mutex_init(&(lock), &attr); \
pthread_mutexattr_destroy(&attr); \
}

View File

@ -69,19 +69,26 @@ P3D_free_string(char *string) {
}
P3D_instance *
P3D_create_instance(P3D_request_ready_func *func,
void *user_data,
const char *p3d_filename,
const P3D_token tokens[], size_t num_tokens) {
P3D_new_instance(P3D_request_ready_func *func, void *user_data) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3DInstance *result = inst_mgr->create_instance(func, user_data);
RELEASE_LOCK(_lock);
return result;
}
bool
P3D_instance_start(P3D_instance *instance, const char *p3d_filename,
const P3D_token tokens[], size_t num_tokens) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
if (p3d_filename == NULL) {
p3d_filename = "";
}
P3DInstance *result =
inst_mgr->create_instance(func, user_data, p3d_filename, tokens, num_tokens);
ACQUIRE_LOCK(_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
bool result = inst_mgr->start_instance
((P3DInstance *)instance, p3d_filename, tokens, num_tokens);
RELEASE_LOCK(_lock);
return result;
}
@ -149,9 +156,7 @@ P3D_request *
P3D_instance_get_request(P3D_instance *instance) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_lock);
nout << "P3D_instance_get_request(" << instance << ")\n";
P3D_request *result = ((P3DInstance *)instance)->get_request();
nout << " result = " << result << "\n" << flush;
RELEASE_LOCK(_lock);
return result;
}
@ -163,8 +168,6 @@ P3D_check_request(bool wait) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3D_instance *inst = inst_mgr->check_request();
nout << "P3D_instance_check_request, inst = " << inst << "\n";
if (inst != NULL || !wait) {
RELEASE_LOCK(_lock);
return inst;

View File

@ -118,7 +118,7 @@ typedef struct {
/* an opaque pointer the host may use to store private data that the
plugin does not interpret. This pointer can be directly set, or
it can be initialized in the P3D_create_instance() call. */
it can be initialized in the P3D_new_instance() call. */
void *_user_data;
/* Additional opaque data may be stored here. */
@ -168,10 +168,10 @@ typedef enum {
} P3D_window_type;
/* This function pointer must be passed to P3D_create_instance(),
below. The host must pass in a pointer to a valid function in the
host's address space, or NULL. If not NULL, this function will be
called asynchronously by the plugin when the plugin needs to make a
/* This function pointer must be passed to P3D_new_instance(), below.
The host must pass in a pointer to a valid function in the host's
address space, or NULL. If not NULL, this function will be called
asynchronously by the plugin when the plugin needs to make a
request from the host. After this notification has been received,
the host should call P3D_instance_get_request() (at its
convenience) to retrieve the actual plugin request. If the host
@ -199,17 +199,26 @@ typedef struct {
/* This function creates a new Panda3D instance.
For p3d_filename pass the name of a file on disk that contains the
contents of the p3d file that should be launched within the
instance. If this is empty or NULL, the "src" token (below) will
be downloaded instead.
The user_data pointer is any arbitrary pointer value; it will be
copied into the _user_data member of the new P3D_instance object.
This pointer is intended for the host to use to store private data
associated with each instance; the plugin will not do anything with
this data.
*/
typedef P3D_instance *
P3D_new_instance_func(P3D_request_ready_func *func, void *user_data);
/* This function should be called at some point after
P3D_new_instance(); it actually starts the instance running.
Before this call, the instance will be in an indeterminate state.
For p3d_filename pass the name of a file on disk that contains the
contents of the p3d file that should be launched within the
instance. If this is empty or NULL, the "src" token (below) will
be downloaded instead.
For tokens, pass an array of P3D_token elements (above), which
correspond to the user-supplied keyword/value pairs that may appear
in the embed token within the HTML syntax; the host is responsible
@ -229,13 +238,10 @@ typedef struct {
output is written to the standard error output, which may be
NULL on a gui application.
*/
typedef P3D_instance *
P3D_create_instance_func(P3D_request_ready_func *func,
void *user_data,
const char *p3d_filename,
const P3D_token tokens[], size_t num_tokens);
The return value is true on success, false on failure. */
typedef bool
P3D_instance_start_func(P3D_instance *instance, const char *p3d_filename,
const P3D_token tokens[], size_t num_tokens);
/* Call this function to interrupt a particular instance and stop it
@ -467,7 +473,8 @@ P3D_instance_feed_url_stream_func(P3D_instance *instance, int unique_id,
/* Define all of the actual prototypes for the above functions. */
EXPCL_P3D_PLUGIN P3D_initialize_func P3D_initialize;
EXPCL_P3D_PLUGIN P3D_free_string_func P3D_free_string;
EXPCL_P3D_PLUGIN P3D_create_instance_func P3D_create_instance;
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_finish_func P3D_instance_finish;
EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window;
EXPCL_P3D_PLUGIN P3D_instance_has_property_func P3D_instance_has_property;

View File

@ -253,7 +253,7 @@ url_notify(const char *url, NPReason reason, void *notifyData) {
break;
}
// delete req;
delete req;
}
////////////////////////////////////////////////////////////////////
@ -333,7 +333,8 @@ stream_as_file(NPStream *stream, const char *fname) {
////////////////////////////////////////////////////////////////////
void PPInstance::
handle_request(P3D_request *request) {
logfile << "handle_request: " << request << "\n";
logfile << "handle_request: " << request << ", " << request->_instance
<< " within " << this << ", " << _p3d_inst << "\n" << flush;
assert(request->_instance == _p3d_inst);
bool handled = false;
@ -401,15 +402,17 @@ create_instance() {
return;
}
const P3D_token *tokens = NULL;
if (!_tokens.empty()) {
tokens = &_tokens[0];
}
_p3d_inst = P3D_create_instance
(request_ready, this, _p3d_filename.c_str(), tokens, _tokens.size());
logfile << "within " << this << ", creating new instance\n" << flush;
_p3d_inst = P3D_new_instance(request_ready, this);
logfile << "within " << this << ", created new instance " << _p3d_inst
<< "\n" << flush;
if (_p3d_inst != NULL) {
const P3D_token *tokens = NULL;
if (!_tokens.empty()) {
tokens = &_tokens[0];
}
P3D_instance_start(_p3d_inst, _p3d_filename.c_str(), tokens, _tokens.size());
send_window();
}
}

View File

@ -261,11 +261,13 @@ create_instance(const string &arg, P3D_window_type window_type,
os_p3d_filename = p3d_filename.to_os_specific();
}
P3D_instance *inst = P3D_create_instance
(NULL, NULL, os_p3d_filename.c_str(), tokens, num_tokens);
P3D_instance *inst = P3D_new_instance(NULL, NULL);
P3D_instance_setup_window
(inst, window_type, win_x, win_y, win_width, win_height, parent_window);
if (inst != NULL) {
P3D_instance_setup_window
(inst, window_type, win_x, win_y, win_width, win_height, parent_window);
P3D_instance_start(inst, os_p3d_filename.c_str(), tokens, num_tokens);
}
return inst;
}