~ubuntu-branches/ubuntu/lucid/blender/lucid

« back to all changes in this revision

Viewing changes to source/gameengine/GamePlayer/xembed/UnixShell.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2009-08-06 22:32:19 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090806223219-8z4eej1u8levu4pz
Tags: 2.49a+dfsg-0ubuntu1
* Merge from debian unstable, remaining changes:
  - debian/control: Build-depend on python-2.6 rather than python-2.5.
  - debian/misc/*.desktop: Add Spanish translation to .desktop 
    files.
  - debian/pyversions: 2.6.
  - debian/rules: Clean *.o of source/blender/python/api2_2x/
* New upstream release (LP: #382153).
* Refreshed patches:
  - 01_sanitize_sys.patch
  - 02_tmp_in_HOME
  - 10_use_systemwide_ftgl
  - 70_portability_platform_detection
* Removed patches merged upstream:
  - 30_fix_python_syntax_warning
  - 90_ubuntu_ffmpeg_52_changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * $Id: UnixShell.c 16961 2008-10-07 17:13:35Z eof $
3
 
 *
4
 
 * ***** BEGIN GPL LICENSE BLOCK *****
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU General Public License
8
 
 * as published by the Free Software Foundation; either version 2
9
 
 * of the License, or (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software Foundation,
18
 
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
 
 *
20
 
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21
 
 * All rights reserved.
22
 
 *
23
 
 * The Original Code is: all of this file.
24
 
 *
25
 
 * Contributor(s): Enrico Fracasso
26
 
 *
27
 
 * ***** END GPL LICENSE BLOCK *****
28
 
 * NS api template, adapted to link to our own internals.
29
 
 */
30
 
 
31
 
#define UNIXSH_VERSION "$Id: UnixShell.c 16961 2008-10-07 17:13:35Z eof $"
32
 
#define MOZ_X11 1
33
 
 
34
 
/* -*- Mode: C; tab-width: 8; c-set-style: bsd -*- */
35
 
 
36
 
/* UnixShell.c was adapted from the template in the Netscape API. */
37
 
 
38
 
/* System: */     
39
 
#include <string.h>
40
 
#include <stdlib.h>
41
 
#include <unistd.h>
42
 
 
43
 
/* All nsapi stuff. nsapi now needs FILE, so include stdio as well. */
44
 
#include <stdio.h>
45
 
#include "npapi.h"
46
 
 
47
 
#ifdef HAVE_CONFIG_H
48
 
#include <config.h>
49
 
#endif
50
 
 
51
 
/* Native hooks: */
52
 
#include "npapi.h"
53
 
 
54
 
/* Threading the NSPR way: */
55
 
#include "prthread.h"
56
 
#include "prlock.h"
57
 
 
58
 
#include "blender_plugin_types.h"
59
 
 
60
 
#include <signal.h>
61
 
 
62
 
/* --------------------------------------------------------------------- */
63
 
 
64
 
/** If defined: write to the plugin log file */
65
 
#ifndef NDEBUG
66
 
#define NZC_GENERATE_LOG
67
 
#endif
68
 
 
69
 
int32 STREAMBUFSIZE;
70
 
 
71
 
/** Generate a log file. */
72
 
static void
73
 
log_entry(char* msg);
74
 
 
75
 
 
76
 
void
77
 
execute_blenderplayer(BlenderPluginInstance*);
78
 
 
79
 
/* --------------------------------------------------------------------- */
80
 
/* Implementations:                                                      */
81
 
/* --------------------------------------------------------------------- */
82
 
 
83
 
/* NPP_GetMIMEDescription() and NPP_GetValue() are called to determine
84
 
 * the mime types supported by this plugin. */
85
 
char*
86
 
NPP_GetMIMEDescription( void )
87
 
{
88
 
        log_entry("NPP_GetMIMEDescription");
89
 
        return("application/x-blender-plugin:blend:Blender 3D web plugin");
90
 
}
91
 
 
92
 
NPError
93
 
NPP_GetValue(
94
 
        NPP instance,
95
 
        NPPVariable variable,
96
 
        void *value
97
 
        )
98
 
{
99
 
        NPError err = NPERR_NO_ERROR;
100
 
        
101
 
        log_entry("NPP_GetValue");
102
 
 
103
 
        switch (variable) {
104
 
        case NPPVpluginNeedsXEmbed:
105
 
                log_entry("NPP_GetValue::NPPVpluginNeedsXEmbed");
106
 
                *((PRBool *)value) = PR_TRUE;
107
 
                break;
108
 
        case NPPVpluginNameString:
109
 
                log_entry("NPP_GetValue::NPPVpluginNameString");
110
 
                *((char **)value) = "Blender";
111
 
                break;
112
 
        case NPPVpluginDescriptionString:
113
 
                log_entry("NPP_GetValue::NPPVpluginDescriptionString");
114
 
                *((char **)value) = "Player for interactive 3D content";
115
 
                break;
116
 
        case NPPVpluginWindowBool:
117
 
                log_entry("NPP_GetValue::NPPVpluginWindowBool");
118
 
                *((PRBool *)value) = PR_FALSE; //not windowless
119
 
                break;
120
 
        case NPPVpluginTransparentBool:
121
 
                log_entry("NPP_GetValue::NPPVpluginTransparentBool");
122
 
                *((PRBool *)value) = PR_FALSE; // not trasparent
123
 
                break;
124
 
        default:
125
 
                err = NPERR_GENERIC_ERROR;
126
 
        }
127
 
        return err;
128
 
}
129
 
 
130
 
