~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-02-19 11:24:23 UTC
  • mfrom: (14.2.23 sid)
  • Revision ID: package-import@ubuntu.com-20140219112423-rkmaz2m7ha06d4tk
Tags: 2.69-3ubuntu1
* Merge with Debian; remaining changes:
  - Configure without OpenImageIO on armhf, as it is not available on
    Ubuntu.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * ***** BEGIN GPL LICENSE BLOCK *****
3
 
 *
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.
8
 
 *
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.
13
 
 *
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.
17
 
 *
18
 
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19
 
 * All rights reserved.
20
 
 *
21
 
 * The Original Code is: all of this file.
22
 
 *
23
 
 * Contributor(s): Enrico Fracasso
24
 
 *
25
 
 * ***** END GPL LICENSE BLOCK *****
26
 
 * NS api template, adapted to link to our own internals.
27
 
 */
28
 
 
29
 
#define MOZ_X11 1
30
 
 
31
 
/* UnixShell.c was adapted from the template in the Netscape API. */
32
 
 
33
 
/* System: */     
34
 
#include <string.h>
35
 
#include <stdlib.h>
36
 
#include <unistd.h>
37
 
 
38
 
/* All nsapi stuff. nsapi now needs FILE, so include stdio as well. */
39
 
#include <stdio.h>
40
 
#include "npapi.h"
41
 
 
42
 
/* Native hooks: */
43
 
#include "npapi.h"
44
 
 
45
 
/* Threading the NSPR way: */
46
 
#include "prthread.h"
47
 
#include "prlock.h"
48
 
 
49
 
#include "blender_plugin_types.h"
50
 
 
51
 
#include <signal.h>
52
 
 
53
 
/* --------------------------------------------------------------------- */
54
 
 
55
 
/** If defined: write to the plugin log file */
56
 
#if defined(DEBUG)
57
 
#define NZC_GENERATE_LOG
58
 
#endif
59
 
 
60
 
int32 STREAMBUFSIZE;
61
 
 
62
 
/** Generate a log file. */
63
 
static void
64
 
log_entry(char* msg);
65
 
 
66
 
 
67
 
void
68
 
execute_blenderplayer(BlenderPluginInstance *);
69
 
 
70
 
/* --------------------------------------------------------------------- */
71
 
/* Implementations:                                                      */
72
 
/* --------------------------------------------------------------------- */
73
 
 
74
 
/* NPP_GetMIMEDescription() and NPP_GetValue() are called to determine
75
 
 * the mime types supported by this plugin. */
76
 
char*
77
 
NPP_GetMIMEDescription(void)
78
 
{
79
 
        log_entry("NPP_GetMIMEDescription");
80
 
        return("application/x-blender-plugin:blend:Blender 3D web plugin");
81
 
}
82
 
 
83
 
NPError
84
 
NPP_GetValue(
85
 
        NPP instance,
86
 
        NPPVariable variable,
87
 
        void *value
88
 
        )
89
 
{
90
 
        NPError err = NPERR_NO_ERROR;
91
 
        
92
 
        log_entry("NPP_GetValue");
93
 
 
94
 
        switch (variable) {
95
 
        case NPPVpluginNeedsXEmbed:
96
 
                log_entry("NPP_GetValue::NPPVpluginNeedsXEmbed");
97
 
                *((PRBool *)value) = PR_TRUE;
98
 
                break;
99
 
        case NPPVpluginNameString:
100
 
                log_entry("NPP_GetValue::NPPVpluginNameString");
101
 
                *((char **)value) = "Blender";
102
 
                break;
103
 
        case NPPVpluginDescriptionString:
104
 
                log_entry("NPP_GetValue::NPPVpluginDescriptionString");
105
 
                *((char **)value) = "Player for interactive 3D content";
106
 
                break;
107
 
        case NPPVpluginWindowBool:
108
 
                log_entry("NPP_GetValue::NPPVpluginWindowBool");
109
 
                *((PRBool *)value) = PR_FALSE; //not windowless
110
 
                break;
111
 
        case NPPVpluginTransparentBool:
112
 
                log_entry("NPP_GetValue::NPPVpluginTransparentBool");
113
 
                *((PRBool *)value) = PR_FALSE; // not trasparent
114
 
                break;
115
 
        default:
116
 
                err = NPERR_GENERIC_ERROR;
117
 
        }
118
 
        return err;
119
 
}
120
 
 
121
 
