diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp
index b48b328b56..3d06e60191 100644
--- a/direct/src/plugin/Sources.pp
+++ b/direct/src/plugin/Sources.pp
@@ -5,6 +5,7 @@
#begin lib_target
#define USE_PACKAGES tinyxml openssl zlib
#define TARGET p3d_plugin
+ #define LIB_PREFIX
#define COMBINED_SOURCES \
$[TARGET]_composite1.cxx
diff --git a/direct/src/plugin/load_plugin_src.cxx b/direct/src/plugin/load_plugin_src.cxx
index 61cf7582e9..96bdf5ade9 100755
--- a/direct/src/plugin/load_plugin_src.cxx
+++ b/direct/src/plugin/load_plugin_src.cxx
@@ -30,7 +30,7 @@ static const string dll_ext = ".dylib";
static const string dll_ext = ".so";
#endif
-static const string default_plugin_filename = "libp3d_plugin";
+static const string default_plugin_filename = "p3d_plugin";
P3D_initialize_func *P3D_initialize;
P3D_free_string_func *P3D_free_string;
diff --git a/direct/src/plugin/make_contents.py b/direct/src/plugin/make_contents.py
index 272b00b932..d4b5cca156 100755
--- a/direct/src/plugin/make_contents.py
+++ b/direct/src/plugin/make_contents.py
@@ -53,9 +53,9 @@ class ContentsMaker:
f = open(contentsFilePathname.toOsSpecific(), 'w')
print >> f, ''
print >> f, ''
- for packageName, packageVersion, file in self.packages:
- print >> f, '' % (
- packageName, packageVersion, file.getParams())
+ for packageName, packageVersion, packagePlatform, file in self.packages:
+ print >> f, '' % (
+ packageName, packageVersion, packagePlatform or '', file.getParams())
f.close()
def scanDirectory(self):
@@ -75,13 +75,25 @@ class ContentsMaker:
localpath = dirpath[len(prefix):].replace(os.sep, '/') + '/'
xml = dirpath[len(prefix):].replace(os.sep, '_') + '.xml'
- if xml.count('_') == 1 and xml in filenames:
+ if xml not in filenames:
+ continue
+
+ if xml.count('_') == 1:
basename = xml.split('.')[0]
packageName, packageVersion = basename.split('_')
+ packagePlatform = None
file = FileSpec(localpath + xml,
Filename(self.stageDir, localpath + xml))
print file.filename
- self.packages.append((packageName, packageVersion, file))
+ self.packages.append((packageName, packageVersion, packagePlatform, file))
+
+ if xml.count('_') == 2:
+ basename = xml.split('.')[0]
+ packageName, packageVersion, packagePlatform = basename.split('_')
+ file = FileSpec(localpath + xml,
+ Filename(self.stageDir, localpath + xml))
+ print file.filename
+ self.packages.append((packageName, packageVersion, packagePlatform, file))
def makeContents(args):
diff --git a/direct/src/plugin/make_package.py b/direct/src/plugin/make_package.py
index 3e0937a124..3fbe79a8ee 100755
--- a/direct/src/plugin/make_package.py
+++ b/direct/src/plugin/make_package.py
@@ -23,10 +23,10 @@ Options:
the local machine that will be filled with the contents of the
package directory for the web server.
- -p package_name
- -v package_version
+ -p name_version[_platform]
- Specify the name and version of the package to build.
+ Specify the package name, version, and optional platfom, of the
+ package to build.
"""
@@ -49,7 +49,9 @@ class PackageMaker:
self.stageDir = None
self.packageName = None
self.packageVersion = None
+ self.packagePlatform = None
+ self.bogusExtensions = []
def build(self):
if not self.startDir:
@@ -59,11 +61,25 @@ class PackageMaker:
if not self.packageName or not self.packageVersion:
raise ArgumentError, "Package name and version not specified."
+ # First, scan the components. If we find any
+ # platform-dependent files, we automatically assume we're
+ # building a platform-specific package.
+ self.components = []
+ self.findComponents()
+
+ for ext in self.bogusExtensions:
+ print "Warning: Found files of type %s, inconsistent with declared platform %s" % (
+ ext, self.packagePlatform)
+
self.packageFullname = '%s_%s' % (
self.packageName, self.packageVersion)
self.packageStageDir = Filename(self.stageDir, '%s/%s' % (self.packageName, self.packageVersion))
+ if self.packagePlatform:
+ self.packageFullname += '_%s' % (self.packagePlatform)
+ self.packageStageDir = Filename(self.packageStageDir, self.packagePlatform)
+
Filename(self.packageStageDir, '.').makeDir()
self.cleanDir(self.packageStageDir)
@@ -73,8 +89,6 @@ class PackageMaker:
if not self.archive.openWrite(uncompressedArchivePathname):
raise IOError, "Couldn't open %s for writing" % (uncompressedArchivePathname)
- self.components = []
-
self.addComponents()
self.archive.close()
@@ -106,7 +120,7 @@ class PackageMaker:
f = open(descFilePathname.toOsSpecific(), 'w')
print >> f, ''
print >> f, ''
- print >> f, '' % (self.packageName, self.packageVersion)
+ print >> f, '' % (self.packageName, self.packageVersion, self.packagePlatform or '')
print >> f, ' ' % (uncompressedArchive.getParams())
print >> f, ' ' % (compressedArchive.getParams())
for file in self.components:
@@ -123,9 +137,9 @@ class PackageMaker:
pathname = Filename(dirname, filename)
pathname.unlink()
- def addComponents(self):
+ def findComponents(self):
""" Walks through all the files in the start directory and
- adds them to the archive. Recursively visits
+ adds them to self.components. Recursively visits
sub-directories. """
startDir = self.startDir.toOsSpecific()
@@ -142,12 +156,41 @@ class PackageMaker:
for basename in filenames:
file = FileSpec(localpath + basename,
Filename(self.startDir, localpath + basename))
- print file.filename
self.components.append(file)
- self.archive.addSubfile(file.filename, file.pathname, 0)
+ print file.filename
+
+ ext = os.path.splitext(basename)[1]
+ if ext in ['.exe', '.dll', '.pyd']:
+ self.ensurePlatform('win32', ext, file)
+ elif ext in ['.dylib']:
+ self.ensurePlatform('osx', ext, file)
+ elif ext in ['.so']:
+ self.ensurePlatform(None, ext, file)
+
+ def ensurePlatform(self, platform, ext, file):
+ """ We have just encountered a file that is specific to a
+ particular platform. Checks that the declared platform is
+ consistent with this. """
+
+ if platform and self.packagePlatform:
+ if self.packagePlatform.startswith(platform):
+ # This platform is consistent with our declared
+ # platform.
+ return
+
+ if ext in self.bogusExtensions:
+ # Already reported this one.
+ return
+
+ self.bogusExtensions.append(ext)
+
+
+ def addComponents(self):
+ for file in self.components:
+ self.archive.addSubfile(file.filename, file.pathname, 0)
def makePackage(args):
- opts, args = getopt.getopt(args, 's:d:p:v:h')
+ opts, args = getopt.getopt(args, 's:d:p:h')
pm = PackageMaker()
pm.startDir = Filename('.')
@@ -157,9 +200,15 @@ def makePackage(args):
elif option == '-d':
pm.stageDir = Filename.fromOsSpecific(value)
elif option == '-p':
- pm.packageName = value
- elif option == '-v':
- pm.packageVersion = value
+ tokens = value.split('_')
+ if len(tokens) >= 1:
+ pm.packageName = tokens[0]
+ if len(tokens) >= 2:
+ pm.packageVersion = tokens[1]
+ if len(tokens) >= 3:
+ pm.packagePlatform = tokens[2]
+ if len(tokens) >= 4:
+ raise ArgumentError, 'Too many tokens in string: %s' % (value)
elif option == '-h':
print __doc__
diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx
index 571087f9d8..043c3d2549 100644
--- a/direct/src/plugin/p3dInstanceManager.cxx
+++ b/direct/src/plugin/p3dInstanceManager.cxx
@@ -95,7 +95,7 @@ initialize() {
#ifdef _WIN32
// _download_url = "http://10.196.143.118/~drose/p3d/";
- _download_url = "http://www.ddrose.com/~drose/p3dwin/";
+ _download_url = "http://www.ddrose.com/~drose/p3d/";
#else
_download_url = "http://www.ddrose.com/~drose/p3d/";
@@ -239,14 +239,16 @@ wait_request() {
// package.
////////////////////////////////////////////////////////////////////
P3DPackage *P3DInstanceManager::
-get_package(const string &package_name, const string &package_version, const string &package_output_name) {
- string key = package_name + "_" + package_version;
+get_package(const string &package_name, const string &package_version,
+ const string &package_platform, const string &package_display_name) {
+ string key = package_name + "_" + package_version + "_" + package_platform;
Packages::iterator pi = _packages.find(key);
if (pi != _packages.end()) {
return (*pi).second;
}
- P3DPackage *package = new P3DPackage(package_name, package_version, package_output_name);
+ P3DPackage *package = new P3DPackage(package_name, package_version,
+ package_platform, package_display_name);
bool inserted = _packages.insert(Packages::value_type(key, package)).second;
assert(inserted);
diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h
index 952dd54ea2..e418f35f1a 100644
--- a/direct/src/plugin/p3dInstanceManager.h
+++ b/direct/src/plugin/p3dInstanceManager.h
@@ -55,7 +55,8 @@ public:
P3DPackage *get_package(const string &package_name,
const string &package_version,
- const string &package_output_name);
+ const string &package_platform,
+ const string &package_display_name);
inline P3DInstance *get_command_instance() const;
inline int get_num_instances() const;
diff --git a/direct/src/plugin/p3dPackage.I b/direct/src/plugin/p3dPackage.I
index 276276d686..2e4db4edcb 100755
--- a/direct/src/plugin/p3dPackage.I
+++ b/direct/src/plugin/p3dPackage.I
@@ -53,7 +53,7 @@ get_package_dir() const {
// Description: Returns the name of this package. This is an
// internal name, used to generate filenames and the
// like; it will generally be all-lowercase and will not
-// contain spaces. See also get_package_output_name()
+// contain spaces. See also get_package_display_name()
// for a name suitable for displaying to the user.
////////////////////////////////////////////////////////////////////
inline const string &P3DPackage::
@@ -72,7 +72,7 @@ get_package_version() const {
}
////////////////////////////////////////////////////////////////////
-// Function: P3DPackage::get_package_output_name
+// Function: P3DPackage::get_package_display_name
// Access: Public
// Description: Returns the name of this package, for output to the
// user. This will be the "public" name of the package,
@@ -80,8 +80,8 @@ get_package_version() const {
// capital letters and spaces where appropriate.
////////////////////////////////////////////////////////////////////
inline const string &P3DPackage::
-get_package_output_name() const {
- return _package_output_name;
+get_package_display_name() const {
+ return _package_display_name;
}
////////////////////////////////////////////////////////////////////
diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx
index fb01d6a5d4..e35fbe8dc5 100755
--- a/direct/src/plugin/p3dPackage.cxx
+++ b/direct/src/plugin/p3dPackage.cxx
@@ -51,21 +51,29 @@ static const double extract_portion = 0.05;
////////////////////////////////////////////////////////////////////
P3DPackage::
P3DPackage(const string &package_name, const string &package_version,
- const string &package_output_name) :
+ const string &package_platform,
+ const string &package_display_name) :
_package_name(package_name),
_package_version(package_version),
- _package_output_name(package_output_name)
+ _package_platform(package_platform),
+ _package_display_name(package_display_name)
{
+ P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+
_package_fullname = _package_name + "_" + _package_version;
+ _package_dir = inst_mgr->get_root_dir() + string("/") + _package_name;
+
+ if (!_package_platform.empty()) {
+ _package_fullname += "_" + _package_platform;
+ _package_dir += "/" + _package_platform;
+ }
+
_ready = false;
_failed = false;
_active_download = NULL;
_partial_download = false;
- P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
-
// Ensure the package directory exists; create it if it does not.
- _package_dir = inst_mgr->get_root_dir() + string("/") + _package_name;
inst_mgr->mkdir_public(_package_dir);
_package_dir += string("/") + _package_version;
@@ -156,7 +164,12 @@ void P3DPackage::
download_desc_file() {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
string url = inst_mgr->get_download_url();
- url += _package_name + "/" + _package_version + "/" + _desc_file_basename;
+ url += _package_name + "/" + _package_version;
+ if (!_package_platform.empty()) {
+ url += "/" + _package_platform;
+ }
+
+ url += "/" + _desc_file_basename;
start_download(DT_desc_file, url, _desc_file_pathname, false);
}
@@ -263,7 +276,12 @@ void P3DPackage::
download_compressed_archive(bool allow_partial) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
string url = inst_mgr->get_download_url();
- url += _package_name + "/" + _package_version + "/" + _compressed_archive._filename;
+ url += _package_name + "/" + _package_version;
+ if (!_package_platform.empty()) {
+ url += "/" + _package_platform;
+ }
+
+ url += "/" + _compressed_archive._filename;
string target_pathname = _package_dir + "/" + _compressed_archive._filename;
diff --git a/direct/src/plugin/p3dPackage.h b/direct/src/plugin/p3dPackage.h
index b5b05cce96..1e8e362e23 100755
--- a/direct/src/plugin/p3dPackage.h
+++ b/direct/src/plugin/p3dPackage.h
@@ -33,7 +33,8 @@
class P3DPackage {
public:
P3DPackage(const string &package_name, const string &package_version,
- const string &package_output_name);
+ const string &package_platform,
+ const string &package_display_name);
~P3DPackage();
class Callback {
@@ -48,7 +49,7 @@ public:
inline const string &get_package_dir() const;
inline const string &get_package_name() const;
inline const string &get_package_version() const;
- inline const string &get_package_output_name() const;
+ inline const string &get_package_display_name() const;
void set_callback(Callback *callback);
void cancel_callback(Callback *callback);
@@ -98,7 +99,8 @@ private:
private:
string _package_name;
string _package_version;
- string _package_output_name;
+ string _package_platform;
+ string _package_display_name;
string _package_fullname;
string _package_dir;
diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx
index f87bedea3d..ec23fcb7bb 100644
--- a/direct/src/plugin/p3dSession.cxx
+++ b/direct/src/plugin/p3dSession.cxx
@@ -50,7 +50,13 @@ P3DSession(P3DInstance *inst) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
- _panda3d = inst_mgr->get_package("panda3d", "dev", "Panda3D");
+#ifdef _WIN32
+ string platform = "win32";
+#else
+ string platform = "osx_i386";
+#endif
+
+ _panda3d = inst_mgr->get_package("panda3d", "dev", platform, "Panda3D");
_panda3d_callback = NULL;
_python_root_dir = _panda3d->get_package_dir();
diff --git a/direct/src/plugin/p3dWinProgressWindow.cxx b/direct/src/plugin/p3dWinProgressWindow.cxx
index 72dd554613..4aeba97a33 100755
--- a/direct/src/plugin/p3dWinProgressWindow.cxx
+++ b/direct/src/plugin/p3dWinProgressWindow.cxx
@@ -280,7 +280,7 @@ make_progress_bar() {
_hwnd, NULL, application, 0);
// Create a static text label. What a major pain *this* is.
- string text_string = "Installing " + _package->get_package_output_name();
+ string text_string = "Installing " + _package->get_package_display_name();
const char *text = text_string.c_str();
HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
diff --git a/direct/src/plugin_npapi/nppanda3d.rc b/direct/src/plugin_npapi/nppanda3d.rc
index 302e11bf1f..a60f372c23 100644
--- a/direct/src/plugin_npapi/nppanda3d.rc
+++ b/direct/src/plugin_npapi/nppanda3d.rc
@@ -32,21 +32,15 @@ BEGIN
BEGIN
BLOCK "040904e4"
BEGIN
- VALUE "Comments", "\0"
- VALUE "CompanyName", " \0"
- VALUE "FileDescription", "nppanda3d\0"
- VALUE "FileExtents", "bic\0"
- VALUE "FileOpenName", "nppanda3d\0"
+ VALUE "FileDescription", "Runs 3-D games and interactive applets\0"
VALUE "FileVersion", "1, 0, 0, 1\0"
- VALUE "InternalName", "nppanda3d\0"
- VALUE "LegalCopyright", "Copyright © 2001\0"
VALUE "LegalTrademarks", "\0"
VALUE "MIMEType", "application/x-panda3d\0"
+ VALUE "FileExtents", "p3d\0"
+ VALUE "FileOpenName", "Panda3D applet\0"
VALUE "OriginalFilename", "nppanda3d.dll\0"
- VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Panda3D Game Engine Plug-in\0"
VALUE "ProductVersion", "1, 0, 0, 1\0"
- VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
diff --git a/direct/src/plugin_npapi/nppanda3d_common.h b/direct/src/plugin_npapi/nppanda3d_common.h
index 418726c420..58810e6720 100644
--- a/direct/src/plugin_npapi/nppanda3d_common.h
+++ b/direct/src/plugin_npapi/nppanda3d_common.h
@@ -57,5 +57,8 @@ extern ofstream logfile;
//#include "npfunctions.h"
#include "npupp.h"
+// Appears in nppanda3d_startup.cxx.
+extern NPNetscapeFuncs *browser;
+
#endif
diff --git a/direct/src/plugin_npapi/nppanda3d_startup.cxx b/direct/src/plugin_npapi/nppanda3d_startup.cxx
index bcdd5c5acf..2eaf5431c1 100644
--- a/direct/src/plugin_npapi/nppanda3d_startup.cxx
+++ b/direct/src/plugin_npapi/nppanda3d_startup.cxx
@@ -21,7 +21,10 @@
#endif
ofstream logfile;
-bool logfile_is_open = false;
+
+NPNetscapeFuncs *browser;
+
+static bool logfile_is_open = false;
static void
open_logfile() {
if (!logfile_is_open) {
@@ -34,119 +37,13 @@ open_logfile() {
}
}
-
-// structure containing pointers to functions implemented by the browser
-static NPNetscapeFuncs *browser;
-
-// Called to create a new instance of the plugin
-NPError
-NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
- int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
- logfile << "new instance\n" << flush;
-
- // Copy the tokens into a temporary array of P3D_token objects.
- P3D_token *tokens = (P3D_token *)alloca(sizeof(P3D_token) * argc);
- for (int i = 0; i < argc; ++i) {
- P3D_token &token = tokens[i];
- token._keyword = argn[i];
- token._value = argv[i];
- logfile << " " << i << ": " << token._keyword << " = " << token._value << "\n";
- }
-
- instance->pdata = P3D_create_instance(NULL, NULL, tokens, argc);
-
- return NPERR_NO_ERROR;
-}
-
-// Called to destroy an instance of the plugin
-NPError
-NPP_Destroy(NPP instance, NPSavedData **save) {
- logfile << "destroy instance\n" << flush;
- (*save) = NULL;
- P3D_instance_finish((P3D_instance *)(instance->pdata));
- instance->pdata = NULL;
-
- return NPERR_NO_ERROR;
-}
-
-// Called to update a plugin instances's NPWindow
-NPError
-NPP_SetWindow(NPP instance, NPWindow *window) {
- logfile << "SetWindow " << window->x << ", " << window->y
- << ", " << window->width << ", " << window->height
- << "\n" << flush;
-
- P3D_instance *inst = (P3D_instance *)(instance->pdata);
- assert(inst != NULL);
-
- P3D_window_handle parent_window;
-#ifdef _WIN32
- parent_window._hwnd = (HWND)(window->window);
-#endif
-
- P3D_window_type window_type = P3D_WT_embedded;
-
- P3D_instance_setup_window
- (inst, window_type,
- window->x, window->y, window->width, window->height,
- parent_window);
-
- return NPERR_NO_ERROR;
-}
-
-
-NPError
-NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream,
- NPBool seekable, uint16 *stype) {
- *stype = NP_ASFILEONLY;
- return NPERR_NO_ERROR;
-}
-
-NPError
-NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
- return NPERR_NO_ERROR;
-}
-
-int32
-NPP_WriteReady(NPP instance, NPStream *stream) {
- return 0;
-}
-
-int32
-NPP_Write(NPP instance, NPStream *stream, int32 offset,
- int32 len, void *buffer) {
- return 0;
-}
-
-void
-NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) {
-}
-
-void
-NPP_Print(NPP instance, NPPrint *platformPrint) {
-}
-
-int16
-NPP_HandleEvent(NPP instance, void *event) {
- return 0;
-}
-
-void
-NPP_URLNotify(NPP instance, const char *url,
- NPReason reason, void *notifyData) {
-}
-
-NPError
-NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
- return NPERR_GENERIC_ERROR;
-}
-
-NPError
-NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
- return NPERR_GENERIC_ERROR;
-}
-
-// Symbol called once by the browser to initialize the plugin
+////////////////////////////////////////////////////////////////////
+// Function: NP_Initialize
+// Description: This function is called (almost) before any other
+// function, to ask the plugin to initialize itself and
+// to send the pointers to the browser control
+// functions. Also see NP_GetEntryPoints.
+////////////////////////////////////////////////////////////////////
#ifdef _WIN32
NPError OSCALL
NP_Initialize(NPNetscapeFuncs *browserFuncs)
@@ -168,9 +65,9 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
logfile << "browserFuncs = " << browserFuncs << "\n" << flush;
#ifdef _WIN32
- string plugin_location = "c:/cygwin/home/drose/player/direct/built/lib/libp3d_plugin.dll";
+ string plugin_location = "c:/cygwin/home/drose/player/direct/built/lib/p3d_plugin.dll";
#else
- string plugin_location = "/Users/drose/player/direct/built/lib/libp3d_plugin.dylib";
+ string plugin_location = "/Users/drose/player/direct/built/lib/p3d_plugin.dylib";
#endif
if (!load_plugin(plugin_location.c_str())) {
@@ -181,7 +78,14 @@ NP_Initialize(NPNetscapeFuncs *browserFuncs,
return NPERR_NO_ERROR;
}
-// Symbol called by the browser to get the plugin's function list
+////////////////////////////////////////////////////////////////////
+// Function: NP_GetEntryPoints
+// Description: This method is extracted directly from the DLL and
+// called at initialization time by the browser, either
+// before or after NP_Initialize, to retrieve the
+// pointers to the rest of the plugin functions that are
+// not exported from the DLL.
+////////////////////////////////////////////////////////////////////
NPError OSCALL
NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) {
open_logfile();
@@ -206,11 +110,204 @@ NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) {
return NPERR_NO_ERROR;
}
-// Symbol called once by the browser to shut down the plugin
+////////////////////////////////////////////////////////////////////
+// Function: NP_Shutdown
+// Description: This function is called when the browser is done with
+// the plugin; it asks the plugin to unload itself and
+// free all used resources.
+////////////////////////////////////////////////////////////////////
NPError OSCALL
NP_Shutdown(void) {
logfile << "shutdown\n" << flush;
unload_plugin();
+ // Not clear whether there's a return value or not. Some versions
+ // of the API have different opinions on this.
return NPERR_NO_ERROR;
}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_New
+// Description: Called by the browser to create a new instance of the
+// plugin.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
+ int16 argc, char *argn[], char *argv[], NPSavedData *saved) {
+ logfile << "new instance\n" << flush;
+
+ // Copy the tokens into a temporary array of P3D_token objects.
+ P3D_token *tokens = (P3D_token *)alloca(sizeof(P3D_token) * argc);
+ for (int i = 0; i < argc; ++i) {
+ P3D_token &token = tokens[i];
+ token._keyword = argn[i];
+ token._value = argv[i];
+ logfile << " " << i << ": " << token._keyword << " = " << token._value << "\n";
+ }
+
+ instance->pdata = P3D_create_instance(NULL, NULL, tokens, argc);
+
+ return NPERR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_Destroy
+// Description: Called by the browser to destroy an instance of the
+// plugin previously created with NPP_New.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_Destroy(NPP instance, NPSavedData **save) {
+ logfile << "destroy instance\n" << flush;
+ (*save) = NULL;
+ P3D_instance_finish((P3D_instance *)(instance->pdata));
+ instance->pdata = NULL;
+
+ return NPERR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_SetWindow
+// Description: Called by the browser to inform the instance of its
+// window size and placement. This is called initially
+// to create the window, and may be called subsequently
+// when the window needs to be moved. It may be called
+// redundantly.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_SetWindow(NPP instance, NPWindow *window) {
+ logfile << "SetWindow " << window->x << ", " << window->y
+ << ", " << window->width << ", " << window->height
+ << "\n" << flush;
+
+ P3D_instance *inst = (P3D_instance *)(instance->pdata);
+ assert(inst != NULL);
+
+ P3D_window_handle parent_window;
+#ifdef _WIN32
+ parent_window._hwnd = (HWND)(window->window);
+#endif
+
+ P3D_instance_setup_window
+ (inst, P3D_WT_embedded,
+ window->x, window->y, window->width, window->height,
+ parent_window);
+
+ return NPERR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_NewStream
+// Description: Called by the browser when a new data stream is
+// created, usually in response to a geturl request; but
+// it is also called initially to supply the data in the
+// data or src element. The plugin must specify how it
+// can receive the stream.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream,
+ NPBool seekable, uint16 *stype) {
+ logfile << "NewStream " << type << ", " << stream->url
+ << ", " << stream->end << "\n" << flush;
+ *stype = NP_ASFILEONLY;
+ return NPERR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_DestroyStream
+// Description: Called by the browser to mark the end of a stream
+// created with NewStream.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) {
+ logfile << "DestroyStream\n" << flush;
+ return NPERR_NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_WriteReady
+// Description: Called by the browser to ask how many bytes it can
+// deliver for a stream.
+////////////////////////////////////////////////////////////////////
+int32
+NPP_WriteReady(NPP instance, NPStream *stream) {
+ logfile << "WriteReady\n";
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_Write
+// Description: Called by the browser to deliver bytes for the
+// stream; the plugin should return the number of bytes
+// consumed.
+////////////////////////////////////////////////////////////////////
+int32
+NPP_Write(NPP instance, NPStream *stream, int32 offset,
+ int32 len, void *buffer) {
+ logfile << "Write\n";
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_StreamAsFile
+// Description: Called by the browser to report the filename that
+// contains the fully-downloaded stream, if
+// NP_ASFILEONLY was specified by the plugin in
+// NPP_NewStream.
+////////////////////////////////////////////////////////////////////
+void
+NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) {
+ logfile << "StreamAsFile: " << fname << "\n" << flush;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_Print
+// Description: Called by the browser when the user attempts to print
+// the page containing the plugin instance.
+////////////////////////////////////////////////////////////////////
+void
+NPP_Print(NPP instance, NPPrint *platformPrint) {
+ logfile << "Print\n";
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_HandleEvent
+// Description: Called by the browser to inform the plugin of OS
+// window events.
+////////////////////////////////////////////////////////////////////
+int16
+NPP_HandleEvent(NPP instance, void *event) {
+ logfile << "HandleEvent\n";
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_URLNotify
+// Description: Called by the browser to inform the plugin of a
+// completed URL request.
+////////////////////////////////////////////////////////////////////
+void
+NPP_URLNotify(NPP instance, const char *url,
+ NPReason reason, void *notifyData) {
+ logfile << "URLNotify: " << url << "\n";
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_GetValue
+// Description: Called by the browser to query specific information
+// from the plugin.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
+ logfile << "GetValue " << variable << "\n";
+ return NPERR_GENERIC_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////
+// Function: NPP_URLNotify
+// Description: Called by the browser to update a scriptable value.
+////////////////////////////////////////////////////////////////////
+NPError
+NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
+ logfile << "SetValue " << variable << "\n";
+ return NPERR_GENERIC_ERROR;
+}