/* --------------------------------------------------------------------- */
131
 
/* Mozilla: NPP_Initialize() is called when
132
 
 * starting the browser, and then every time the plugin is started*/
133
 
NPError
134
 
NPP_Initialize(void)
135
 
{
136
 
        log_entry("NPP_Initialize");
137
 
        return NPERR_NO_ERROR;
138
 
}
139
 
 
140
 
/* --------------------------------------------------------------------- */
141
 
 
142
 
void
143
 
NPP_Shutdown(void)
144
 
{
145
 
        log_entry("NPP_Shutdown");
146
 
}
147
 
 
148
 
 
149
 
NPError 
150
 
NPP_New(
151
 
        NPMIMEType pluginType,
152
 
        NPP instance,
153
 
        uint16 mode,
154
 
        int16 argc,
155
 
        char* argn[],
156
 
        char* argv[],
157
 
        NPSavedData* saved
158
 
        )
159
 
{
160
 
        BlenderPluginInstance* This  = NULL;
161
 
        int i = 0;
162
 
        int retval = 0;
163
 
 
164
 
        log_entry("NPP_New");
165
 
        
166
 
        if (instance == NULL)
167
 
                return NPERR_INVALID_INSTANCE_ERROR;
168
 
        
169
 
        instance->pdata = NPN_MemAlloc(sizeof(BlenderPluginInstance));
170
 
        if (instance->pdata == 0)
171
 
                return NPERR_OUT_OF_MEMORY_ERROR;
172
 
        
173
 
        This = (BlenderPluginInstance*) instance->pdata;
174
 
        This->browser_instance = instance;
175
 
        This->pID = 0;
176
 
        This->blend_file = 0;
177
 
        This->temp_mail_file_name = 0;
178
 
        This->main_file_store = 0;
179
 
        This->display = NULL;
180
 
        This->window = 0;
181
 
 
182
 
        /* Parse the options from the file. Should I do this in the
183
 
         * implementation file maybe? Now we do a lot with
184
 
         * instance-specific data. */
185
 
        /*
186
 
        while (i <argc ) {
187
 
                if (!strcmp(argn[i],"src")) {
188
 
                        The blend file to load. 
189
 
                        int url_len = strlen(argv[i]);
190
 
                        if ((url_len > 0) && (url_len < 4096) ) {
191
 
                                This->blend_file = NPN_MemAlloc(url_len + 1);
192
 
                                if (This->blend_file == 0)
193
 
                                        return NPERR_OUT_OF_MEMORY_ERROR;
194
 
                                strcpy(This->blend_file, argv[i]);
195
 
                                
196
 
                                retval = NPN_GetURL(This->browser_instance,
197
 
                                                    This->blend_file,
198
 
                                                    NULL);
199
 
                                if (retval != NPERR_NO_ERROR) {
200
 
                                        log_entry("Cannot read animation");
201
 
                                        NPN_Status(instance, "Cannot read animation file");
202
 
                                        This->blend_file = NULL;
203
 
                                        return NPERR_NO_ERROR;
204
 
                                } else
205
 
                                        log_entry("Animation loaded"); 
206
 
                        }
207
 
                }               
208
 
                i++;
209
 
        }*/
210
 
                
211
 
        if (This != NULL) {
212
 
                return NPERR_NO_ERROR;
213
 
        } else
214
 
                return NPERR_OUT_OF_MEMORY_ERROR;
215
 
}
216
 
 
217
 
 
218
 
NPError 
219
 
NPP_Destroy( NPP instance, NPSavedData** save )
220
 
{
221
 
        BlenderPluginInstance* This;
222
 
 
223
 
        log_entry("NPP_Destroy");
224
 
 
225
 
        if (instance == NULL)
226
 
                return NPERR_INVALID_INSTANCE_ERROR;
227
 
 
228
 
        This = (BlenderPluginInstance*) instance->pdata;
229
 
        printf("NPP_Destroy ID:  0x%x %d\n", This->window, This->window);
230
 
 
231
 
        if (This != NULL) {
232
 
 
233
 
                if (This->pID != 0) {
234
 
#ifdef WITH_PRIVSEP
235
 
                        kill(This->pID, SIGTERM);
236
 
#else 
237
 
                        kill(This->pID, SIGKILL); //if I have to kill blenderplayer directly I need to send SIGKILL
238
 
#endif
239
 
                        wait(This->pID);
240
 
                        unlink(This->temp_mail_file_name);
241
 
                }
242
 
 
243
 
                // sometimes FF doesn't delete it's own window...
244
 
                //printf("%s \n", NPN_UserAgent(instance));
245
 
                /*if (This->display != NULL && This->window != 0)
246
 
                        XDestroyWindow(This->display, This->window);
247
 
                */
248
 
                if (This->blend_file) NPN_MemFree(This->blend_file);
249
 
                if (This->temp_mail_file_name) NPN_MemFree(This->temp_mail_file_name);
250
 
                if (This->main_file_store) NPN_MemFree(This->main_file_store);
251
 
                NPN_MemFree(instance->pdata);
252
 
                instance->pdata = NULL;
253
 
        }       
254
 
 
255
 
        return NPERR_NO_ERROR;
256
 
}
257
 
 
258
 
 
259
 
 
260
 