/* --------------------------------------------------------------------- */
122
 
/* Mozilla: NPP_Initialize() is called when
123
 
 * starting the browser, and then every time the plugin is started*/
124
 
NPError
125
 
NPP_Initialize(void)
126
 
{
127
 
        log_entry("NPP_Initialize");
128
 
        return NPERR_NO_ERROR;
129
 
}
130
 
 
131
 
/* --------------------------------------------------------------------- */
132
 
 
133
 
void
134
 
NPP_Shutdown(void)
135
 
{
136
 
        log_entry("NPP_Shutdown");
137
 
}
138
 
 
139
 
 
140
 
NPError 
141
 
NPP_New(
142
 
        NPMIMEType pluginType,
143
 
        NPP instance,
144
 
        uint16 mode,
145
 
        int16 argc,
146
 
        char* argn[],
147
 
        char* argv[],
148
 
        NPSavedData* saved
149
 
        )
150
 
{
151
 
        BlenderPluginInstance *This = NULL;
152
 
        int i = 0;
153
 
        int retval = 0;
154
 
 
155
 
        log_entry("NPP_New");
156
 
        
157
 
        if (instance == NULL)
158
 
                return NPERR_INVALID_INSTANCE_ERROR;
159
 
        
160
 
        instance->pdata = NPN_MemAlloc(sizeof(BlenderPluginInstance));
161
 
        if (instance->pdata == 0)
162
 
                return NPERR_OUT_OF_MEMORY_ERROR;
163
 
        
164
 
        This = (BlenderPluginInstance *) instance->pdata;
165
 
        This->browser_instance = instance;
166
 
        This->pID = 0;
167
 
        This->blend_file = 0;
168
 
        This->temp_mail_file_name = 0;
169
 
        This->main_file_store = 0;
170
 
        This->display = NULL;
171
 
        This->window = 0;
172
 
 
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. */
176
 
        /*
177
 
        while (i <argc ) {
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]);
186
 
                                
187
 
                                retval = NPN_GetURL(This->browser_instance,
188
 
                                                    This->blend_file,
189
 
                                                    NULL);
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;
195
 
                                }
196
 
                                else {
197
 
                                        log_entry("Animation loaded");
198
 
                                }
199
 
                        }
200
 
                }               
201
 
                i++;
202
 
        }*/
203
 
                
204
 
        if (This != NULL) {
205
 
                return NPERR_NO_ERROR;
206
 
        }
207
 
        else {
208
 
                return NPERR_OUT_OF_MEMORY_ERROR;
209
 
        }
210
 
}
211
 
 
212
 
 
213
 
NPError 
214
 
NPP_Destroy( NPP instance, NPSavedData** save )
215
 
{
216
 
        BlenderPluginInstance *This;
217
 
 
218
 
        log_entry("NPP_Destroy");
219
 
 
220
 
        if (instance == NULL)
221
 
                return NPERR_INVALID_INSTANCE_ERROR;
222
 
 
223
 
        This = (BlenderPluginInstance *) instance->pdata;
224
 
        printf("NPP_Destroy ID:  0x%x %d\n", This->window, This->window);
225
 
 
226
 
        if (This != NULL) {
227
 
 
228
 
                if (This->pID != 0) {
229
 
#ifdef WITH_PRIVSEP
230
 
                        kill(This->pID, SIGTERM);
231
 
#else 
232
 
                        kill(This->pID, SIGKILL); //if I have to kill blenderplayer directly I need to send SIGKILL
233
 
#endif
234
 
                        wait(This->pID);
235
 
                        unlink(This->temp_mail_file_name);
236
 
                }
237
 
 
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);
242
 
                */
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;
248
 
        }       
