added file streaming support
[ego.git] / src / plugin / egoplayer.c
blob3f097d5802ce42983c195561e724b8e87e1286e8
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->config_obj)
340 evas_object_del (pi->config_obj);
341 if (pi->theme_obj)
342 evas_object_del (pi->theme_obj);
343 if (pi->anim)
344 ecore_animator_del (pi->anim);
345 if (pi->evas)
346 evas_free (pi->evas);
347 NPN_MemFree(instance->pdata);
348 instance->pdata = NULL;
351 return NPERR_NO_ERROR;
354 static void
355 _config_fps_read (void *data)
357 PluginInstance *pi = (PluginInstance *) data;
358 int fps = ecore_config_int_get ("fps");
359 ecore_animator_frametime_set (1.0 / (double) fps);
360 edje_frametime_set (1.0 / (double) fps);
363 static void
364 _config_fps_write (void *data, Evas_Object *obj, void *event_info)
366 PluginInstance *pi = (PluginInstance *) data;
367 int fps = atoi (elm_entry_entry_get (obj));
368 ecore_config_int_set ("fps", fps);
369 ecore_config_save ();
370 _config_fps_read (pi);
373 static void
374 _config_theme_read (void *data)
376 PluginInstance *pi = (PluginInstance *) data;
377 char path[256];
378 sprintf (path, "%s/%s", THEMEDIR, ecore_config_theme_get ("theme"));
379 edje_object_file_set (pi->theme_obj, path, "ego/theme");
382 static void
383 _config_theme_write (void *data, Evas_Object *obj, void *event_info)
385 PluginInstance *pi = (PluginInstance *) data;
386 ecore_config_theme_set ("theme", elm_entry_entry_get (obj));
387 ecore_config_save ();
388 _config_theme_read (pi);
391 static void
392 _config_engine_read (void *data)
394 PluginInstance *pi = (PluginInstance *) data;
395 int method = evas_render_method_lookup (ecore_config_string_get ("engine"));
396 if (method != evas_output_method_get (pi->evas))
398 if (method == evas_render_method_lookup ("software_x11"))
400 evas_output_method_set (pi->evas, method);
401 evas_output_size_set (pi->evas, pi->width, pi->height);
402 evas_output_viewport_set (pi->evas, 0, 0, pi->width, pi->height);
404 printf ("software_x11\n");
405 Evas_Engine_Info_Software_X11 *einfo = (Evas_Engine_Info_Software_X11 *) evas_engine_info_get (pi->evas);
406 /* the following is specific to the engine */
407 einfo->info.display = pi->display;
408 einfo->info.visual = pi->visual;
409 einfo->info.colormap = pi->colormap;
410 einfo->info.drawable = (Drawable) pi->window;
411 einfo->info.depth = pi->depth;
412 einfo->info.rotation = 0;
413 einfo->info.debug = 0;
414 evas_engine_info_set(pi->evas, (Evas_Engine_Info *) einfo);
416 else if (method == evas_render_method_lookup ("gl_x11"))
418 evas_output_method_set (pi->evas, method);
419 evas_output_size_set (pi->evas, pi->width, pi->height);
420 evas_output_viewport_set (pi->evas, 0, 0, pi->width, pi->height);
422 printf ("gl_x11\n");
423 Evas_Engine_Info_GL_X11 *einfo = (Evas_Engine_Info_GL_X11 *) evas_engine_info_get (pi->evas);
424 /* the following is specific to the engine */
425 einfo->info.display = pi->display;
426 einfo->info.visual = pi->visual;
427 einfo->info.colormap = pi->colormap;
428 einfo->info.drawable = (Drawable) pi->window;
429 einfo->info.depth = pi->depth;
430 evas_engine_info_set(pi->evas, (Evas_Engine_Info *) einfo);
435 static void
436 _config_engine_write (void *data, Evas_Object *obj, void *event_info)
438 PluginInstance *pi = (PluginInstance *) data;
439 int ptr;
440 printf ("%d\n", pi->engine_toggle);
441 if (pi->engine_toggle == 0)
442 ecore_config_string_set ("engine", "gl_x11");
443 else
444 ecore_config_string_set ("engine", "software_x11");
445 ecore_config_save ();
446 _config_engine_read (pi);
449 NPError
450 NPP_SetWindow (NPP instance, NPWindow *window)
452 if (instance == NULL)
453 return NPERR_INVALID_INSTANCE_ERROR;
455 PluginInstance *pi = (PluginInstance *) instance->pdata;
456 if (pi == NULL)
457 return NPERR_INVALID_INSTANCE_ERROR;
459 NPSetWindowCallbackStruct *ws_info = (NPSetWindowCallbackStruct *) window->ws_info;
461 if (pi->window == (Window) window->window) {
462 /* The page with the plugin is being resized.
463 Save any UI information because the next time
464 around expect a SetWindow with a new window
468 fprintf(stderr, "plugin received window resize.\n");
469 fprintf(stderr, "Window=(%i)\n", (int)window);
470 fprintf(stderr, "W=(%i) H=(%i)\n",
471 (int)window->width, (int)window->height);
474 return NPERR_NO_ERROR;
475 } else {
476 pi->window = (Window) window->window;
477 pi->x = window->x;
478 pi->y = window->y;
479 pi->width = window->width;
480 pi->height = window->height;
481 pi->display = ws_info->display;
482 pi->visual = ws_info->visual;
483 pi->depth = ws_info->depth;
484 pi->colormap = ws_info->colormap;
486 char path[256];
487 sprintf (path, "%s/%s", CONFIGDIR, "config.edb");
488 ecore_config_file_load (path);
490 _config_fps_read (pi);
491 _config_engine_read (pi);
493 // add animator to render evas
494 pi->anim = ecore_animator_add (mep_animator, pi);
495 ecore_animator_frametime_set (1.0 / 25.0);
496 evas_event_feed_mouse_in (pi->evas, 0, NULL);
498 NPN_GetURL (instance, pi->data, NULL);
500 // theme
501 pi->theme_obj = edje_object_add (pi->evas);
502 //edje_object_file_set (pi->theme_obj, THEMEDIR"/default.edj", "ego/theme");
503 _config_theme_read (pi);
504 edje_object_part_text_set (pi->theme_obj, "message", "loading");
505 edje_object_signal_emit (pi->theme_obj, "idle,start", "");
506 evas_object_resize (pi->theme_obj, pi->width, pi->height);
507 evas_object_focus_set (pi->theme_obj, 1);
508 evas_object_show (pi->theme_obj);
510 // menu
512 Evas_Object *tab = elm_table_add (pi->theme_obj);
513 elm_table_homogenous_set (tab, 0);
514 evas_object_show (tab);
516 Evas_Object *lab_fps = elm_label_add (pi->theme_obj);
517 elm_label_label_set (lab_fps, "fps");
518 elm_table_pack (tab, lab_fps, 0, 0, 1, 1);
519 evas_object_show (lab_fps);
521 Evas_Object *entry_fps = elm_entry_add (pi->theme_obj);
522 elm_entry_entry_set (entry_fps, "25");
523 elm_entry_single_line_set (entry_fps, 1);
524 elm_entry_editable_set (entry_fps, 1);
525 elm_table_pack (tab, entry_fps, 1, 0, 1, 1);
526 evas_object_show (entry_fps);
528 Evas_Object *lab_engine = elm_label_add (pi->theme_obj);
529 elm_label_label_set (lab_engine, "engine");
530 elm_table_pack (tab, lab_engine, 0, 1, 1, 1);
531 evas_object_show (lab_engine);
533 Evas_Object *toggle_engine = elm_toggle_add (pi->theme_obj);
534 elm_toggle_states_labels_set (toggle_engine, "software_x11", "gl_x11");
535 elm_toggle_state_pointer_set (toggle_engine, &(pi->engine_toggle));
536 elm_toggle_state_set (toggle_engine, 1);
537 elm_table_pack (tab, toggle_engine, 1, 1, 1, 1);
538 evas_object_show (toggle_engine);
539 evas_object_smart_callback_add (toggle_engine, "changed", _config_engine_write, pi);
541 Evas_Object *lab_theme = elm_label_add (pi->theme_obj);
542 elm_label_label_set (lab_theme, "theme");
543 elm_table_pack (tab, lab_theme, 0, 2, 1, 1);
544 evas_object_show (lab_theme);
546 Evas_Object *entry_theme = elm_entry_add (pi->theme_obj);
547 elm_entry_entry_set (entry_theme, "default.edj");
548 elm_entry_single_line_set (entry_theme, 1);
549 elm_entry_editable_set (entry_theme, 1);
550 elm_table_pack (tab, entry_theme, 1, 2, 1, 1);
551 evas_object_show (entry_theme);
553 pi->config_obj = elm_frame_add (pi->theme_obj);
554 elm_frame_label_set (pi->config_obj, "E Goes Online");
555 elm_frame_content_set (pi->config_obj, tab);
556 edje_object_part_swallow (pi->theme_obj, "config.content", pi->config_obj);
559 // set up message system
560 #if WINDOWED
561 Widget xtwidget = XtWindowToWidget (pi->display, pi->window);
562 long event_mask = NoEventMask |
563 ExposureMask |
564 ButtonPressMask |
565 ButtonReleaseMask |
566 PointerMotionMask |
567 StructureNotifyMask |
568 SubstructureNotifyMask |
569 EnterWindowMask |
570 LeaveWindowMask;
572 XSelectInput (pi->display, pi->window, event_mask);
573 XtAddEventHandler (xtwidget, event_mask, True, mep_event_handler, pi);
574 #endif /* WINDOWED */
576 #if COMPLIANT
577 pi->atom = XInternAtom (pi->display, "edje_atom", False);
578 pi->msg.type = ClientMessage;
579 pi->msg.display = pi->display;
580 pi->msg.window = pi->window;
581 pi->msg.message_type = pi->atom;
582 pi->msg.format = 32;
583 pi->msg.data.l[0] = 0;
584 #endif /* COMPLIANT */
586 pi->done = 0;
588 // initialize asynccallback loop
589 mep_asynccall (pi);
592 return NPERR_NO_ERROR;
595 NPError
596 NPP_NewStream (NPP instance,
597 NPMIMEType type,
598 NPStream *stream,
599 NPBool seekable,
600 uint16 *stype)
602 if (instance == NULL)
603 return NPERR_INVALID_INSTANCE_ERROR;
605 if (!strcmp (type, "application/x-ego"))
607 *stype = NP_ASFILEONLY; //ONLY
610 printf ("NPP_NewStream: %s %d\n", type, *stype);
612 return NPERR_NO_ERROR;
615 int32
616 NPP_WriteReady (NPP instance, NPStream *stream)
618 if (instance == NULL)
619 return NPERR_INVALID_INSTANCE_ERROR;
621 printf ("NPP_WriteReady\n");
623 /* We don't want any data, kill the stream */
624 NPN_DestroyStream(instance, stream, NPRES_DONE);
626 /* Number of bytes ready to accept in NPP_Write() */
627 return -1L; /* don't accept any bytes in NPP_Write() */
630 int32
631 NPP_Write (NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
633 if (instance == NULL)
634 return NPERR_INVALID_INSTANCE_ERROR;
636 printf ("NPP_Write\n");
638 /* We don't want any data, kill the stream */
639 NPN_DestroyStream(instance, stream, NPRES_DONE);
641 return -1L; /* don't accept any bytes in NPP_Write() */
644 NPError
645 NPP_DestroyStream (NPP instance, NPStream *stream, NPError reason)
647 if (instance == NULL)
648 return NPERR_INVALID_INSTANCE_ERROR;
650 /***** Insert NPP_DestroyStream code here *****\
651 PluginInstance* pi;
652 pi = (PluginInstance*) instance->pdata;
653 \**********************************************/
655 return NPERR_NO_ERROR;
658 void
659 NPP_StreamAsFile (NPP instance, NPStream *stream, const char* fname)
661 /***** Insert NPP_StreamAsFile code here *****\
662 PluginInstance* pi;
663 if (instance != NULL)
664 pi = (PluginInstance*) instance->pdata;
665 \*********************************************/
666 printf ("NPP_StreamAsFile: %s\n", fname);
667 PluginInstance *pi = (PluginInstance *) instance->pdata;
669 if (pi->data)
670 NPN_MemFree (pi->data);
671 pi->data = fname;
672 edje_object_part_text_set (pi->theme_obj, "message", "loaded");
673 edje_object_signal_emit (pi->theme_obj, "idle,stop", "");
675 // load ego file
676 Eet_File *fl_file = eet_open (pi->data, EET_FILE_MODE_READ);
677 void *globbuf;
678 int globbufsize;
680 globbuf = eet_read (fl_file, "ego/bytecode", &globbufsize);
681 printf ("globbufsize: %d\n", globbufsize);
683 int num, i;
684 char **keys = eet_list (fl_file, "*", &num);
685 for (i = 0; i < num; i++)
686 printf ("%d: %s\n", i, keys[i]);
687 free (keys);
689 // ego
690 if (luaL_loadbuffer (pi->L, globbuf, globbufsize, NULL))
691 printf ("ego load chunk error: %s\n", luaL_checkstring (pi->L, -1));
692 pi->ego_obj = ego_object_add (pi->evas, pi->L);
693 evas_object_show (pi->ego_obj);
694 edje_object_part_swallow (pi->theme_obj, "content", pi->ego_obj);
696 free (globbuf);
697 eet_close (fl_file);
700 void
701 NPP_URLNotify (NPP instance, const char* url,
702 NPReason reason, void* notifyData)
704 /***** Insert NPP_URLNotify code here *****\
705 PluginInstance* pi;
706 if (instance != NULL)
707 pi = (PluginInstance*) instance->pdata;
708 \*********************************************/
709 printf ("URLNotify: %s\n", url);
712 void
713 NPP_Print (NPP instance, NPPrint* printInfo)
715 if(printInfo == NULL)
716 return;
718 if (instance != NULL) {
719 /***** Insert NPP_Print code here *****\
720 PluginInstance* pi = (PluginInstance*) instance->pdata;
721 \**************************************/
723 if (printInfo->mode == NP_FULL) {
725 * PLUGIN DEVELOPERS:
726 * If your plugin would like to take over
727 * printing completely when it is in full-screen mode,
728 * set printInfo->pluginPrinted to TRUE and print your
729 * plugin as you see fit. If your plugin wants Netscape
730 * to handle printing in this case, set
731 * printInfo->pluginPrinted to FALSE (the default) and
732 * do nothing. If you do want to handle printing
733 * yourself, printOne is true if the print button
734 * (as opposed to the print menu) was clicked.
735 * On the Macintosh, platformPrint is a THPrint; on
736 * Windows, platformPrint is a structure
737 * (defined in npapi.h) containing the printer name, port,
738 * etc.
741 /***** Insert NPP_Print code here *****\
742 void* platformPrint =
743 printInfo->print.fullPrint.platformPrint;
744 NPBool printOne =
745 printInfo->print.fullPrint.printOne;
746 \**************************************/
748 /* Do the default*/
749 printInfo->print.fullPrint.pluginPrinted = FALSE;
751 else { /* If not fullscreen, we must be embedded */
753 * PLUGIN DEVELOPERS:
754 * If your plugin is embedded, or is full-screen
755 * but you returned false in pluginPrinted above, NPP_Print
756 * will be called with mode == NP_EMBED. The NPWindow
757 * in the printInfo gives the location and dimensions of
758 * the embedded plugin on the printed page. On the
759 * Macintosh, platformPrint is the printer port; on
760 * Windows, platformPrint is the handle to the printing
761 * device context.
764 /***** Insert NPP_Print code here *****\
765 NPWindow* printWindow =
766 &(printInfo->print.embedPrint.window);
767 void* platformPrint =
768 printInfo->print.embedPrint.platformPrint;
769 \**************************************/