NPError 
261
 
NPP_SetWindow( NPP instance,NPWindow* window ) 
262
 
{
263
 
        BlenderPluginInstance* This;
264
 
 
265
 
        log_entry("NPP_SetWindow");
266
 
 
267
 
        if (instance == NULL)
268
 
                return NPERR_INVALID_INSTANCE_ERROR;
269
 
 
270
 
        /* window handle */ 
271
 
        if ((window == NULL) || (window->window == NULL)) {
272
 
                return NPERR_NO_ERROR; /* mmmmmm  */
273
 
        }
274
 
        
275
 
        if (window->ws_info == NULL)
276
 
                return NPERR_NO_ERROR; /* mmmmmm  */
277
 
 
278
 
        This = (BlenderPluginInstance*) instance->pdata;
279
 
 
280
 
        if (This) {
281
 
                This->window = (Window) window->window;
282
 
 
283
 
                NPSetWindowCallbackStruct* window_info = window->ws_info;
284
 
                This->display = window_info->display;
285
 
 
286
 
                printf("ID window 0x%x %d\n", window->window, window->window);
287
 
                return NPERR_NO_ERROR;
288
 
        } else {
289
 
                return NPERR_INVALID_INSTANCE_ERROR;
290
 
        }
291
 
}
292
 
 
293
 
 
294
 
NPError 
295
 
NPP_NewStream(
296
 
        NPP instance,
297
 
        NPMIMEType type,
298
 
        NPStream *stream, 
299
 
        NPBool seekable,
300
 
        uint16 *stype
301
 
        )
302
 
{
303
 
        //NPByteRange range;
304
 
        BlenderPluginInstance* This;
305
 
 
306
 
        log_entry("NPP_NewStream");
307
 
        
308
 
        if (instance == NULL)
309
 
                return NPERR_INVALID_INSTANCE_ERROR;
310
 
 
311
 
        This = (BlenderPluginInstance*) instance->pdata;
312
 
 
313
 
        if (!This) 
314
 
                return NPERR_INVALID_INSTANCE_ERROR;
315
 
 
316
 
        printf("Loading main file %s (%s)\n", stream->url, type);
317
 
        if ( strcmp(type,"text/html") == 0 ) // original HTML file 
318
 
                return NPERR_NO_ERROR;
319
 
        
320
 
        This->stream_total = stream->end;
321
 
        This->stream_retrieved = 0;
322
 
        This->main_file_store = NPN_MemAlloc(stream->end*sizeof(unsigned char));
323
 
        if (!This->main_file_store) {
324
 
                fprintf(stderr, "Blender plugin: Out of memory! "
325
 
                        "Cannot get chunk for loading animation.\n");
326
 
                return NPERR_OUT_OF_MEMORY_ERROR;
327
 
        }
328
 
 
329
 
        This->main_file_stream = stream;
330
 
 
331
 
        return NPERR_NO_ERROR;
332
 
                
333
 
}
334
 
 
335
 
 
336
 
/* PLUGIN DEVELOPERS:
337
 
 *      These next 2 functions are directly relevant in a plug-in which
338
 
 *      handles the data in a streaming manner. If you want zero bytes
339
 
 *      because no buffer space is YET available, return 0. As long as
340
 
 *      the stream has not been written to the plugin, Navigator will
341
 
 *      continue trying to send bytes.  If the plugin doesn't want them,
342
 
 *      just return some large number from NPP_WriteReady(), and
343
 
 *      ignore them in NPP_Write().  For a NP_ASFILE stream, they are
344
 
 *      still called but can safely be ignored using this strategy.
345
 
 */
346
 
 
347
 
int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
348
 
                                   * mode so we can take any size stream in our
349
 
                                   * write call (since we ignore it) */
350
 
 
351
 
int32 
352
 
NPP_WriteReady(
353
 
        NPP instance,
354
 
        NPStream *stream
355
 
        )
356
 
{
357
 
        BlenderPluginInstance* This = NULL;
358
 
        int acceptable = 0;
359
 
        
360
 
        log_entry("NPP_WriteReady"); 
361
 
 
362
 
        if (instance == NULL)   
363
 
                return NPERR_INVALID_INSTANCE_ERROR;
364
 
 
365
 
        This = (BlenderPluginInstance*) instance->pdata;
366
 
 
367
 
        if (This == NULL)       
368
 
                return NPERR_INVALID_INSTANCE_ERROR;
369
 
 
370
 
        /* Check whether buffers already exist: */
371
 
 
372
 
        if ((This->main_file_stream && This->main_file_store)) {
373
 
                acceptable = STREAMBUFSIZE;
374
 
        }
375
 
        
376
 
        
377
 
        return acceptable;
378
 
}
379
 
 
380
 
 
381
 
int32 
382
 
NPP_Write(
383
 
        NPP instance,
384
 
        NPStream *stream,
385
 
        int32 offset,
386
 
        int32 len,
387
 
        void *buffer
388
 
        )
389
 