249
 
 
250
 
        return NPERR_NO_ERROR;
251
 
}
252
 
 
253
 
 
254
 
 
255
 
NPError 
256
 
NPP_SetWindow( NPP instance,NPWindow* window ) 
257
 
{
258
 
        BlenderPluginInstance *This;
259
 
 
260
 
        log_entry("NPP_SetWindow");
261
 
 
262
 
        if (instance == NULL)
263
 
                return NPERR_INVALID_INSTANCE_ERROR;
264
 
 
265
 
        /* window handle */ 
266
 
        if ((window == NULL) || (window->window == NULL)) {
267
 
                return NPERR_NO_ERROR; /* mmmmmm  */
268
 
        }
269
 
        
270
 
        if (window->ws_info == NULL)
271
 
                return NPERR_NO_ERROR; /* mmmmmm  */
272
 
 
273
 
        This = (BlenderPluginInstance *) instance->pdata;
274
 
 
275
 
        if (This) {
276
 
                This->window = (Window) window->window;
277
 
 
278
 
                NPSetWindowCallbackStruct* window_info = window->ws_info;
279
 
                This->display = window_info->display;
280
 
 
281
 
                printf("ID window 0x%x %d\n", window->window, window->window);
282
 
                return NPERR_NO_ERROR;
283
 
        }
284
 
        else {
285
 
                return NPERR_INVALID_INSTANCE_ERROR;
286
 
        }
287
 
}
288
 
 
289
 
 
290
 
NPError 
291
 
NPP_NewStream(
292
 
        NPP instance,
293
 
        NPMIMEType type,
294
 
        NPStream *stream, 
295
 
        NPBool seekable,
296
 
        uint16 *stype
297
 
        )
298
 
{
299
 
        //NPByteRange range;
300
 
        BlenderPluginInstance *This;
301
 
 
302
 
        log_entry("NPP_NewStream");
303
 
        
304
 
        if (instance == NULL)
305
 
                return NPERR_INVALID_INSTANCE_ERROR;
306
 
 
307
 
        This = (BlenderPluginInstance *) instance->pdata;
308
 
 
309
 
        if (!This) 
310
 
                return NPERR_INVALID_INSTANCE_ERROR;
311
 
 
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;
315
 
        
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;
323
 
        }
324
 
 
325
 
        This->main_file_stream = stream;
326
 
 
327
 
        return NPERR_NO_ERROR;
328
 
                
329
 
}
330
 
 
331
 
 
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.
341
 
 */
342
 
 
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) */
346
 
 
347
 
int32 
348
 
NPP_WriteReady(
349
 
        NPP instance,
350
 
        NPStream *stream
351
 
        )
352
 
{
353
 
        BlenderPluginInstance *This = NULL;
354
 
        int acceptable = 0;
355
 
        
356
 
        log_entry("NPP_WriteReady");
357
 
 
358
 
        if (instance == NULL)
359
 
                return NPERR_INVALID_INSTANCE_ERROR;
360
 
 
361
 
        This = (BlenderPluginInstance *) instance->pdata;
362
 
 
363
 
        if (This == NULL)
364
 
                return NPERR_INVALID_INSTANCE_ERROR;
365
 
 
366
 
        /* Check whether buffers already exist: */
367
 
 
368
 
        if ((This->main_file_stream && This->main_file_store)) {
369
 
                acceptable = STREAMBUFSIZE;
370
 
        }
371
 
        
372
 
        
373
 
        return acceptable;
374
 
}
375
 
 
376
 
 
377
 
int32 
378
 
NPP_Write(
379
 
        NPP instance,
380
 
        NPStream *stream,
381
 
        int32 offset,
382
 
        int32 len,
383
 
        void *buffer
384
 
        )
385
 
