Code cleanup; fixed possible memery corruption; Updated source code headers
[ArenaLive.git] / ns-unix.c
blob9612dee65686bb768bc9775285ddd235ae6397b2
1 /*
2 * (C) Copyright 2009 ZeXx86 (zexx86@gmail.com)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
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.
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
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Based on GLugin http://exa.czweb.org/repos/glugin.tar.bz2
19 * Big thanks for "exa"
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/types.h>
29 #include <signal.h>
31 #include <GL/glx.h>
33 #include "glugin.h"
35 static NPNetscapeFuncs gNetscapeFuncs; /* Netscape Function table */
37 /* prototypes */
38 void plugin_process_handler (pluginData *, Window, Visual *);
41 NPError NP_Initialize (NPNetscapeFuncs *nsTable, NPPluginFuncs *pluginFuncs)
43 Log ("init");
45 /* this is respectfully taken from mplayerplug-in, as it was observed
46 * and proved to be extremely useful. */
47 if ((nsTable == NULL) || (pluginFuncs == NULL))
48 return NPERR_INVALID_FUNCTABLE_ERROR;
50 Log ("table ok");
52 if ((nsTable->version >> 8) > NP_VERSION_MAJOR)
53 return NPERR_INCOMPATIBLE_VERSION_ERROR;
55 Log ("table version ok");
57 /*check for table size removed, probable alignment or such problems.
60 if (nsTable->size < sizeof(NPNetscapeFuncs))
61 return NPERR_INVALID_FUNCTABLE_ERROR;
62 Log("table size ok");
66 if (pluginFuncs->size < sizeof (NPPluginFuncs))
67 return NPERR_INVALID_FUNCTABLE_ERROR;
69 Log ("ok pluginfuncs size check");
71 Log ("ok initing");
73 gNetscapeFuncs.version = nsTable->version;
74 gNetscapeFuncs.size = nsTable->size;
75 gNetscapeFuncs.posturl = nsTable->posturl;
76 gNetscapeFuncs.geturl = nsTable->geturl;
77 gNetscapeFuncs.requestread = nsTable->requestread;
78 gNetscapeFuncs.newstream = nsTable->newstream;
79 gNetscapeFuncs.write = nsTable->write;
80 gNetscapeFuncs.destroystream = nsTable->destroystream;
81 gNetscapeFuncs.status = nsTable->status;
82 gNetscapeFuncs.uagent = nsTable->uagent;
83 gNetscapeFuncs.memalloc = nsTable->memalloc;
84 gNetscapeFuncs.memfree = nsTable->memfree;
85 gNetscapeFuncs.memflush = nsTable->memflush;
86 gNetscapeFuncs.reloadplugins = nsTable->reloadplugins;
87 gNetscapeFuncs.getJavaEnv = nsTable->getJavaEnv;
88 gNetscapeFuncs.getJavaPeer = nsTable->getJavaPeer;
89 gNetscapeFuncs.getvalue = nsTable->getvalue;
90 gNetscapeFuncs.setvalue = nsTable->setvalue;
92 pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
93 pluginFuncs->size = sizeof (NPPluginFuncs);
94 pluginFuncs->newp = NPP_New;
95 pluginFuncs->destroy = NPP_Destroy;
96 pluginFuncs->event = NPP_HandleEvent;
97 pluginFuncs->setwindow = NPP_SetWindow;
98 pluginFuncs->print = NPP_Print;
99 pluginFuncs->newstream = NPP_NewStream;
100 pluginFuncs->destroystream = NPP_DestroyStream;
101 pluginFuncs->asfile = NPP_StreamAsFile;
102 pluginFuncs->writeready = NPP_WriteReady;
103 pluginFuncs->write = NPP_Write;
105 return NPERR_NO_ERROR;
108 NPError NP_Shutdown ()
110 Log ("shutdown");
112 return NPERR_NO_ERROR;
116 char *NP_GetMIMEDescription ()
118 Log ("get mime");
119 return "x-application/glugin:gln:Glugin;";
122 NPError NP_GetValue (void *instance, NPPVariable variable, void *value)
124 Log ("get value");
126 switch (variable) {
127 case NPPVpluginNameString:
128 (*(char **) value) = "Arena Live";
129 break;
130 case NPPVpluginDescriptionString:
131 (*(char **) value) = "Arena Live plugin";
132 break;
133 default:
134 return NPERR_INVALID_PARAM;
137 return NPERR_NO_ERROR;
140 NPError NPP_New (
141 NPMIMEType mime,
142 NPP instance,
143 uint16 mode,
144 int16 argc, char *argn[], char *argv[],
145 NPSavedData *saved)
147 int i;
148 pluginData *pd;
150 Log ("new p");
152 gNetscapeFuncs.setvalue (instance, NPPVpluginTransparentBool, false);
154 instance->pdata = gNetscapeFuncs.memalloc (sizeof (pluginData));
156 Log ("allocated");
158 pd = pdof (instance);
160 pd->exit_request = 0;
161 pd->exit_ack = 0;
162 pd->has_window = 0;
164 pd->conparam = 0;
165 pd->action = -1;
167 for (i = 0; i < argc; ++ i) {
168 if (!strcmp (argn[i], "conparam")) {
169 Log ("html tag parameter - conparam");
171 pd->conparam = strdup (argv[i]);
172 } else
173 if (!strcmp (argn[i], "action")) {
174 Log ("html tag parameter - action");
176 pd->action = atoi (argv[i]);
181 return NPERR_NO_ERROR;
184 void set_nonblock (int fd)
186 long flags = fcntl (fd, F_GETFL, 0);
188 flags |= (O_NONBLOCK | O_NDELAY);
190 fcntl (fd, F_SETFL, flags);
193 NPError NPP_SetWindow (NPP instance, NPWindow *w)
195 pluginData *pd = pdof (instance);
196 pid_t child;
197 int pw[2], pr[2];
199 if (!w) {
200 Log ("setwindow: destroyed");
201 return NPERR_NO_ERROR;
204 if (!pd->has_window) {
205 pd->has_window = 1;
207 pipe (pw);
208 pipe (pr);
210 set_nonblock (pr[0]);
211 set_nonblock (pr[1]);
212 set_nonblock (pw[0]);
213 set_nonblock (pw[1]);
215 child = fork ();
217 if (child == -1)
218 return NPERR_MODULE_LOAD_FAILED_ERROR;
220 if (!child) {
221 Log ("in new process!");
223 close (pw[1]);
224 close (pr[0]);
226 pd->pw = fdopen (pr[1], "w");
227 pd->pr = fdopen (pw[0], "r");
229 /* TODO check if setsid is needed here */
231 plugin_process_handler (pd, pd->win = (Window) (w->window), ((NPSetWindowCallbackStruct *) (w->ws_info))->visual);
233 _exit (0);
234 } else {
235 pd->child = child;
237 close (pw[0]);
238 close (pr[1]);
240 pd->pw = fdopen (pw[1], "w");
241 pd->pr = fdopen (pr[0], "r");
245 // we don't really care about window resize events, as long as
246 // it can catch them by native methods
248 return NPERR_NO_ERROR;
252 int16 NPP_HandleEvent (NPP instance, void *event)
254 Log ("event");
256 return true;
259 NPError NPP_Destroy (NPP instance, NPSavedData **saved)
261 pluginData *pd = pdof (instance);
263 Log ("killing child...");
265 kill (pd->child, SIGUSR1);
267 fclose (pd->pw);
268 fclose (pd->pr);
270 usleep (10000);
272 //TODO
273 //wait until the child really terminates. Mutexes?
275 gNetscapeFuncs.memfree (instance->pdata);
276 Log ("deleted ok");
278 return NPERR_NO_ERROR;
281 void NPP_Print (NPP instance, NPPrint *printInfo)
283 Log ("attempt to print");
286 NPError NPP_NewStream (NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16* stype)
288 Log ("new stream");
290 host_newstream (pdof (instance), stream);
292 return NPERR_NO_ERROR;
295 NPError NPP_DestroyStream (NPP instance, NPStream *stream, NPReason reason)
297 Log ("destroy stream");
299 host_destroystream (pdof (instance), stream);
301 return NPERR_NO_ERROR;
304 int32 NPP_Write (NPP instance, NPStream *stream, int32 offset, int32 len, void *buf)
306 Log ("write %d",len);
308 host_write (pdof (instance), stream, offset, len, buf);
310 return len;
313 void NPP_StreamAsFile (NPP instance, NPStream* stream, const char* fname)
315 Log ("as file:");
316 Log (fname);
319 int32 NPP_WriteReady (NPP instance, NPStream *stream)
321 Log("write ready");
323 return 1024; //ooh replace.
326 void resize (Display *dpy, Window win)
328 XWindowAttributes wa;
330 XGetWindowAttributes (dpy, win, &wa);
332 glViewport (0,0,wa.width, wa.height);
336 static pluginData *g_pd;
338 void sig_usr1 (int i)
340 g_pd->exit_request = 1;
343 void swapbuffers (pluginData *pd)
345 glXSwapBuffers (pd->dpy, pd->win);
348 void plugin_process_handler (pluginData *pd, Window win, Visual *vis)
350 g_pd = pd;
352 pd->win = win;
354 signal (SIGUSR1, sig_usr1);
356 /* call action function */
357 plugin_action (pd);
359 Log ("plugin killed, cleaning up.");
361 fclose (pd->pw);
362 fclose (pd->pr);
364 //glXMakeCurrent(dpy, None, 0);
365 //glXDestroyContext(dpy,ctx);
367 if (pd->conparam)
368 free (pd->conparam);
371 void writedata (FILE *f, void *x, unsigned len)
373 fwrite (x, len, sizeof (char), f);
376 void host_newstream (pluginData *pd, NPStream *s)
378 writedata (pd->pw, (void *) gln_new_stream, sizeof (int));
379 writedata (pd->pw, (void *) &s, sizeof (NPStream));
381 fflush (pd->pw);
384 void host_destroystream (pluginData*pd, NPStream*s)
386 writedata (pd->pw, (void *) gln_destroy_stream, sizeof (int));
387 writedata (pd->pw, (void *) s, sizeof (NPStream));
389 fflush (pd->pw);
392 void host_write (pluginData *pd, NPStream *s, int32 off, int32 siz, void *data)
394 writedata (pd->pw, (void *) gln_stream_data, sizeof (int));
395 writedata (pd->pw, (void *) s, sizeof (NPStream));
396 writedata (pd->pw, (void *) &off, sizeof (off));
397 writedata (pd->pw, (void *) &siz, sizeof (off));
399 fwrite (data, siz, sizeof (char), pd->pw);
401 fflush (pd->pw);
404 void host_read_guest_requests (pluginData *pd)
406 Log ("Reading guest requests");