{
390
 
        BlenderPluginInstance* This = NULL;
391
 
        int accepted = 0;
392
 
        
393
 
        log_entry("NPP_Write"); 
394
 
 
395
 
        if (instance == NULL)   
396
 
                return NPERR_INVALID_INSTANCE_ERROR;
397
 
        
398
 
        This = (BlenderPluginInstance*) instance->pdata;
399
 
 
400
 
        if (This == NULL)       
401
 
                return NPERR_INVALID_INSTANCE_ERROR;
402
 
 
403
 
        
404
 
        if (stream == This->main_file_stream) {
405
 
                log_entry("NPP_Write: loading main_file_stream"); 
406
 
                memcpy(((unsigned char*)This->main_file_store) + This->stream_retrieved, buffer, len);
407
 
                accepted = len;
408
 
                This->stream_retrieved += len;
409
 
                if (This->stream_retrieved >= This->stream_total) {
410
 
                        log_entry("NPP_Write: main_file_stream loaded"); 
411
 
                        execute_blenderplayer(This);
412
 
                }
413
 
        } else {
414
 
                /* the stream ref wasn't set yet..*/
415
 
                log_entry("NPP_Write: not main stream"); 
416
 
                log_entry(stream->url);
417
 
 
418
 
                accepted = len;
419
 
        }
420
 
 
421
 
        return accepted;
422
 
}
423
 
 
424
 
 
425
 
 
426
 
NPError 
427
 
NPP_DestroyStream(
428
 
        NPP instance,
429
 
        NPStream *stream,
430
 
        NPError reason
431
 
        )
432
 
{
433
 
        BlenderPluginInstance* This = NULL;
434
 
 
435
 
        log_entry("NPP_DestroyStream");
436
 
 
437
 
        if (instance == NULL)
438
 
                return NPERR_INVALID_INSTANCE_ERROR;
439
 
        This = (BlenderPluginInstance*) instance->pdata;
440
 
 
441
 
        if (This) {
442
 
                if (reason != NPRES_DONE) {
443
 
                        if (stream == This->main_file_stream) {                         
444
 
                                // stream destroyed by NPP_Destroy
445
 
                                NPN_Status(instance, "Cannot read animation file");
446
 
                                //main_file_failed(This->application);
447
 
                        }
448
 
                }
449
 
                return NPERR_NO_ERROR;
450
 
        } else {
451
 
                return NPERR_INVALID_INSTANCE_ERROR;
452
 
        }
453
 
 
454
 
}
455
 
 
456
 
 
457
 
/* Not supposed to be called anymore... Anyway, we don't need the
458
 
 * results. Some Moz implementations will call this one regardless the
459
 
 * desired transfer mode! */
460
 
void 
461
 
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname )
462
 
{
463
 
/*      log_entry("NPP_StreamAsFile"); */
464
 
}
465
 
 
466
 
 
467
 
void 
468
 
NPP_Print(NPP instance, NPPrint* printInfo ) 
469
 
{
470
 
        
471
 
        log_entry("NPP_Print");
472
 
        if(printInfo == NULL)
473
 
                return;
474
 
        if (instance != NULL) {
475
 
                if (printInfo->mode == NP_FULL) {
476
 
                        printInfo->print.fullPrint.pluginPrinted = FALSE;
477
 
                }
478
 
                else {  /* If not fullscreen, we must be embedded */
479
 
                }
480
 
        }
481
 
}
482
 
 
483
 
 
484
 
void
485
 
execute_blenderplayer(BlenderPluginInstance* instance){
486
 
 
487
 
        char file_name[] = "/tmp/blender.XXXXXX";
488
 
        int fd = mkstemp(file_name);
489
 
 
490
 
        ssize_t real_size = write(fd, instance->main_file_store, instance->stream_retrieved);
491
 
        close(fd);
492
 
 
493
 
        instance->temp_mail_file_name = NPN_MemAlloc(strlen(file_name) + 1);
494
 
        strcpy(instance->temp_mail_file_name, file_name);
495
 
 
496
 
        instance->pID = fork();
497
 
        //XSelectInput(This->display , This->window, SubstructureNotifyMask);
498
 
        //XSync(This->display, FALSE);
499
 
        
500
 
 
501
 
#if defined(WITH_APPARMOR)
502
 
        const char* executable = "blenderplayer-web"; 
503
 
#elif defined(WITH_PRIVSEP)
504
 
        const char* executable = "blenderplayer-wrapper";
505
 
#else   
506
 
        const char* executable = "blenderplayer";
507
 
#endif
508
 
 
509
 
        if (instance->pID == 0) {              // child
510
 
                char window_id[50];
511
 
                sprintf(window_id, "%d", instance->window);
512
 
                //exit(0);
513
 
#ifdef WITH_PRIVSEP
514
 
                execlp(executable, executable, file_name, window_id, (char*)NULL);
515
 
#else 
516
 
                execlp(executable, executable, "-i", window_id, file_name, (char*)NULL);
517
 
#endif
518
 
        
519
 
        } else if (instance->pID < 0) {           // failed to fork
520
 
                printf("Failed to fork!!!\n");                                  
521
 
        }
522
 
 
523
 
        /*XEvent e;
524
 
        int started = 0;
525
 
        while(!started) {
526
 
                XNextEvent(This->display, &e);
527
 
                printf("Event type %d\n", e.type);                                      
528
 
                if (e.type == MapNotify) {
529
 
                        started = 1;
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);
532
 
                }
533
 
        }*/
534
 
 
535
 
}
536
 
 
537
 
 
538
 
/* --------------------------------------------------------------------- */
539
 
 
540
 
