2
* ***** BEGIN GPL LICENSE BLOCK *****
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19
* All rights reserved.
21
* The Original Code is: all of this file.
23
* Contributor(s): Enrico Fracasso
25
* ***** END GPL LICENSE BLOCK *****
26
* NS api template, adapted to link to our own internals.
31
/* UnixShell.c was adapted from the template in the Netscape API. */
38
/* All nsapi stuff. nsapi now needs FILE, so include stdio as well. */
45
/* Threading the NSPR way: */
49
#include "blender_plugin_types.h"
53
/* --------------------------------------------------------------------- */
55
/** If defined: write to the plugin log file */
57
#define NZC_GENERATE_LOG
62
/** Generate a log file. */
68
execute_blenderplayer(BlenderPluginInstance *);
70
/* --------------------------------------------------------------------- */
71
/* Implementations: */
72
/* --------------------------------------------------------------------- */
74
/* NPP_GetMIMEDescription() and NPP_GetValue() are called to determine
75
* the mime types supported by this plugin. */
77
NPP_GetMIMEDescription(void)
79
log_entry("NPP_GetMIMEDescription");
80
return("application/x-blender-plugin:blend:Blender 3D web plugin");
90
NPError err = NPERR_NO_ERROR;
92
log_entry("NPP_GetValue");
95
case NPPVpluginNeedsXEmbed:
96
log_entry("NPP_GetValue::NPPVpluginNeedsXEmbed");
97
*((PRBool *)value) = PR_TRUE;
99
case NPPVpluginNameString:
100
log_entry("NPP_GetValue::NPPVpluginNameString");
101
*((char **)value) = "Blender";
103
case NPPVpluginDescriptionString:
104
log_entry("NPP_GetValue::NPPVpluginDescriptionString");
105
*((char **)value) = "Player for interactive 3D content";
107
case NPPVpluginWindowBool:
108
log_entry("NPP_GetValue::NPPVpluginWindowBool");
109
*((PRBool *)value) = PR_FALSE; //not windowless
111
case NPPVpluginTransparentBool:
112
log_entry("NPP_GetValue::NPPVpluginTransparentBool");
113
*((PRBool *)value) = PR_FALSE; // not trasparent
116
err = NPERR_GENERIC_ERROR;
121
/* --------------------------------------------------------------------- */
122
/* Mozilla: NPP_Initialize() is called when
123
* starting the browser, and then every time the plugin is started*/
127
log_entry("NPP_Initialize");
128
return NPERR_NO_ERROR;
131
/* --------------------------------------------------------------------- */
136
log_entry("NPP_Shutdown");
142
NPMIMEType pluginType,
151
BlenderPluginInstance *This = NULL;
155
log_entry("NPP_New");
157
if (instance == NULL)
158
return NPERR_INVALID_INSTANCE_ERROR;
160
instance->pdata = NPN_MemAlloc(sizeof(BlenderPluginInstance));
161
if (instance->pdata == 0)
162
return NPERR_OUT_OF_MEMORY_ERROR;
164
This = (BlenderPluginInstance *) instance->pdata;
165
This->browser_instance = instance;
167
This->blend_file = 0;
168
This->temp_mail_file_name = 0;
169
This->main_file_store = 0;
170
This->display = NULL;
173
/* Parse the options from the file. Should I do this in the
174
* implementation file maybe? Now we do a lot with
175
* instance-specific data. */
178
if (!strcmp(argn[i],"src")) {
179
The blend file to load.
180
int url_len = strlen(argv[i]);
181
if ((url_len > 0) && (url_len < 4096) ) {
182
This->blend_file = NPN_MemAlloc(url_len + 1);
183
if (This->blend_file == 0)
184
return NPERR_OUT_OF_MEMORY_ERROR;
185
strcpy(This->blend_file, argv[i]);
187
retval = NPN_GetURL(This->browser_instance,
190
if (retval != NPERR_NO_ERROR) {
191
log_entry("Cannot read animation");
192
NPN_Status(instance, "Cannot read animation file");
193
This->blend_file = NULL;
194
return NPERR_NO_ERROR;
197
log_entry("Animation loaded");
205
return NPERR_NO_ERROR;
208
return NPERR_OUT_OF_MEMORY_ERROR;
214
NPP_Destroy( NPP instance, NPSavedData** save )
216
BlenderPluginInstance *This;
218
log_entry("NPP_Destroy");
220
if (instance == NULL)
221
return NPERR_INVALID_INSTANCE_ERROR;
223
This = (BlenderPluginInstance *) instance->pdata;
224
printf("NPP_Destroy ID: 0x%x %d\n", This->window, This->window);
228
if (This->pID != 0) {
230
kill(This->pID, SIGTERM);
232
kill(This->pID, SIGKILL); //if I have to kill blenderplayer directly I need to send SIGKILL
235
unlink(This->temp_mail_file_name);
238
/* sometimes FF doesn't delete it's own window... */
239
//printf("%s\n", NPN_UserAgent(instance));
240
/*if (This->display != NULL && This->window != 0)
241
XDestroyWindow(This->display, This->window);
243
if (This->blend_file) NPN_MemFree(This->blend_file);
244
if (This->temp_mail_file_name) NPN_MemFree(This->temp_mail_file_name);
245
if (This->main_file_store) NPN_MemFree(This->main_file_store);
246
NPN_MemFree(instance->pdata);
247
instance->pdata = NULL;
250
return NPERR_NO_ERROR;
256
NPP_SetWindow( NPP instance,NPWindow* window )
258
BlenderPluginInstance *This;
260
log_entry("NPP_SetWindow");
262
if (instance == NULL)
263
return NPERR_INVALID_INSTANCE_ERROR;
266
if ((window == NULL) || (window->window == NULL)) {
267
return NPERR_NO_ERROR; /* mmmmmm */
270
if (window->ws_info == NULL)
271
return NPERR_NO_ERROR; /* mmmmmm */
273
This = (BlenderPluginInstance *) instance->pdata;
276
This->window = (Window) window->window;
278
NPSetWindowCallbackStruct* window_info = window->ws_info;
279
This->display = window_info->display;
281
printf("ID window 0x%x %d\n", window->window, window->window);
282
return NPERR_NO_ERROR;
285
return NPERR_INVALID_INSTANCE_ERROR;
300
BlenderPluginInstance *This;
302
log_entry("NPP_NewStream");
304
if (instance == NULL)
305
return NPERR_INVALID_INSTANCE_ERROR;
307
This = (BlenderPluginInstance *) instance->pdata;
310
return NPERR_INVALID_INSTANCE_ERROR;
312
printf("Loading main file %s (%s)\n", stream->url, type);
313
if (strcmp(type, "text/html") == 0) /* original HTML file */
314
return NPERR_NO_ERROR;
316
This->stream_total = stream->end;
317
This->stream_retrieved = 0;
318
This->main_file_store = NPN_MemAlloc(stream->end*sizeof(unsigned char));
319
if (!This->main_file_store) {
320
fprintf(stderr, "Blender plugin: Out of memory! "
321
"Cannot get chunk for loading animation.\n");
322
return NPERR_OUT_OF_MEMORY_ERROR;
325
This->main_file_stream = stream;
327
return NPERR_NO_ERROR;
332
/* PLUGIN DEVELOPERS:
333
* These next 2 functions are directly relevant in a plug-in which
334
* handles the data in a streaming manner. If you want zero bytes
335
* because no buffer space is YET available, return 0. As long as
336
* the stream has not been written to the plugin, Navigator will
337
* continue trying to send bytes. If the plugin doesn't want them,
338
* just return some large number from NPP_WriteReady(), and
339
* ignore them in NPP_Write(). For a NP_ASFILE stream, they are
340
* still called but can safely be ignored using this strategy.
343
int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
344
* mode so we can take any size stream in our
345
* write call (since we ignore it) */
353
BlenderPluginInstance *This = NULL;
356
log_entry("NPP_WriteReady");
358
if (instance == NULL)
359
return NPERR_INVALID_INSTANCE_ERROR;
361
This = (BlenderPluginInstance *) instance->pdata;
364
return NPERR_INVALID_INSTANCE_ERROR;
366
/* Check whether buffers already exist: */
368
if ((This->main_file_stream && This->main_file_store)) {
369
acceptable = STREAMBUFSIZE;
386
BlenderPluginInstance *This = NULL;
389
log_entry("NPP_Write");
391
if (instance == NULL)
392
return NPERR_INVALID_INSTANCE_ERROR;
394
This = (BlenderPluginInstance *) instance->pdata;
397
return NPERR_INVALID_INSTANCE_ERROR;
400
if (stream == This->main_file_stream) {
401
log_entry("NPP_Write: loading main_file_stream");
402
memcpy(((unsigned char*)This->main_file_store) + This->stream_retrieved, buffer, len);
404
This->stream_retrieved += len;
405
if (This->stream_retrieved >= This->stream_total) {
406
log_entry("NPP_Write: main_file_stream loaded");
407
execute_blenderplayer(This);
411
/* the stream ref wasn't set yet..*/
412
log_entry("NPP_Write: not main stream");
413
log_entry(stream->url);
430
BlenderPluginInstance *This = NULL;
432
log_entry("NPP_DestroyStream");
434
if (instance == NULL)
435
return NPERR_INVALID_INSTANCE_ERROR;
436
This = (BlenderPluginInstance *) instance->pdata;
439
if (reason != NPRES_DONE) {
440
if (stream == This->main_file_stream) {
441
/* stream destroyed by NPP_Destroy */
442
NPN_Status(instance, "Cannot read animation file");
443
/* main_file_failed(This->application); */
446
return NPERR_NO_ERROR;
449
return NPERR_INVALID_INSTANCE_ERROR;
455
/* Not supposed to be called anymore... Anyway, we don't need the
456
* results. Some Moz implementations will call this one regardless the
457
* desired transfer mode! */
459
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname )
461
/* log_entry("NPP_StreamAsFile"); */
466
NPP_Print(NPP instance, NPPrint* printInfo )
469
log_entry("NPP_Print");
470
if (printInfo == NULL)
472
if (instance != NULL) {
473
if (printInfo->mode == NP_FULL) {
474
printInfo->print.fullPrint.pluginPrinted = FALSE;
476
else { /* If not fullscreen, we must be embedded */
483
execute_blenderplayer(BlenderPluginInstance *instance)
486
char file_name[] = "/tmp/blender.XXXXXX";
487
int fd = mkstemp(file_name);
489
ssize_t real_size = write(fd, instance->main_file_store, instance->stream_retrieved);
492
instance->temp_mail_file_name = NPN_MemAlloc(strlen(file_name) + 1);
493
strcpy(instance->temp_mail_file_name, file_name);
495
instance->pID = fork();
496
//XSelectInput(This->display, This->window, SubstructureNotifyMask);
497
//XSync(This->display, FALSE);
500
#if defined(WITH_APPARMOR)
501
const char* executable = "blenderplayer-web";
502
#elif defined(WITH_PRIVSEP)
503
const char* executable = "blenderplayer-wrapper";
505
const char* executable = "blenderplayer";
508
if (instance->pID == 0) { // child
510
sprintf(window_id, "%d", instance->window);
513
execlp(executable, executable, file_name, window_id, (char*)NULL);
515
execlp(executable, executable, "-i", window_id, file_name, (char*)NULL);
519
else if (instance->pID < 0) { // failed to fork
520
printf("Failed to fork!!!\n");
526
XNextEvent(This->display, &e);
527
printf("Event type %d\n", e.type);
528
if (e.type == MapNotify) {
530
XCreateWindowEvent event = e.xcreatewindow;
531
printf("Created window x:%d, y: %d, h: %d, w: %d\n", event.x, event.y, event.height, event.width);
538
/* --------------------------------------------------------------------- */
543
#ifdef NZC_GENERATE_LOG
544
FILE* fp = fopen("/tmp/plugin_log", "a");
546
fprintf(fp, "--> Unixshell:: %s\n",
553
/* --------------------------------------------------------------------- */