{
386
 
        BlenderPluginInstance *This = NULL;
387
 
        int accepted = 0;
388
 
        
389
 
        log_entry("NPP_Write");
390
 
 
391
 
        if (instance == NULL)
392
 
                return NPERR_INVALID_INSTANCE_ERROR;
393
 
        
394
 
        This = (BlenderPluginInstance *) instance->pdata;
395
 
 
396
 
        if (This == NULL)
397
 
                return NPERR_INVALID_INSTANCE_ERROR;
398
 
 
399
 
        
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);
403
 
                accepted = 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);
408
 
                }
409
 
        }
410
 
        else {
411
 
                /* the stream ref wasn't set yet..*/
412
 
                log_entry("NPP_Write: not main stream"); 
413
 
                log_entry(stream->url);
414
 
 
415
 
                accepted = len;
416
 
        }
417
 
 
418
 
        return accepted;
419
 
}
420
 
 
421
 
 
422
 
 
423
 
NPError 
424
 
NPP_DestroyStream(
425
 
        NPP instance,
426
 
        NPStream *stream,
427
 
        NPError reason
428
 
        )
429
 
{
430
 
        BlenderPluginInstance *This = NULL;
431
 
 
432
 
        log_entry("NPP_DestroyStream");
433
 
 
434
 
        if (instance == NULL)
435
 
                return NPERR_INVALID_INSTANCE_ERROR;
436
 
        This = (BlenderPluginInstance *) instance->pdata;
437
 
 
438
 
        if (This) {
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); */
444
 
                        }
445
 
                }
446
 
                return NPERR_NO_ERROR;
447
 
        }
448
 
        else {
449
 
                return NPERR_INVALID_INSTANCE_ERROR;
450
 
        }
451
 
 
452
 
}
453
 
 
454
 
 
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! */
458
 
void 
459
 
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname )
460
 
{
461
 
/*      log_entry("NPP_StreamAsFile"); */
462
 
}
463
 
 
464
 
 
465
 
void 
466
 
NPP_Print(NPP instance, NPPrint* printInfo ) 
467
 
{
468
 
        
469
 
        log_entry("NPP_Print");
470
 
        if (printInfo == NULL)
471
 
                return;
472
 
        if (instance != NULL) {
473
 
                if (printInfo->mode == NP_FULL) {
474
 
                        printInfo->print.fullPrint.pluginPrinted = FALSE;
475
 
                }
476
 
                else {  /* If not fullscreen, we must be embedded */
477
 
                }
478
 
        }
479
 
}
480
 
 
481
 
 
482
 
void
483
 
execute_blenderplayer(BlenderPluginInstance *instance)
484
 
{
485
 
 
486
 
        char file_name[] = "/tmp/blender.XXXXXX";
487
 
        int fd = mkstemp(file_name);
488
 
 
489
 
        ssize_t real_size = write(fd, instance->main_file_store, instance->stream_retrieved);
490
 
        close(fd);
491
 
 
492
 
        instance->temp_mail_file_name = NPN_MemAlloc(strlen(file_name) + 1);
493
 
        strcpy(instance->temp_mail_file_name, file_name);
494
 
 
495
 
        instance->pID = fork();
496
 
        //XSelectInput(This->display, This->window, SubstructureNotifyMask);
497
 
        //XSync(This->display, FALSE);
498
 
        
499
 
 
500
 
#if defined(WITH_APPARMOR)
501
 
        const char* executable = "blenderplayer-web"; 
502
 
#elif defined(WITH_PRIVSEP)
503
 
        const char* executable = "blenderplayer-wrapper";
504
 
#else   
505
 
        const char* executable = "blenderplayer";
506
 
#endif
507
 
 
508
 
        if (instance->pID == 0) {              // child
509
 
                char window_id[50];
510
 
                sprintf(window_id, "%d", instance->window);
511
 
                //exit(0);
512
 
#ifdef WITH_PRIVSEP
513
 
                execlp(executable, executable, file_name, window_id, (char*)NULL);
514
 
#else 
515
 
                execlp(executable, executable, "-i", window_id, file_name, (char*)NULL);
516
 
#endif
517
 
        
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
 
/* --------------------------------------------------------------------- */