static void
541
 
log_entry(char* msg)
542
 
{
543
 
#ifdef NZC_GENERATE_LOG 
544
 
        FILE* fp = fopen("/tmp/plugin_log","a");
545
 
        if (!fp) return;
546
 
        fprintf(fp, "--> Unixshell:: %s\n", 
547
 
                msg); 
548
 
        fflush(fp);
549
 
        fclose (fp);
550
 
#endif
551
 
}
552
 
 
553
 
/* --------------------------------------------------------------------- */
 
1
/**
 
2
 * $Id: UnixShell.c 19485 2009-03-31 22:34:34Z gsrb3d $
 
3
 *
 
4
 * ***** BEGIN GPL LICENSE BLOCK *****
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software Foundation,
 
18
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
19
 *
 
20
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 
21
 * All rights reserved.
 
22
 *
 
23
 * The Original Code is: all of this file.
 
24
 *
 
25
 * Contributor(s): Enrico Fracasso
 
26
 *
 
27
 * ***** END GPL LICENSE BLOCK *****
 
28
 * NS api template, adapted to link to our own internals.
 
29
 */
 
30
 
 
31
#define UNIXSH_VERSION "$Id: UnixShell.c 19485 2009-03-31 22:34:34Z gsrb3d $"
 
32
#define MOZ_X11 1
 
33
 
 
34
/* -*- Mode: C; tab-width: 8; c-set-style: bsd -*- */
 
35
 
 
36
/* UnixShell.c was adapted from the template in the Netscape API. */
 
37
 
 
38
/* System: */     
 
39
#include <string.h>
 
40
#include <stdlib.h>
 
41
#include <unistd.h>
 
42
 
 
43
/* All nsapi stuff. nsapi now needs FILE, so include stdio as well. */
 
44
#include <stdio.h>
 
45
#include "npapi.h"
 
46
 
 
47
#ifdef HAVE_CONFIG_H
 
48
#include <config.h>
 
49
#endif
 
50
 
 
51
/* Native hooks: */
 
52
#include "npapi.h"
 
53
 
 
54
/* Threading the NSPR way: */
 
55
#include "prthread.h"
 
56
#include "prlock.h"
 
57
 
 
58
#include "blender_plugin_types.h"
 
59
 
 
60
#include <signal.h>
 
61
 
 
62
/* --------------------------------------------------------------------- */
 
63
 
 
64
/** If defined: write to the plugin log file */
 
65
#ifndef NDEBUG
 
66
#define NZC_GENERATE_LOG
 
67
#endif
 
68
 
 
69
int32 STREAMBUFSIZE;
 
70
 
 
71
/** Generate a log file. */
 
72
static void
 
73
log_entry(char* msg);
 
74
 
 
75
 
 
76
void
 
77
execute_blenderplayer(BlenderPluginInstance*);
 
78
 
 
79
/* --------------------------------------------------------------------- */
 
80
/* Implementations:                                                      */
 
81
/* --------------------------------------------------------------------- */
 
82
 
 
83
/* NPP_GetMIMEDescription() and NPP_GetValue() are called to determine
 
84
 * the mime types supported by this plugin. */
 
85
char*
 
86
NPP_GetMIMEDescription( void )
 
87
{
 
88
        log_entry("NPP_GetMIMEDescription");
 
89
        return("application/x-blender-plugin:blend:Blender 3D web plugin");
 
90
}
 
91
 
 
92
NPError
 
93
NPP_GetValue(
 
94
        NPP instance,
 
95
        NPPVariable variable,
 
96
        void *value
 
97
        )
 
98
{
 
99
        NPError err = NPERR_NO_ERROR;
 
100
        
 
101
        log_entry("NPP_GetValue");
 
102
 
 
103
        switch (variable) {
 
104
        case NPPVpluginNeedsXEmbed:
 
105
                log_entry("NPP_GetValue::NPPVpluginNeedsXEmbed");
 
106
                *((PRBool *)value) = PR_TRUE;
 
107
                break;
 
108
        case NPPVpluginNameString:
 
109
                log_entry("NPP_GetValue::NPPVpluginNameString");
 
110
                *((char **)value) = "Blender";
 
111
                break;
 
112
        case NPPVpluginDescriptionString:
 
113
                log_entry("NPP_GetValue::NPPVpluginDescriptionString");
 
114
                *((char **)value) = "Player for interactive 3D content";
 
115
                break;
 
116
        case NPPVpluginWindowBool:
 
117
                log_entry("NPP_GetValue::NPPVpluginWindowBool");
 
118
                *((PRBool *)value) = PR_FALSE; //not windowless
 
119
                break;
 
120
        case NPPVpluginTransparentBool:
 
121
                log_entry("NPP_GetValue::NPPVpluginTransparentBool");
 
122
                *((PRBool *)value) = PR_FALSE; // not trasparent
 
123
                break;
 
124
        default:
 
125
                err = NPERR_GENERIC_ERROR;
 
126
        }
 
127
        return err;
 
128
}
 
129
 
 
130
/* --------------------------------------------------------------------- */
 
131
/* Mozilla: NPP_Initialize() is called when
 
132
 * starting the browser, and then every time the plugin is started*/
 
133
NPError
 
134
NPP_Initialize(void)
 
135
{
 
136
        log_entry("NPP_Initialize");
 
137
        return NPERR_NO_ERROR;
 
138
}
 
