/blender-2.63a/source/gameengine/GamePlayer/xembed/UnixShell.c
C | 555 lines | 325 code | 112 blank | 118 comment | 67 complexity | e52c20549af690f34448de0bc0b9c969 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Enrico Fracasso
- *
- * ***** END GPL LICENSE BLOCK *****
- * NS api template, adapted to link to our own internals.
- */
- #define MOZ_X11 1
- /* -*- Mode: C; tab-width: 8; c-set-style: bsd -*- */
- /* UnixShell.c was adapted from the template in the Netscape API. */
- /* System: */
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- /* All nsapi stuff. nsapi now needs FILE, so include stdio as well. */
- #include <stdio.h>
- #include "npapi.h"
- /* Native hooks: */
- #include "npapi.h"
- /* Threading the NSPR way: */
- #include "prthread.h"
- #include "prlock.h"
- #include "blender_plugin_types.h"
- #include <signal.h>
- /* --------------------------------------------------------------------- */
- /** If defined: write to the plugin log file */
- #if defined(DEBUG)
- #define NZC_GENERATE_LOG
- #endif
- int32 STREAMBUFSIZE;
- /** Generate a log file. */
- static void
- log_entry(char* msg);
- void
- execute_blenderplayer(BlenderPluginInstance*);
- /* --------------------------------------------------------------------- */
- /* Implementations: */
- /* --------------------------------------------------------------------- */
- /* NPP_GetMIMEDescription() and NPP_GetValue() are called to determine
- * the mime types supported by this plugin. */
- char*
- NPP_GetMIMEDescription(void)
- {
- log_entry("NPP_GetMIMEDescription");
- return("application/x-blender-plugin:blend:Blender 3D web plugin");
- }
- NPError
- NPP_GetValue(
- NPP instance,
- NPPVariable variable,
- void *value
- )
- {
- NPError err = NPERR_NO_ERROR;
-
- log_entry("NPP_GetValue");
- switch (variable) {
- case NPPVpluginNeedsXEmbed:
- log_entry("NPP_GetValue::NPPVpluginNeedsXEmbed");
- *((PRBool *)value) = PR_TRUE;
- break;
- case NPPVpluginNameString:
- log_entry("NPP_GetValue::NPPVpluginNameString");
- *((char **)value) = "Blender";
- break;
- case NPPVpluginDescriptionString:
- log_entry("NPP_GetValue::NPPVpluginDescriptionString");
- *((char **)value) = "Player for interactive 3D content";
- break;
- case NPPVpluginWindowBool:
- log_entry("NPP_GetValue::NPPVpluginWindowBool");
- *((PRBool *)value) = PR_FALSE; //not windowless
- break;
- case NPPVpluginTransparentBool:
- log_entry("NPP_GetValue::NPPVpluginTransparentBool");
- *((PRBool *)value) = PR_FALSE; // not trasparent
- break;
- default:
- err = NPERR_GENERIC_ERROR;
- }
- return err;
- }
- /* --------------------------------------------------------------------- */
- /* Mozilla: NPP_Initialize() is called when
- * starting the browser, and then every time the plugin is started*/
- NPError
- NPP_Initialize(void)
- {
- log_entry("NPP_Initialize");
- return NPERR_NO_ERROR;
- }
- /* --------------------------------------------------------------------- */
- void
- NPP_Shutdown(void)
- {
- log_entry("NPP_Shutdown");
- }
- NPError
- NPP_New(
- NPMIMEType pluginType,
- NPP instance,
- uint16 mode,
- int16 argc,
- char* argn[],
- char* argv[],
- NPSavedData* saved
- )
- {
- BlenderPluginInstance* This = NULL;
- int i = 0;
- int retval = 0;
- log_entry("NPP_New");
-
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
-
- instance->pdata = NPN_MemAlloc(sizeof(BlenderPluginInstance));
- if (instance->pdata == 0)
- return NPERR_OUT_OF_MEMORY_ERROR;
-
- This = (BlenderPluginInstance*) instance->pdata;
- This->browser_instance = instance;
- This->pID = 0;
- This->blend_file = 0;
- This->temp_mail_file_name = 0;
- This->main_file_store = 0;
- This->display = NULL;
- This->window = 0;
- /* Parse the options from the file. Should I do this in the
- * implementation file maybe? Now we do a lot with
- * instance-specific data. */
- /*
- while (i <argc ) {
- if (!strcmp(argn[i],"src")) {
- The blend file to load.
- int url_len = strlen(argv[i]);
- if ((url_len > 0) && (url_len < 4096) ) {
- This->blend_file = NPN_MemAlloc(url_len + 1);
- if (This->blend_file == 0)
- return NPERR_OUT_OF_MEMORY_ERROR;
- strcpy(This->blend_file, argv[i]);
-
- retval = NPN_GetURL(This->browser_instance,
- This->blend_file,
- NULL);
- if (retval != NPERR_NO_ERROR) {
- log_entry("Cannot read animation");
- NPN_Status(instance, "Cannot read animation file");
- This->blend_file = NULL;
- return NPERR_NO_ERROR;
- }
- else {
- log_entry("Animation loaded");
- }
- }
- }
- i++;
- }*/
-
- if (This != NULL) {
- return NPERR_NO_ERROR;
- }
- else {
- return NPERR_OUT_OF_MEMORY_ERROR;
- }
- }
- NPError
- NPP_Destroy( NPP instance, NPSavedData** save )
- {
- BlenderPluginInstance* This;
- log_entry("NPP_Destroy");
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- This = (BlenderPluginInstance*) instance->pdata;
- printf("NPP_Destroy ID: 0x%x %d\n", This->window, This->window);
- if (This != NULL) {
- if (This->pID != 0) {
- #ifdef WITH_PRIVSEP
- kill(This->pID, SIGTERM);
- #else
- kill(This->pID, SIGKILL); //if I have to kill blenderplayer directly I need to send SIGKILL
- #endif
- wait(This->pID);
- unlink(This->temp_mail_file_name);
- }
- // sometimes FF doesn't delete it's own window...
- //printf("%s\n", NPN_UserAgent(instance));
- /*if (This->display != NULL && This->window != 0)
- XDestroyWindow(This->display, This->window);
- */
- if (This->blend_file) NPN_MemFree(This->blend_file);
- if (This->temp_mail_file_name) NPN_MemFree(This->temp_mail_file_name);
- if (This->main_file_store) NPN_MemFree(This->main_file_store);
- NPN_MemFree(instance->pdata);
- instance->pdata = NULL;
- }
- return NPERR_NO_ERROR;
- }
- NPError
- NPP_SetWindow( NPP instance,NPWindow* window )
- {
- BlenderPluginInstance* This;
- log_entry("NPP_SetWindow");
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- /* window handle */
- if ((window == NULL) || (window->window == NULL)) {
- return NPERR_NO_ERROR; /* mmmmmm */
- }
-
- if (window->ws_info == NULL)
- return NPERR_NO_ERROR; /* mmmmmm */
- This = (BlenderPluginInstance*) instance->pdata;
- if (This) {
- This->window = (Window) window->window;
- NPSetWindowCallbackStruct* window_info = window->ws_info;
- This->display = window_info->display;
- printf("ID window 0x%x %d\n", window->window, window->window);
- return NPERR_NO_ERROR;
- }
- else {
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- }
- NPError
- NPP_NewStream(
- NPP instance,
- NPMIMEType type,
- NPStream *stream,
- NPBool seekable,
- uint16 *stype
- )
- {
- //NPByteRange range;
- BlenderPluginInstance* This;
- log_entry("NPP_NewStream");
-
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- This = (BlenderPluginInstance*) instance->pdata;
- if (!This)
- return NPERR_INVALID_INSTANCE_ERROR;
- printf("Loading main file %s (%s)\n", stream->url, type);
- if ( strcmp(type,"text/html") == 0 ) // original HTML file
- return NPERR_NO_ERROR;
-
- This->stream_total = stream->end;
- This->stream_retrieved = 0;
- This->main_file_store = NPN_MemAlloc(stream->end*sizeof(unsigned char));
- if (!This->main_file_store) {
- fprintf(stderr, "Blender plugin: Out of memory! "
- "Cannot get chunk for loading animation.\n");
- return NPERR_OUT_OF_MEMORY_ERROR;
- }
- This->main_file_stream = stream;
- return NPERR_NO_ERROR;
-
- }
- /* PLUGIN DEVELOPERS:
- * These next 2 functions are directly relevant in a plug-in which
- * handles the data in a streaming manner. If you want zero bytes
- * because no buffer space is YET available, return 0. As long as
- * the stream has not been written to the plugin, Navigator will
- * continue trying to send bytes. If the plugin doesn't want them,
- * just return some large number from NPP_WriteReady(), and
- * ignore them in NPP_Write(). For a NP_ASFILE stream, they are
- * still called but can safely be ignored using this strategy.
- */
- int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
- * mode so we can take any size stream in our
- * write call (since we ignore it) */
- int32
- NPP_WriteReady(
- NPP instance,
- NPStream *stream
- )
- {
- BlenderPluginInstance* This = NULL;
- int acceptable = 0;
-
- log_entry("NPP_WriteReady");
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- This = (BlenderPluginInstance*) instance->pdata;
- if (This == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- /* Check whether buffers already exist: */
- if ((This->main_file_stream && This->main_file_store)) {
- acceptable = STREAMBUFSIZE;
- }
-
-
- return acceptable;
- }
- int32
- NPP_Write(
- NPP instance,
- NPStream *stream,
- int32 offset,
- int32 len,
- void *buffer
- )
- {
- BlenderPluginInstance* This = NULL;
- int accepted = 0;
-
- log_entry("NPP_Write");
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
-
- This = (BlenderPluginInstance*) instance->pdata;
- if (This == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
-
- if (stream == This->main_file_stream) {
- log_entry("NPP_Write: loading main_file_stream");
- memcpy(((unsigned char*)This->main_file_store) + This->stream_retrieved, buffer, len);
- accepted = len;
- This->stream_retrieved += len;
- if (This->stream_retrieved >= This->stream_total) {
- log_entry("NPP_Write: main_file_stream loaded");
- execute_blenderplayer(This);
- }
- }
- else {
- /* the stream ref wasn't set yet..*/
- log_entry("NPP_Write: not main stream");
- log_entry(stream->url);
- accepted = len;
- }
- return accepted;
- }
- NPError
- NPP_DestroyStream(
- NPP instance,
- NPStream *stream,
- NPError reason
- )
- {
- BlenderPluginInstance* This = NULL;
- log_entry("NPP_DestroyStream");
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- This = (BlenderPluginInstance*) instance->pdata;
- if (This) {
- if (reason != NPRES_DONE) {
- if (stream == This->main_file_stream) {
- // stream destroyed by NPP_Destroy
- NPN_Status(instance, "Cannot read animation file");
- //main_file_failed(This->application);
- }
- }
- return NPERR_NO_ERROR;
- }
- else {
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- }
- /* Not supposed to be called anymore... Anyway, we don't need the
- * results. Some Moz implementations will call this one regardless the
- * desired transfer mode! */
- void
- NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname )
- {
- /* log_entry("NPP_StreamAsFile"); */
- }
- void
- NPP_Print(NPP instance, NPPrint* printInfo )
- {
-
- log_entry("NPP_Print");
- if (printInfo == NULL)
- return;
- if (instance != NULL) {
- if (printInfo->mode == NP_FULL) {
- printInfo->print.fullPrint.pluginPrinted = FALSE;
- }
- else { /* If not fullscreen, we must be embedded */
- }
- }
- }
- void
- execute_blenderplayer(BlenderPluginInstance* instance)
- {
- char file_name[] = "/tmp/blender.XXXXXX";
- int fd = mkstemp(file_name);
- ssize_t real_size = write(fd, instance->main_file_store, instance->stream_retrieved);
- close(fd);
- instance->temp_mail_file_name = NPN_MemAlloc(strlen(file_name) + 1);
- strcpy(instance->temp_mail_file_name, file_name);
- instance->pID = fork();
- //XSelectInput(This->display , This->window, SubstructureNotifyMask);
- //XSync(This->display, FALSE);
-
- #if defined(WITH_APPARMOR)
- const char* executable = "blenderplayer-web";
- #elif defined(WITH_PRIVSEP)
- const char* executable = "blenderplayer-wrapper";
- #else
- const char* executable = "blenderplayer";
- #endif
- if (instance->pID == 0) { // child
- char window_id[50];
- sprintf(window_id, "%d", instance->window);
- //exit(0);
- #ifdef WITH_PRIVSEP
- execlp(executable, executable, file_name, window_id, (char*)NULL);
- #else
- execlp(executable, executable, "-i", window_id, file_name, (char*)NULL);
- #endif
-
- }
- else if (instance->pID < 0) { // failed to fork
- printf("Failed to fork!!!\n");
- }
- /*XEvent e;
- int started = 0;
- while (!started) {
- XNextEvent(This->display, &e);
- printf("Event type %d\n", e.type);
- if (e.type == MapNotify) {
- started = 1;
- XCreateWindowEvent event = e.xcreatewindow;
- printf("Created window x:%d, y: %d, h: %d, w: %d\n", event.x, event.y, event.height, event.width);
- }
- }*/
- }
- /* --------------------------------------------------------------------- */
- static void
- log_entry(char* msg)
- {
- #ifdef NZC_GENERATE_LOG
- FILE* fp = fopen("/tmp/plugin_log","a");
- if (!fp) return;
- fprintf(fp, "--> Unixshell:: %s\n",
- msg);
- fflush(fp);
- fclose (fp);
- #endif
- }
- /* --------------------------------------------------------------------- */