fixed X11_softare_info changing
[ego.git] / src / plugin / egoplayer.c
blob0b2b6fa488e57216e6d7e7cdeee579c9f8386e1a
1 #include "egoplayer.h"
3 /*
4 * manages the use of the function NPN_PluginThreadAsyncCall
5 * and its alternative implementation with XEvents
7 * 1: enable plugin for
8 * - gecko < 1.9
9 * - webkit
11 * 0: plugin runs only with
12 * - gecko >= 1.9
14 #define COMPLIANT 0
17 * manages the use of the windowed and windowless mode of plugins
19 * 1: plugin runs in windowed mode
20 * - gecko < 1.9
22 * 0: plugin runs in windowless mode (transparency)
23 * - gecko >= 1.9
25 #define WINDOWED 1
27 void
28 mep_asynccall (void *data)
30 PluginInstance *pi = (PluginInstance *) data;
31 ecore_main_loop_iterate ();
32 if (!pi->done)
34 usleep (1000); // max 100 fps
35 #if COMPLIANT
36 XSendEvent (
37 pi->display,
38 pi->window,
40 NoEventMask,
41 (XEvent *) &(pi->msg));
42 #else
43 NPN_PluginThreadAsyncCall (pi->instance, mep_asynccall, (void *) pi);
44 #endif /* COMPLIANT */
48 int
49 mep_animator (void *data)
51 PluginInstance *pi = (PluginInstance *) data;
52 evas_render (pi->evas);
53 return 1;
56 #if WINDOWED
57 void
58 mep_event_handler (Widget xtwidget, void *data, XEvent *xevent, Boolean *b)
60 PluginInstance *pi = (PluginInstance *) data;
61 NPP_HandleEvent (pi->instance, xevent);
63 #endif /* WINDOWED */
65 char*
66 NPP_GetMIMEDescription (void)
68 return (MIME_TYPES_HANDLED);
71 NPError
72 NPP_GetValue (NPP instance, NPPVariable variable, void *value)
74 PluginInstance *pi;
75 NPError err = NPERR_NO_ERROR;
77 switch (variable) {
78 case NPPVpluginNameString:
79 *((char **) value) = PLUGIN_NAME;
80 break;
81 case NPPVpluginDescriptionString:
82 *((char **) value) = PLUGIN_DESCRIPTION;
83 break;
84 default:
85 err = NPERR_GENERIC_ERROR;
87 return err;
90 int16
91 NPP_HandleEvent (NPP instance, void *xevent)
93 PluginInstance *pi = (PluginInstance *) instance->pdata;
94 Evas *evas = pi->evas;
95 XEvent ev = *((XEvent *) xevent);
97 switch (ev.type) {
98 case KeyPress:
99 printf ("KeyPress\n");
100 break;
101 case KeyRelease:
102 printf ("KeyRelease\n");
103 break;
104 case ButtonPress:
105 printf ("ButtonPress\n");
106 evas_event_feed_mouse_move(evas, ev.xbutton.x, ev.xbutton.y, 0, NULL);
107 evas_event_feed_mouse_down(evas, ev.xbutton.button, EVAS_BUTTON_NONE, 0, NULL);
108 break;
109 case ButtonRelease:
110 printf ("ButtonRelease\n");
111 evas_event_feed_mouse_move(evas, ev.xbutton.x, ev.xbutton.y, 0, NULL);
112 evas_event_feed_mouse_up(evas, ev.xbutton.button, EVAS_BUTTON_NONE, 0, NULL);
113 break;
114 case MotionNotify:
115 //printf ("MotionNotify\n");
116 evas_event_feed_mouse_move(evas, ev.xmotion.x, ev.xmotion.y, 0, NULL);
117 break;
118 case EnterNotify:
119 printf ("EnterNotify\n");
120 break;
121 case LeaveNotify:
122 printf ("LeaveNotify\n");
123 break;
124 case FocusIn:
125 printf ("FocusIn\n");
126 break;
127 case FocusOut:
128 printf ("FocusOut\n");
129 break;
130 case KeymapNotify:
131 printf ("KeymapNotify\n");
132 break;
133 case Expose:
134 printf ("Expose\n");
135 evas_damage_rectangle_add(evas,
136 ev.xexpose.x,
137 ev.xexpose.y,
138 ev.xexpose.width,
139 ev.xexpose.height);
140 break;
141 case GraphicsExpose:
142 printf ("GraphicsExpose\n");
143 break;
144 case NoExpose:
145 printf ("NoExpose\n");
146 break;
147 case VisibilityNotify:
148 printf ("VisibilityNotify\n");
149 break;
150 case CreateNotify:
151 printf ("CreateNotify\n");
152 break;
153 case DestroyNotify:
154 printf ("DestroyNotify\n");
155 break;
156 case UnmapNotify:
157 printf ("UnmapNotify\n");
158 break;
159 case MapNotify:
160 printf ("MapNotify\n");
161 break;
162 case MapRequest:
163 printf ("MapRequest\n");
164 break;
165 case ReparentNotify:
166 printf ("ReparentNotify\n");
167 break;
168 case ConfigureNotify:
169 printf ("ConfigureNotify\n");
170 evas_output_size_set(evas,
171 ev.xconfigure.width,
172 ev.xconfigure.height);
173 break;
174 case ConfigureRequest:
175 printf ("ConfigureRequest\n");
176 break;
177 case GravityNotify:
178 printf ("GravityNotify\n");
179 break;
180 case ResizeRequest:
181 printf ("ResizeRequest\n");
182 break;
183 case CirculateNotify:
184 printf ("CirculateNotify\n");
185 break;
186 case CirculateRequest:
187 printf ("CirculateRequest\n");
188 break;
189 case PropertyNotify:
190 printf ("PropertyNotify\n");
191 break;
192 case SelectionClear:
193 printf ("SelectionClear\n");
194 break;
195 case SelectionRequest:
196 printf ("SelectionRequest\n");
197 break;
198 case SelectionNotify:
199 printf ("SelectionNotify\n");
200 break;
201 case ColormapNotify:
202 printf ("ColormapNotify\n");
203 break;
204 case ClientMessage:
205 #if COMPLIANT
206 //printf ("ClientMessage\n");
207 if (ev.xclient.message_type == pi->atom)
208 mep_asynccall (pi);
209 #endif
210 break;
211 case MappingNotify:
212 printf ("MappingNotify\n");
213 break;
214 case LASTEvent:
215 printf ("LASTEvent\n");
216 break;
219 return TRUE;
222 NPError
223 NPP_Initialize (void)
225 const char *ref = "ego";
226 eet_init ();
227 ecore_init ();
228 ecore_config_init (ref);
229 evas_init ();
230 edje_init ();
231 elm_init (1, &ref);
233 return NPERR_NO_ERROR;
236 #ifdef OJI
237 jref
238 NPP_GetJavaClass ()
240 return NULL;
242 #endif
244 void
245 NPP_Shutdown (void)
247 elm_shutdown ();
248 edje_shutdown ();
249 evas_shutdown ();
250 ecore_config_shutdown ();
251 ecore_shutdown ();
252 eet_shutdown ();
255 NPError
256 NPP_New (NPMIMEType pluginType,
257 NPP instance,
258 uint16 mode,
259 int16 argc,
260 char* argn[],
261 char* argv[],
262 NPSavedData* saved)
264 if (instance == NULL)
265 return NPERR_INVALID_INSTANCE_ERROR;
266 instance->pdata = NPN_MemAlloc (sizeof (PluginInstance));
268 PluginInstance *pi = (PluginInstance*) instance->pdata;
269 if (pi == NULL)
270 return NPERR_OUT_OF_MEMORY_ERROR;
271 memset(pi, 0, sizeof (PluginInstance));
273 /* mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h) */
274 pi->mode = mode;
275 pi->type = strdup ("application/x-ego");
276 pi->instance = instance;
278 pi->pluginsPageUrl = NULL;
279 pi->exists = FALSE;
281 /* Parse argument list passed to plugin instance */
282 /* We are interested in these arguments
283 * PLUGINSPAGE = <url>
285 while (argc > 0)
287 argc --;
288 if (argv[argc] != NULL)
290 if (!PL_strcasecmp (argn[argc], "PLUGINSPAGE"))
291 pi->pluginsPageUrl = strdup (argv[argc]);
292 else if (!PL_strcasecmp (argn[argc], "PLUGINURL"))
293 pi->pluginsFileUrl = strdup (argv[argc]);
294 else if (!PL_strcasecmp (argn[argc], "CODEBASE"))
295 pi->pluginsPageUrl = strdup (argv[argc]);
296 else if (!PL_strcasecmp (argn[argc], "CLASSID"))
297 pi->pluginsFileUrl = strdup (argv[argc]);
298 else if (!PL_strcasecmp (argn[argc], "HIDDEN"))
299 pi->pluginsHidden = (!PL_strcasecmp (argv[argc], "TRUE"));
300 else if (!PL_strcasecmp (argn[argc], "DATA"))
301 pi->data = strdup (argv[argc]);
305 // create evas for this plugin instance
306 pi->evas = evas_new ();
308 pi->L = luaL_newstate ();
309 ego_sandbox (pi->L, 4);
310 luaopen_ego (pi->L);
312 lua_pushstring (pi->L, pi->data);
313 lua_setfield (pi->L, LUA_REGISTRYINDEX, "ego_file");
315 return NPERR_NO_ERROR;
318 NPError
319 NPP_Destroy (NPP instance, NPSavedData** save)
321 if (instance == NULL)
322 return NPERR_INVALID_INSTANCE_ERROR;
324 PluginInstance *pi = (PluginInstance*) instance->pdata;
326 pi->done = 1;
328 if (pi != NULL) {
329 if (pi->type)
330 NPN_MemFree(pi->type);
331 if (pi->pluginsPageUrl)
332 NPN_MemFree(pi->pluginsPageUrl);
333 if (pi->pluginsFileUrl)
334 NPN_MemFree(pi->pluginsFileUrl);
335 if (pi->L)
336 lua_close (pi->L);
337 if (pi->ego_obj)
338 evas_object_del (pi->ego_obj);
339 if (pi->theme_obj)
340 evas_object_del (pi->theme_obj);
341 if (pi->anim)
342 ecore_animator_del (pi->anim);
343 if (pi->evas)
344 evas_free (pi->evas);
345 NPN_MemFree(instance->pdata);
346 instance->pdata = NULL;
349 return NPERR_NO_ERROR;
352 static void
353 _config_fps_read (void *data)
355 PluginInstance *pi = (PluginInstance *) data;
356 int fps = ecore_config_int_get ("fps");
357 ecore_animator_frametime_set (1.0 / (double) fps);
358 edje_frametime_set (1.0 / (double) fps);
361 static void
362 _config_theme_read (void *data)
364 PluginInstance *pi = (PluginInstance *) data;
365 char path[256];
366 sprintf (path, "%s/%s", THEMEDIR, ecore_config_theme_get ("theme"));
367 edje_object_file_set (pi->theme_obj, path, "ego/theme");
370 static void
371 _config_engine_read (void *data)
373 PluginInstance *pi = (PluginInstance *) data;
374 int method = evas_render_method_lookup (ecore_config_string_get ("engine"));
375 if (method != evas_output_method_get (pi->evas))
377 if (method == evas_render_method_lookup ("software_x11"))
379 evas_output_method_set (pi->evas, method);
380 evas_output_size_set (pi->evas, pi->width, pi->height);
381 evas_output_viewport_set (pi->evas, 0, 0, pi->width, pi->height);
383 printf ("software_x11\n");
384 Evas_Engine_Info_Software_X11 *einfo = (Evas_Engine_Info_Software_X11 *) evas_engine_info_get (pi->evas);
385 /* the following is specific to the engine */
386 einfo->info.connection = pi->display;
387 einfo->info.visual = pi->visual;
388 einfo->info.colormap = pi->colormap;
389 einfo->info.drawable = (Drawable) pi->window;
390 einfo->info.depth = pi->depth;
391 einfo->info.rotation = 0;
392 einfo->info.debug = 0;
393 evas_engine_info_set(pi->evas, (Evas_Engine_Info *) einfo);
395 else if (method == evas_render_method_lookup ("gl_x11"))
397 evas_output_method_set (pi->evas, method);
398 evas_output_size_set (pi->evas, pi->width, pi->height);
399 evas_output_viewport_set (pi->evas, 0, 0, pi->width, pi->height);
401 printf ("gl_x11\n");
402 Evas_Engine_Info_GL_X11 *einfo = (Evas_Engine_Info_GL_X11 *) evas_engine_info_get (pi->evas);
403 /* the following is specific to the engine */
404 einfo->info.display = pi->display;
405 einfo->info.visual = pi->visual;
406 einfo->info.colormap = pi->colormap;
407 einfo->info.drawable = (Drawable) pi->window;
408 einfo->info.depth = pi->depth;
409 evas_engine_info_set(pi->evas, (Evas_Engine_Info *) einfo);
414 NPError
415 NPP_SetWindow (NPP instance, NPWindow *window)
417 if (instance == NULL)
418 return NPERR_INVALID_INSTANCE_ERROR;
420 PluginInstance *pi = (PluginInstance *) instance->pdata;
421 if (pi == NULL)
422 return NPERR_INVALID_INSTANCE_ERROR;
424 NPSetWindowCallbackStruct *ws_info = (NPSetWindowCallbackStruct *) window->ws_info;
426 if (pi->window == (Window) window->window) {
427 /* The page with the plugin is being resized.
428 Save any UI information because the next time
429 around expect a SetWindow with a new window
433 fprintf(stderr, "plugin received window resize.\n");
434 fprintf(stderr, "Window=(%i)\n", (int)window);
435 fprintf(stderr, "W=(%i) H=(%i)\n",
436 (int)window->width, (int)window->height);
439 return NPERR_NO_ERROR;
440 } else {
441 pi->window = (Window) window->window;
442 pi->x = window->x;
443 pi->y = window->y;
444 pi->width = window->width;
445 pi->height = window->height;
446 pi->display = ws_info->display;
447 pi->visual = ws_info->visual;
448 pi->depth = ws_info->depth;
449 pi->colormap = ws_info->colormap;
451 char path[256];
452 sprintf (path, "%s/%s", CONFIGDIR, "config.edb");
453 ecore_config_file_load (path);
455 _config_fps_read (pi);
456 _config_engine_read (pi);
458 // add animator to render evas
459 pi->anim = ecore_animator_add (mep_animator, pi);
460 ecore_animator_frametime_set (1.0 / 25.0);
461 evas_event_feed_mouse_in (pi->evas, 0, NULL);
463 NPN_GetURL (instance, pi->data, NULL);
465 // theme
466 pi->theme_obj = edje_object_add (pi->evas);
467 //edje_object_file_set (pi->theme_obj, THEMEDIR"/default.edj", "ego/theme");
468 _config_theme_read (pi);
469 edje_object_part_text_set (pi->theme_obj, "message", "loading");
470 edje_object_signal_emit (pi->theme_obj, "idle,start", "");
471 evas_object_resize (pi->theme_obj, pi->width, pi->height);
472 evas_object_focus_set (pi->theme_obj, 1);
473 evas_object_show (pi->theme_obj);
475 // set up message system
476 #if WINDOWED
477 Widget xtwidget = XtWindowToWidget (pi->display, pi->window);
478 long event_mask = NoEventMask |
479 ExposureMask |
480 ButtonPressMask |
481 ButtonReleaseMask |
482 PointerMotionMask |
483 StructureNotifyMask |
484 SubstructureNotifyMask |
485 EnterWindowMask |
486 LeaveWindowMask;
488 XSelectInput (pi->display, pi->window, event_mask);
489 XtAddEventHandler (xtwidget, event_mask, True, mep_event_handler, pi);
490 #endif /* WINDOWED */
492 #if COMPLIANT
493 pi->atom = XInternAtom (pi->display, "edje_atom", False);
494 pi->msg.type = ClientMessage;
495 pi->msg.display = pi->display;
496 pi->msg.window = pi->window;
497 pi->msg.message_type = pi->atom;
498 pi->msg.format = 32;
499 pi->msg.data.l[0] = 0;
500 #endif /* COMPLIANT */
502 pi->done = 0;
504 // initialize asynccallback loop
505 mep_asynccall (pi);
508 return NPERR_NO_ERROR;
511 NPError
512 NPP_NewStream (NPP instance,
513 NPMIMEType type,
514 NPStream *stream,
515 NPBool seekable,
516 uint16 *stype)
518 if (instance == NULL)
519 return NPERR_INVALID_INSTANCE_ERROR;
521 if (!strcmp (type, "application/x-ego"))
523 *stype = NP_ASFILEONLY; //ONLY
526 printf ("NPP_NewStream: %s %d\n", type, *stype);
528 return NPERR_NO_ERROR;
531 int32
532 NPP_WriteReady (NPP instance, NPStream *stream)
534 if (instance == NULL)
535 return NPERR_INVALID_INSTANCE_ERROR;
537 printf ("NPP_WriteReady\n");
539 /* We don't want any data, kill the stream */
540 NPN_DestroyStream(instance, stream, NPRES_DONE);
542 /* Number of bytes ready to accept in NPP_Write() */
543 return -1L; /* don't accept any bytes in NPP_Write() */
546 int32
547 NPP_Write (NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
549 if (instance == NULL)
550 return NPERR_INVALID_INSTANCE_ERROR;
552 printf ("NPP_Write\n");
554 /* We don't want any data, kill the stream */
555 NPN_DestroyStream(instance, stream, NPRES_DONE);
557 return -1L; /* don't accept any bytes in NPP_Write() */
560 NPError
561 NPP_DestroyStream (NPP instance, NPStream *stream, NPError reason)
563 if (instance == NULL)
564 return NPERR_INVALID_INSTANCE_ERROR;
566 /***** Insert NPP_DestroyStream code here *****\
567 PluginInstance* pi;
568 pi = (PluginInstance*) instance->pdata;
569 \**********************************************/
571 return NPERR_NO_ERROR;
574 void
575 NPP_StreamAsFile (NPP instance, NPStream *stream, const char* fname)
577 /***** Insert NPP_StreamAsFile code here *****\
578 PluginInstance* pi;
579 if (instance != NULL)
580 pi = (PluginInstance*) instance->pdata;
581 \*********************************************/
582 printf ("NPP_StreamAsFile: %s\n", fname);
583 PluginInstance *pi = (PluginInstance *) instance->pdata;
585 if (pi->data)
586 NPN_MemFree (pi->data);
587 pi->data = fname;
588 edje_object_part_text_set (pi->theme_obj, "message", "loaded");
589 edje_object_signal_emit (pi->theme_obj, "idle,stop", "");
591 // load ego file
592 Eet_File *fl_file = eet_open (pi->data, EET_FILE_MODE_READ);
593 void *globbuf;
594 int globbufsize;
596 globbuf = eet_read (fl_file, "ego/bytecode", &globbufsize);
597 printf ("globbufsize: %d\n", globbufsize);
599 int num, i;
600 char **keys = eet_list (fl_file, "*", &num);
601 for (i = 0; i < num; i++)
602 printf ("%d: %s\n", i, keys[i]);
603 free (keys);
605 // ego
606 if (luaL_loadbuffer (pi->L, globbuf, globbufsize, NULL))
607 printf ("ego load chunk error: %s\n", luaL_checkstring (pi->L, -1));
608 pi->ego_obj = ego_object_add (pi->evas, pi->L);
609 evas_object_show (pi->ego_obj);
610 edje_object_part_swallow (pi->theme_obj, "content", pi->ego_obj);
612 free (globbuf);
613 eet_close (fl_file);
616 void
617 NPP_URLNotify (NPP instance, const char* url,
618 NPReason reason, void* notifyData)
620 /***** Insert NPP_URLNotify code here *****\
621 PluginInstance* pi;
622 if (instance != NULL)
623 pi = (PluginInstance*) instance->pdata;
624 \*********************************************/
625 printf ("URLNotify: %s\n", url);
628 void
629 NPP_Print (NPP instance, NPPrint* printInfo)
631 if(printInfo == NULL)
632 return;
634 if (instance != NULL) {
635 /***** Insert NPP_Print code here *****\
636 PluginInstance* pi = (PluginInstance*) instance->pdata;
637 \**************************************/
639 if (printInfo->mode == NP_FULL) {
641 * PLUGIN DEVELOPERS:
642 * If your plugin would like to take over
643 * printing completely when it is in full-screen mode,
644 * set printInfo->pluginPrinted to TRUE and print your
645 * plugin as you see fit. If your plugin wants Netscape
646 * to handle printing in this case, set
647 * printInfo->pluginPrinted to FALSE (the default) and
648 * do nothing. If you do want to handle printing
649 * yourself, printOne is true if the print button
650 * (as opposed to the print menu) was clicked.
651 * On the Macintosh, platformPrint is a THPrint; on
652 * Windows, platformPrint is a structure
653 * (defined in npapi.h) containing the printer name, port,
654 * etc.
657 /***** Insert NPP_Print code here *****\
658 void* platformPrint =
659 printInfo->print.fullPrint.platformPrint;
660 NPBool printOne =
661 printInfo->print.fullPrint.printOne;
662 \**************************************/
664 /* Do the default*/
665 printInfo->print.fullPrint.pluginPrinted = FALSE;
667 else { /* If not fullscreen, we must be embedded */
669 * PLUGIN DEVELOPERS:
670 * If your plugin is embedded, or is full-screen
671 * but you returned false in pluginPrinted above, NPP_Print
672 * will be called with mode == NP_EMBED. The NPWindow
673 * in the printInfo gives the location and dimensions of
674 * the embedded plugin on the printed page. On the
675 * Macintosh, platformPrint is the printer port; on
676 * Windows, platformPrint is the handle to the printing
677 * device context.
680 /***** Insert NPP_Print code here *****\
681 NPWindow* printWindow =
682 &(printInfo->print.embedPrint.window);
683 void* platformPrint =
684 printInfo->print.embedPrint.platformPrint;
685 \**************************************/