139
 
 
140
/* --------------------------------------------------------------------- */
 
141
 
 
142
void
 
143
NPP_Shutdown(void)
 
144
{
 
145
        log_entry("NPP_Shutdown");
 
146
}
 
147
 
 
148
 
 
149
NPError 
 
150
NPP_New(
 
151
        NPMIMEType pluginType,
 
152
        NPP instance,
 
153
        uint16 mode,
 
154
        int16 argc,
 
155
        char* argn[],
 
156
        char* argv[],
 
157
        NPSavedData* saved
 
158
        )
 
159
{
 
160
        BlenderPluginInstance* This  = NULL;
 
161
        int i = 0;
 
162
        int retval = 0;
 
163
 
 
164
        log_entry("NPP_New");
 
165
        
 
166
        if (instance == NULL)
 
167
                return NPERR_INVALID_INSTANCE_ERROR;
 
168
        
 
169
        instance->pdata = NPN_MemAlloc(sizeof(BlenderPluginInstance));
 
170
        if (instance->pdata == 0)
 
171
                return NPERR_OUT_OF_MEMORY_ERROR;
 
172
        
 
173
        This = (BlenderPluginInstance*) instance->pdata;
 
174
        This->browser_instance = instance;
 
175
        This->pID = 0;
 
176
        This->blend_file = 0;
 
177
        This->temp_mail_file_name = 0;
 
178
        This->main_file_store = 0;
 
179
        This->display = NULL;
 
180
        This->window = 0;
 
181
 
 
182
        /* Parse the options from the file. Should I do this in the
 
183
         * implementation file maybe? Now we do a lot with
 
184
         * instance-specific data. */
 
185
        /*
 
186
        while (i <argc ) {
 
187
                if (!strcmp(argn[i],"src")) {
 
188
                        The blend file to load. 
 
189
                        int url_len = strlen(argv[i]);
 
190
                        if ((url_len > 0) && (url_len < 4096) ) {
 
191
                                This->blend_file = NPN_MemAlloc(url_len + 1);
 
192
                                if (This->blend_file == 0)
 
193
                                        return NPERR_OUT_OF_MEMORY_ERROR;
 
194
                                strcpy(This->blend_file, argv[i]);
 
195
                                
 
196
                                retval = NPN_GetURL(This->browser_instance,
 
197
                                                    This->blend_file,
 
198
                                                    NULL);
 
199
                                if (retval != NPERR_NO_ERROR) {
 
200
                                        log_entry("Cannot read animation");
 
201
                                        NPN_Status(instance, "Cannot read animation file");
 
202
                                        This->blend_file = NULL;
 
203
                                        return NPERR_NO_ERROR;
 
204
                                } else
 
205
                                        log_entry("Animation loaded"); 
 
206
                        }
 
207
                }               
 
208
                i++;
 
209
        }*/
 
210
                
 
211
        if (This != NULL) {
 
212
                return NPERR_NO_ERROR;
 
213
        } else
 
214
                return NPERR_OUT_OF_MEMORY_ERROR;
 
215
}
 
216
 
 
217
 
 
218
NPError 
 
219
NPP_Destroy( NPP instance, NPSavedData** save )
 
220
{
 
221
        BlenderPluginInstance* This;
 
222
 
 
223
        log_entry("NPP_Destroy");
 
224
 
 
225
        if (instance == NULL)
 
226
                return NPERR_INVALID_INSTANCE_ERROR;
 
227
 
 
228
        This = (BlenderPluginInstance*) instance->pdata;
 
229
        printf("NPP_Destroy ID:  0x%x %d\n", This->window, This->window);
 
230
 
 
231
        if (This != NULL) {
 
232
 
 
233
                if (This->pID != 0) {
 
234
#ifdef WITH_PRIVSEP
 
235
                        kill(This->pID, SIGTERM);
 
236
#else 
 
237
                        kill(This->pID, SIGKILL); //if I have to kill blenderplayer directly I need to send SIGKILL
 
238
#endif
 
239
                        wait(This->pID);
 
240
                        unlink(This->temp_mail_file_name);
 
241
                }
 
242
 
 
243
                // sometimes FF doesn't delete it's own window...
 
244
                //printf("%s \n", NPN_UserAgent(instance));
 
245
                /*if (This->display != NULL && This->window != 0)
 
246
                        XDestroyWindow(This->display, This->window);
 
247
                */
 
248
                if (This->blend_file) NPN_MemFree(This->blend_file);
 
249
                if (This->temp_mail_file_name) NPN_MemFree(This->temp_mail_file_name);
 
250
                if (This->main_file_store) NPN_MemFree(This->main_file_store);
 
251
                NPN_MemFree(instance->pdata);
 
252
                instance->pdata = NULL;
 
253
        }       
 
254
 
 
255
        return NPERR_NO_ERROR;
 
256
}
 
257
 
 
258
 
 
259
 
 
260
NPError 
 
261
NPP_SetWindow( NPP instance,NPWindow* window ) 
 
