added elementary layout, clock. prototyped plugin configuration
[ego.git] / src / plugin / egoplayer.c
blob0169e06c8018daf25de38a3603b8bfc6e2746898
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 #if WINDOWED
49 int
50 mep_animator (void *data)
52 PluginInstance *pi = (PluginInstance *) data;
53 evas_render (pi->evas);
54 return 1;
56 #endif /* WINDOWED */
58 void
59 mep_event_handler (Widget xtwidget, void *data, XEvent *xevent, Boolean *b)
61 PluginInstance *pi = (PluginInstance *) data;
62 NPP_HandleEvent (pi->instance, xevent);
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->evas)
338 evas_free (pi->evas);
339 if (pi->data)
340 NPN_MemFree (pi->data);
341 NPN_MemFree(instance->pdata);
342 instance->pdata = NULL;
345 return NPERR_NO_ERROR;
348 static void
349 _config_fps_read (void *data)
351 PluginInstance *pi = (PluginInstance *) data;
352 int fps = ecore_config_int_get ("fps");
353 ecore_animator_frametime_set (1.0 / (double) fps);
354 edje_frametime_set (1.0 / (double) fps);
357 static void
358 _config_fps_write (void *data, Evas_Object *obj, void *event_info)
360 PluginInstance *pi = (PluginInstance *) data;
361 int fps = atoi (elm_entry_entry_get (obj));
362 ecore_config_int_set ("fps", fps);
363 _config_fps_read (pi);
366 static void
367 _config_theme_read (void *data)
369 PluginInstance *pi = (PluginInstance *) data;
370 char path[256];
371 sprintf (path, "%s/%s", THEMEDIR, ecore_config_theme_get ("theme"));
372 edje_object_file_set (pi->theme_obj, path, "ego/theme");
375 static void
376 _config_theme_write (void *data, Evas_Object *obj, void *event_info)
378 PluginInstance *pi = (PluginInstance *) data;
379 ecore_config_theme_set ("theme", elm_entry_entry_get (obj));
380 _config_theme_read (pi);
383 static void
384 _config_engine_read (void *data)
386 PluginInstance *pi = (PluginInstance *) data;
387 int method = evas_render_method_lookup (ecore_config_string_get ("engine"));
388 if (method != evas_output_method_get (pi->evas))
390 evas_output_method_set (pi->evas, method);
391 evas_output_size_set (pi->evas, pi->width, pi->height);
392 evas_output_viewport_set (pi->evas, 0, 0, pi->width, pi->height);
394 if (method == evas_render_method_lookup ("software_x11"))
396 printf ("software_x11\n");
397 Evas_Engine_Info_Software_X11 *einfo = (Evas_Engine_Info_Software_X11 *) evas_engine_info_get (pi->evas);
398 /* the following is specific to the engine */
399 einfo->info.display = pi->display;
400 einfo->info.visual = pi->visual;
401 einfo->info.colormap = pi->colormap;
402 einfo->info.drawable = (Drawable) pi->window;
403 einfo->info.depth = pi->depth;
404 einfo->info.rotation = 0;
405 einfo->info.debug = 0;
406 evas_engine_info_set(pi->evas, (Evas_Engine_Info *) einfo);
408 else if (method == evas_render_method_lookup ("gl_x11"))
410 printf ("gl_x11\n");
411 Evas_Engine_Info_GL_X11 *einfo = (Evas_Engine_Info_GL_X11 *) evas_engine_info_get (pi->evas);
412 /* the following is specific to the engine */
413 einfo->info.display = pi->display;
414 einfo->info.visual = pi->visual;
415 einfo->info.colormap = pi->colormap;
416 einfo->info.drawable = (Drawable) pi->window;
417 einfo->info.depth = pi->depth;
418 evas_engine_info_set(pi->evas, (Evas_Engine_Info *) einfo);
423 static void
424 _config_engine_write (void *data, Evas_Object *obj, void *event_info)
426 PluginInstance *pi = (PluginInstance *) data;
427 int ptr;
428 printf ("%d\n", pi->engine_toggle);
429 if (pi->engine_toggle == 0)
430 ecore_config_string_set ("engine", "gl_x11");
431 else
432 ecore_config_string_set ("engine", "software_x11");
433 _config_engine_read (pi);
436 NPError
437 NPP_SetWindow (NPP instance, NPWindow *window)
439 if (instance == NULL)
440 return NPERR_INVALID_INSTANCE_ERROR;
442 PluginInstance *pi = (PluginInstance *) instance->pdata;
443 if (pi == NULL)
444 return NPERR_INVALID_INSTANCE_ERROR;
446 NPSetWindowCallbackStruct *ws_info = (NPSetWindowCallbackStruct *) window->ws_info;
448 if (pi->window == (Window) window->window) {
449 /* The page with the plugin is being resized.
450 Save any UI information because the next time
451 around expect a SetWindow with a new window
455 fprintf(stderr, "plugin received window resize.\n");
456 fprintf(stderr, "Window=(%i)\n", (int)window);
457 fprintf(stderr, "W=(%i) H=(%i)\n",
458 (int)window->width, (int)window->height);
461 return NPERR_NO_ERROR;
462 } else {
463 pi->window = (Window) window->window;
464 pi->x = window->x;
465 pi->y = window->y;
466 pi->width = window->width;
467 pi->height = window->height;
468 pi->display = ws_info->display;
469 pi->visual = ws_info->visual;
470 pi->depth = ws_info->depth;
471 pi->colormap = ws_info->colormap;
473 char path[256];
474 sprintf (path, "%s/%s", CONFIGDIR, "config.edb");
475 ecore_config_file_load (path);
477 _config_fps_read (pi);
478 _config_engine_read (pi);
480 // add animator to render evas
481 ecore_animator_add (mep_animator, pi);
482 ecore_animator_frametime_set (1.0 / 25.0);
483 evas_event_feed_mouse_in (pi->evas, 0, NULL);
485 // load ego file
486 Eet_File *fl_file = eet_open (pi->data, EET_FILE_MODE_READ);
487 void *globbuf;
488 int globbufsize;
490 globbuf = eet_read (fl_file, "ego/bytecode", &globbufsize);
491 printf ("globbufsize: %d\n", globbufsize);
493 int num, i;
494 char **keys = eet_list (fl_file, "*", &num);
495 for (i = 0; i < num; i++)
496 printf ("%d: %s\n", i, keys[i]);
497 free (keys);
499 // ego
500 if (luaL_loadbuffer (pi->L, globbuf, globbufsize, NULL))
501 printf ("ego load chunk error: %s\n", luaL_checkstring (pi->L, -1));
502 pi->ego_obj = ego_object_add (pi->evas, pi->L);
503 evas_object_show (pi->ego_obj);
504 evas_object_focus_set (pi->ego_obj, 1);
506 // theme
507 pi->theme_obj = edje_object_add (pi->evas);
508 //edje_object_file_set (pi->theme_obj, THEMEDIR"/default.edj", "ego/theme");
509 _config_theme_read (pi);
510 edje_object_part_swallow (pi->theme_obj, "content", pi->ego_obj);
511 edje_object_part_text_set (pi->theme_obj, "message", "loading");
512 edje_object_signal_emit (pi->theme_obj, "idle,start", "");
513 evas_object_resize (pi->theme_obj, pi->width, pi->height);
514 evas_object_show (pi->theme_obj);
516 // menu
518 Evas_Object *tab = elm_table_add (pi->theme_obj);
519 elm_table_homogenous_set (tab, 0);
520 evas_object_show (tab);
522 Evas_Object *lab_fps = elm_label_add (pi->theme_obj);
523 elm_label_label_set (lab_fps, "fps");
524 elm_table_pack (tab, lab_fps, 0, 0, 1, 1);
525 evas_object_show (lab_fps);
527 Evas_Object *entry_fps = elm_entry_add (pi->theme_obj);
528 elm_entry_entry_set (entry_fps, "25");
529 elm_entry_single_line_set (entry_fps, 1);
530 elm_entry_editable_set (entry_fps, 1);
531 elm_table_pack (tab, entry_fps, 1, 0, 1, 1);
532 evas_object_show (entry_fps);
534 Evas_Object *lab_engine = elm_label_add (pi->theme_obj);
535 elm_label_label_set (lab_engine, "engine");
536 elm_table_pack (tab, lab_engine, 0, 1, 1, 1);
537 evas_object_show (lab_engine);
539 Evas_Object *toggle_engine = elm_toggle_add (pi->theme_obj);
540 elm_toggle_states_labels_set (toggle_engine, "software_x11", "gl_x11");
541 elm_toggle_state_pointer_set (toggle_engine, &(pi->engine_toggle));
542 elm_toggle_state_set (toggle_engine, 1);
543 elm_table_pack (tab, toggle_engine, 1, 1, 1, 1);
544 evas_object_show (toggle_engine);
545 evas_object_smart_callback_add (toggle_engine, "changed", _config_engine_write, pi);
547 Evas_Object *lab_theme = elm_label_add (pi->theme_obj);
548 elm_label_label_set (lab_theme, "theme");
549 elm_table_pack (tab, lab_theme, 0, 2, 1, 1);
550 evas_object_show (lab_theme);
552 Evas_Object *entry_theme = elm_entry_add (pi->theme_obj);
553 elm_entry_entry_set (entry_theme, "default.edj");
554 elm_entry_single_line_set (entry_theme, 1);
555 elm_entry_editable_set (entry_theme, 1);
556 elm_table_pack (tab, entry_theme, 1, 2, 1, 1);
557 evas_object_show (entry_theme);
559 pi->config_obj = elm_frame_add (pi->theme_obj);
560 elm_frame_label_set (pi->config_obj, "E Goes Online");
561 elm_frame_content_set (pi->config_obj, tab);
562 edje_object_part_swallow (pi->theme_obj, "config.content", pi->config_obj);
565 free (globbuf);
566 eet_close (fl_file);
568 // set up message system
569 #if WINDOWED
570 Widget xtwidget = XtWindowToWidget (pi->display, pi->window);
571 long event_mask = NoEventMask |
572 ExposureMask |
573 ButtonPressMask |
574 ButtonReleaseMask |
575 PointerMotionMask |
576 StructureNotifyMask |
577 SubstructureNotifyMask |
578 EnterWindowMask |
579 LeaveWindowMask;
581 XSelectInput (pi->display, pi->window, event_mask);
582 XtAddEventHandler (xtwidget, event_mask, True, mep_event_handler, pi);
583 #endif /* WINDOWED */
585 #if COMPLIANT
586 pi->atom = XInternAtom (pi->display, "edje_atom", False);
587 pi->msg.type = ClientMessage;
588 pi->msg.display = pi->display;
589 pi->msg.window = pi->window;
590 pi->msg.message_type = pi->atom;
591 pi->msg.format = 32;
592 pi->msg.data.l[0] = 0;
593 #endif /* COMPLIANT */
595 pi->done = 0;
597 // initialize asynccallback loop
598 mep_asynccall (pi);
601 return NPERR_NO_ERROR;
604 NPError
605 NPP_NewStream (NPP instance,
606 NPMIMEType type,
607 NPStream *stream,
608 NPBool seekable,
609 uint16 *stype)
611 if (instance == NULL)
612 return NPERR_INVALID_INSTANCE_ERROR;
614 printf ("NPP_NewStream: %s %d\n", type, *stype);
616 return NPERR_NO_ERROR;
619 int32
620 NPP_WriteReady (NPP instance, NPStream *stream)
622 if (instance == NULL)
623 return NPERR_INVALID_INSTANCE_ERROR;
625 printf ("NPP_WriteReady\n");
627 /* We don't want any data, kill the stream */
628 NPN_DestroyStream(instance, stream, NPRES_DONE);
630 /* Number of bytes ready to accept in NPP_Write() */
631 return -1L; /* don't accept any bytes in NPP_Write() */
634 int32
635 NPP_Write (NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
637 if (instance == NULL)
638 return NPERR_INVALID_INSTANCE_ERROR;
640 printf ("NPP_Write\n");
642 /* We don't want any data, kill the stream */
643 NPN_DestroyStream(instance, stream, NPRES_DONE);
645 return -1L; /* don't accept any bytes in NPP_Write() */
648 NPError
649 NPP_DestroyStream (NPP instance, NPStream *stream, NPError reason)
651 if (instance == NULL)
652 return NPERR_INVALID_INSTANCE_ERROR;
654 /***** Insert NPP_DestroyStream code here *****\
655 PluginInstance* pi;
656 pi = (PluginInstance*) instance->pdata;
657 \**********************************************/
659 return NPERR_NO_ERROR;
662 void
663 NPP_StreamAsFile (NPP instance, NPStream *stream, const char* fname)
665 /***** Insert NPP_StreamAsFile code here *****\
666 PluginInstance* pi;
667 if (instance != NULL)
668 pi = (PluginInstance*) instance->pdata;
669 \*********************************************/
670 printf ("NPP_StreamAsFile: %s\n", fname);
673 void
674 NPP_URLNotify (NPP instance, const char* url,
675 NPReason reason, void* notifyData)
677 /***** Insert NPP_URLNotify code here *****\
678 PluginInstance* pi;
679 if (instance != NULL)
680 pi = (PluginInstance*) instance->pdata;
681 \*********************************************/
682 printf ("URLNotify: %s\n", url);
685 void
686 NPP_Print (NPP instance, NPPrint* printInfo)
688 if(printInfo == NULL)
689 return;
691 if (instance != NULL) {
692 /***** Insert NPP_Print code here *****\
693 PluginInstance* pi = (PluginInstance*) instance->pdata;
694 \**************************************/
696 if (printInfo->mode == NP_FULL) {
698 * PLUGIN DEVELOPERS:
699 * If your plugin would like to take over
700 * printing completely when it is in full-screen mode,
701 * set printInfo->pluginPrinted to TRUE and print your
702 * plugin as you see fit. If your plugin wants Netscape
703 * to handle printing in this case, set
704 * printInfo->pluginPrinted to FALSE (the default) and
705 * do nothing. If you do want to handle printing
706 * yourself, printOne is true if the print button
707 * (as opposed to the print menu) was clicked.
708 * On the Macintosh, platformPrint is a THPrint; on
709 * Windows, platformPrint is a structure
710 * (defined in npapi.h) containing the printer name, port,
711 * etc.
714 /***** Insert NPP_Print code here *****\
715 void* platformPrint =
716 printInfo->print.fullPrint.platformPrint;
717 NPBool printOne =
718 printInfo->print.fullPrint.printOne;
719 \**************************************/
721 /* Do the default*/
722 printInfo->print.fullPrint.pluginPrinted = FALSE;
724 else { /* If not fullscreen, we must be embedded */
726 * PLUGIN DEVELOPERS:
727 * If your plugin is embedded, or is full-screen
728 * but you returned false in pluginPrinted above, NPP_Print
729 * will be called with mode == NP_EMBED. The NPWindow
730 * in the printInfo gives the location and dimensions of
731 * the embedded plugin on the printed page. On the
732 * Macintosh, platformPrint is the printer port; on
733 * Windows, platformPrint is the handle to the printing
734 * device context.
737 /***** Insert NPP_Print code here *****\
738 NPWindow* printWindow =
739 &(printInfo->print.embedPrint.window);
740 void* platformPrint =
741 printInfo->print.embedPrint.platformPrint;
742 \**************************************/