262
{
 
263
        BlenderPluginInstance* This;
 
264
 
 
265
        log_entry("NPP_SetWindow");
 
266
 
 
267
        if (instance == NULL)
 
268
                return NPERR_INVALID_INSTANCE_ERROR;
 
269
 
 
270
        /* window handle */ 
 
271
        if ((window == NULL) || (window->window == NULL)) {
 
272
                return NPERR_NO_ERROR; /* mmmmmm  */
 
273
        }
 
274
        
 
275
        if (window->ws_info == NULL)
 
276
                return NPERR_NO_ERROR; /* mmmmmm  */
 
277
 
 
278
        This = (BlenderPluginInstance*) instance->pdata;
 
279
 
 
280
        if (This) {
 
281
                This->window = (Window) window->window;
 
282
 
 
283
                NPSetWindowCallbackStruct* window_info = window->ws_info;
 
284
                This->display = window_info->display;
 
285
 
 
286
                printf("ID window 0x%x %d\n", window->window, window->window);
 
287
                return NPERR_NO_ERROR;
 
288
        } else {
 
289
                return NPERR_INVALID_INSTANCE_ERROR;
 
290
        }
 
291
}
 
292
 
 
293
 
 
294
NPError 
 
295
NPP_NewStream(
 
296
        NPP instance,
 
297
        NPMIMEType type,
 
298
        NPStream *stream, 
 
299
        NPBool seekable,
 
300
        uint16 *stype
 
301
        )
 
302
{
 
303
        //NPByteRange range;
 
304
        BlenderPluginInstance* This;
 
305
 
 
306
        log_entry("NPP_NewStream");
 
307
        
 
308
        if (instance == NULL)
 
309
                return NPERR_INVALID_INSTANCE_ERROR;
 
310
 
 
311
        This = (BlenderPluginInstance*) instance->pdata;
 
312
 
 
313
        if (!This) 
 
314
                return NPERR_INVALID_INSTANCE_ERROR;
 
315
 
 
316
        printf("Loading main file %s (%s)\n", stream->url, type);
 
317
        if ( strcmp(type,"text/html") == 0 ) // original HTML file 
 
318
                return NPERR_NO_ERROR;
 
319
        
 
320
        This->stream_total = stream->end;
 
321
        This->stream_retrieved = 0;
 
322
        This->main_file_store = NPN_MemAlloc(stream->end*sizeof(unsigned char));
 
323
        if (!This->main_file_store) {
 
324
                fprintf(stderr, "Blender plugin: Out of memory! "
 
325
                        "Cannot get chunk for loading animation.\n");
 
326
                return NPERR_OUT_OF_MEMORY_ERROR;
 
327
        }
 
328
 
 
329
        This->main_file_stream = stream;
 
330
 
 
331
        return NPERR_NO_ERROR;
 
332
                
 
333
}
 
334
 
 
335
 
 
336
/* PLUGIN DEVELOPERS:
 
337
 *      These next 2 functions are directly relevant in a plug-in which
 
338
 *      handles the data in a streaming manner. If you want zero bytes
 
339
 *      because no buffer space is YET available, return 0. As long as
 
340
 *      the stream has not been written to the plugin, Navigator will
 
341
 *      continue trying to send bytes.  If the plugin doesn't want them,
 
342
 *      just return some large number from NPP_WriteReady(), and
 
343
 *      ignore them in NPP_Write().  For a NP_ASFILE stream, they are
 
344
 *      still called but can safely be ignored using this strategy.
 
345
 */
 
346
 
 
347
int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
 
348
                                   * mode so we can take any size stream in our
 
349
                                   * write call (since we ignore it) */
 
350
 
 
351
int32 
 
352
NPP_WriteReady(
 
353
        NPP instance,
 
354
        NPStream *stream
 
355
        )
 
356
{
 
357
        BlenderPluginInstance* This = NULL;
 
358
        int acceptable = 0;
 
359
        
 
360
        log_entry("NPP_WriteReady"); 
 
361
 
 
362
        if (instance == NULL)   
 
363
                return NPERR_INVALID_INSTANCE_ERROR;
 
364
 
 
365
        This = (BlenderPluginInstance*) instance->pdata;
 
366
 
 
367
        if (This == NULL)       
 
368
                return NPERR_INVALID_INSTANCE_ERROR;
 
369
 
 
370
        /* Check whether buffers already exist: */
 
371
 
 
372
        if ((This->main_file_stream && This->main_file_store)) {
 
373
                acceptable = STREAMBUFSIZE;
 
374
        }
 
375
        
 
376
        
 
377
        return acceptable;
 
378
}
 
379
 
 
380
 
 
381
int32 
 
382
NPP_Write(
 
383
        NPP instance,
 
384
        NPStream *stream,
 
385
        int32 offset,
 
386
        int32 len,
 
387
        void *buffer
 
388
        )
 
389
{
 
390
        BlenderPluginInstance* This = NULL;
 
391
        int accepted = 0;
 
392
        
 
393
        log_entry("NPP_Write"); 
 
394
 
 
395
        if (instance == NULL)   
 
396
                return NPERR_INVALID_INSTANCE_ERROR;
 
397
        
 
398
        This = (BlenderPluginInstance*) instance->pdata;
 
399
 
 
400
        if (This == NULL)       
 
401
                return NPERR_INVALID_INSTANCE_ERROR;
 
402
 
 
403
        
 
404
        if (stream == This->main_file_stream) {
 
405
                log_entry("NPP_Write: loading main_file_stream"); 
 
406
                memcpy(((unsigned char*)This->main_file_store) + This->stream_retrieved, buffer, len);
 
407
                accepted = len;
 
408
                This->stream_retrieved += len;
 
409
                if (This->stream_retrieved >= This->stream_total) {
 
410
                        log_entry("NPP_Write: main_file_stream loaded"); 
 
411
                        execute_blenderplayer(This);
 
412
                }
 
413
        } else {
 
414
                /* the stream ref wasn't set yet..*/
 
415
                log_entry("NPP_Write: not main stream"); 
 
416
                log_entry(stream->url);
 
417
 
 
418
                accepted = len;
 
419
        }
 
420
 
 
421
        return accepted;
 
422
}
 
423
 
 
424
 
 
425
 
 
426
NPError 
 
427
NPP_DestroyStream(
 
428
        NPP instance,
 
429
        NPStream *stream,
 
430
        NPError reason
 
431
        )
 
432
{
 
433
        BlenderPluginInstance* This = NULL;
 
434
 
 
435
        log_entry("NPP_DestroyStream");
 
436
 
 
437
        if (instance == NULL)
 
438
                return NPERR_INVALID_INSTANCE_ERROR;
 
439
        This = (BlenderPluginInstance*) instance->pdata;
 
440
 
 
441
        if (This) {
 
442
                if (reason != NPRES_DONE) {
 
443
                        if (stream == This->main_file_stream) {                         
 
444
                                // stream destroyed by NPP_Destroy
 
445
                                NPN_Status(instance, "Cannot read animation file");
 
446
                                //main_file_failed(This->application);
 
447
                        }
 
448
                }
 
449
                return NPERR_NO_ERROR;
 
450
        } else {
 
451
                return NPERR_INVALID_INSTANCE_ERROR;
 
452
        }
 
453
 
 
454
}
 
455
 
 
456
 
 
457
/* Not supposed to be called anymore... Anyway, we don't need the
 
458
 * results. Some Moz implementations will call this one regardless the
 
459
 * desired transfer mode! */
 
460
void 
 
461
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname )
 
462
{
 
463
/*      log_entry("NPP_StreamAsFile"); */
 
464
}
 
465
 
 
466
 
 
467
void 
 
468
NPP_Print(NPP instance, NPPrint* printInfo ) 
 
469
{
 
470
        
 
471
        log_entry("NPP_Print");
 
472
        if(printInfo == NULL)
 
473
                return;
 
474
        if (instance != NULL) {
 
475
                if (printInfo->mode == NP_FULL) {
 
476
                        printInfo->print.fullPrint.pluginPrinted = FALSE;
 
477
                }
 
478
                else {  /* If not fullscreen, we must be embedded */
 
479
                }
 
480
        }
 
481
}
 
482
 
 
483
 
 
484
void
 
485
execute_blenderplayer(BlenderPluginInstance* instance){
 
486
 
 
487
        char file_name[] = "/tmp/blender.XXXXXX";
 
488
        int fd = mkstemp(file_name);
 
489
 
 
490
        ssize_t real_size = write(fd, instance->main_file_store, instance->stream_retrieved);
 
491
        close(fd);
 
492
 
 
493
        instance->temp_mail_file_name = NPN_MemAlloc(strlen(file_name) + 1);
 
494
        strcpy(instance->temp_mail_file_name, file_name);
 
495
 
 
496
        instance->pID = fork();
 
497
        //XSelectInput(This->display , This->window, SubstructureNotifyMask);
 
498
        //XSync(This->display, FALSE);
 
499
        
 
500
 
 
501
#if defined(WITH_APPARMOR)
 
502
        const char* executable = "blenderplayer-web"; 
 
503
#elif defined(WITH_PRIVSEP)
 
504
        const char* executable = "blenderplayer-wrapper";
 
505
#else   
 
506
        const char* executable = "blenderplayer";
 
507
#endif
 
508
 
 
509
        if (instance->pID == 0) {              // child
 
510
                char window_id[50];
 
511
                sprintf(window_id, "%d", instance->window);
 
512
                //exit(0);
 
513
#ifdef WITH_PRIVSEP
 
514
                execlp(executable, executable, file_name, window_id, (char*)NULL);
 
515
#else 
 
516
                execlp(executable, executable, "-i", window_id, file_name, (char*)NULL);
 
517
#endif
 
518
        
 
519
        } else if (instance->pID < 0) {           // failed to fork
 
520
                printf("Failed to fork!!!\n");                                  
 
521
        }
 
522
 
 
523
        /*XEvent e;
 
524
        int started = 0;
 
525
        while(!started) {
 
526
                XNextEvent(This->display, &e);
 
527
                printf("Event type %d\n", e.type);                                      
 
528
                if (e.type == MapNotify) {
 
529
                        started = 1;
 
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);
 
532
                }
 
533
        }*/
 
534
 
 
535
}
 
536
 
 
537
 
 
538
/* --------------------------------------------------------------------- */
 
539
 
 
540
static void
 
541
log_entry(char* msg)
 
542
{
 
543
#ifdef NZC_GENERATE_LOG 
 
544
        FILE* fp = fopen("/tmp/plugin_log","a");
 
545
        if (!fp) return;
 
546
        fprintf(fp, "--> Unixshell:: %s\n", 
 
547
                msg); 
 
548
        fflush(fp);
 
549
        fclose (fp);
 
550
#endif
 
551
}
 
552
 
 
553
/* --------------------------------------------------------------------- */