more mozilla mompatibility
[glugin.git] / ns-unix.cpp
blobd53347c6570e1aff8e2f2f1e3451ad7a0257d75c
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/types.h>
8 #include <signal.h>
10 #include <GL/glx.h>
12 #include "glugin.h"
14 #define pdof(x) ((pluginData*)(x->pdata))
16 static NPNetscapeFuncs gNetscapeFuncs; /* Netscape Function table */
18 NPError NP_Initialize(NPNetscapeFuncs * nsTable, NPPluginFuncs * pluginFuncs)
20 Log("init");
22 /* this is respectfully taken from mplayerplug-in, as it was observed
23 * and proved to be extremely useful. */
24 if ((nsTable == NULL) || (pluginFuncs == NULL))
25 return NPERR_INVALID_FUNCTABLE_ERROR;
26 if ((nsTable->version >> 8) > NP_VERSION_MAJOR)
27 return NPERR_INCOMPATIBLE_VERSION_ERROR;
28 if (nsTable->size < sizeof(NPNetscapeFuncs))
29 return NPERR_INVALID_FUNCTABLE_ERROR;
30 if (pluginFuncs->size < sizeof(NPPluginFuncs))
31 return NPERR_INVALID_FUNCTABLE_ERROR;
33 gNetscapeFuncs.version = nsTable->version;
34 gNetscapeFuncs.size = nsTable->size;
35 gNetscapeFuncs.posturl = nsTable->posturl;
36 gNetscapeFuncs.geturl = nsTable->geturl;
37 gNetscapeFuncs.requestread = nsTable->requestread;
38 gNetscapeFuncs.newstream = nsTable->newstream;
39 gNetscapeFuncs.write = nsTable->write;
40 gNetscapeFuncs.destroystream = nsTable->destroystream;
41 gNetscapeFuncs.status = nsTable->status;
42 gNetscapeFuncs.uagent = nsTable->uagent;
43 gNetscapeFuncs.memalloc = nsTable->memalloc;
44 gNetscapeFuncs.memfree = nsTable->memfree;
45 gNetscapeFuncs.memflush = nsTable->memflush;
46 gNetscapeFuncs.reloadplugins = nsTable->reloadplugins;
47 gNetscapeFuncs.getJavaEnv = nsTable->getJavaEnv;
48 gNetscapeFuncs.getJavaPeer = nsTable->getJavaPeer;
49 gNetscapeFuncs.getvalue = nsTable->getvalue;
50 gNetscapeFuncs.setvalue = nsTable->setvalue;
52 pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
53 pluginFuncs->size = sizeof(NPPluginFuncs);
54 pluginFuncs->newp = NPP_New;
55 pluginFuncs->destroy = NPP_Destroy;
56 pluginFuncs->event = NPP_HandleEvent;
57 pluginFuncs->setwindow = NPP_SetWindow;
58 pluginFuncs->print = NPP_Print;
59 pluginFuncs->newstream = NPP_NewStream;
60 pluginFuncs->destroystream = NPP_DestroyStream;
61 pluginFuncs->asfile = NPP_StreamAsFile;
62 pluginFuncs->writeready = NPP_WriteReady;
63 pluginFuncs->write = NPP_Write;
65 return NPERR_NO_ERROR;
68 NPError NP_Shutdown() {
69 Log("shutdown");
70 return NPERR_NO_ERROR;
74 char* NP_GetMIMEDescription() {
75 Log("get mime");
76 return "x-application/glugin:gln:Glugin;";
79 NPError NP_GetValue(
80 void*instance,
81 NPPVariable variable,
82 void* value)
84 Log("get value");
85 switch(variable) {
86 case NPPVpluginNameString:
87 (*(char**)value)="Glugin";
88 break;
89 case NPPVpluginDescriptionString:
90 (*(char**)value)="the GL plugin";
91 break;
92 default:
93 return NPERR_INVALID_PARAM;
95 return NPERR_NO_ERROR;
98 bool read_color(char* str, int*r, int*g, int*b)
100 int len=strlen(str);
101 if(!((len==3)||(len==6)))return false;
103 int color;
104 if(!sscanf(str,"%x",&color))return false;
106 if(len==6) {
107 *r=(color/65536)%256;
108 *g=(color/256)%256;
109 *b=color%256;
110 } else {
111 *r=255*((color/256)%16)/15;
112 *g=255*((color/16)%16)/15;
113 *b=255*(color%16)/15;
115 Log("Read color: %d %d %d\n",*r,*g,*b);
116 return true;
119 NPError NPP_New(
120 NPMIMEType mime,
121 NPP instance,
122 uint16 mode,
123 int16 argc, char*argn[], char*argv[],
124 NPSavedData* saved)
126 int i;
127 pluginData* pd;
129 Log("new p");
130 gNetscapeFuncs.setvalue(instance, NPPVpluginTransparentBool, false);
133 instance->pdata=gNetscapeFuncs.memalloc(sizeof(pluginData));
135 Log("allocated");
137 pd=pdof(instance);
138 pd->exit_request=pd->exit_ack=pd->has_window=
139 pd->r=pd->g=pd->b=0;
140 pd->br=pd->bg=pd->bb=255;
142 for(i=0;i<argc;++i){ Log(argn[i]);Log(argv[i]);Log("--");
143 if(!strcmp(argn[i],"gln-color")) {
144 Log("AAA");
145 read_color(argv[i],
146 &(pd->r),
147 &(pd->g),
148 &(pd->b));}
149 else if(!strcmp(argn[i],"gln-bgcolor")) {
150 Log("BBB");
151 read_color(argv[i],
152 &(pd->br),
153 &(pd->bg),
154 &(pd->bb));}
158 return NPERR_NO_ERROR;
161 void set_nonblock(int fd)
163 long flags;
165 flags=fcntl(fd, F_GETFL, 0);
166 flags|=O_NONBLOCK|O_NDELAY;
167 fcntl(fd, F_SETFL, flags);
170 void plugin_process_handler(pluginData*, Window, Visual*);
172 NPError NPP_SetWindow(
173 NPP instance,
174 NPWindow *w)
176 pluginData*pd=pdof(instance);
177 pid_t child;
178 int pw[2],pr[2];
180 if(!w) {
181 Log("setwindow: destroyed");
182 return NPERR_NO_ERROR;
185 if(!pd->has_window){
186 pd->has_window=1;
188 pipe(pw);
189 pipe(pr);
191 set_nonblock(pr[0]);
192 set_nonblock(pr[1]);
193 set_nonblock(pw[0]);
194 set_nonblock(pw[1]);
196 child=fork();
198 if(child==-1) return NPERR_MODULE_LOAD_FAILED_ERROR;
200 if(!child) {
201 Log("in new process!");
203 close(pw[1]);
204 close(pr[0]);
206 pd->pw=fdopen(pr[1],"w");
207 pd->pr=fdopen(pw[0],"r");
209 //TODO check if setsid is needed here
211 plugin_process_handler(pd, pd->win=(Window)(w->window),
212 ((NPSetWindowCallbackStruct*)
213 (w->ws_info))->visual);
214 _exit(0);
216 } else {
217 pd->child=child;
219 close(pw[0]);
220 close(pr[1]);
221 pd->pw=fdopen(pw[1],"w");
222 pd->pr=fdopen(pr[0],"r");
226 //we don't really care about window resize events, as long as
227 //it can catch them by native methods
229 return NPERR_NO_ERROR;
233 int16 NPP_HandleEvent(
234 NPP instance,
235 void* event)
237 Log("event");
239 return true;
242 NPError NPP_Destroy(
243 NPP instance,
244 NPSavedData** saved)
246 pluginData* pd;
247 pd=pdof(instance);
249 Log("killing child...");
251 kill(pd->child,SIGUSR1);
252 fclose(pd->pw);
253 fclose(pd->pr);
254 usleep(10000);
256 //TODO
257 //wait until the child really terminates. Mutexes?
259 gNetscapeFuncs.memfree(instance->pdata);
260 Log("deleted ok");
262 return NPERR_NO_ERROR;
265 void NPP_Print(NPP instance, NPPrint *printInfo)
267 Log("attempt to print");
270 NPError NPP_NewStream(
271 NPP instance,
272 NPMIMEType type,
273 NPStream* stream,
274 NPBool seekable,
275 uint16* stype)
277 Log("new stream");
278 host_newstream(pdof(instance),stream);
279 return NPERR_NO_ERROR;
282 NPError NPP_DestroyStream(
283 NPP instance,
284 NPStream* stream,
285 NPReason reason)
287 Log("destroy stream");
288 host_destroystream(pdof(instance),stream);
289 return NPERR_NO_ERROR;
292 int32 NPP_Write(NPP instance,
293 NPStream* stream,
294 int32 offset,
295 int32 len,
296 void* buf)
298 Log("write %d",len);
299 host_write(pdof(instance),stream,offset,len,buf);
300 return len;
303 void NPP_StreamAsFile(
304 NPP instance,
305 NPStream* stream,
306 const char* fname)
308 Log("as file:");
309 Log(fname);
312 int32 NPP_WriteReady(NPP instance, NPStream* stream)
314 Log("write ready");
315 return 1024; //ooh replace.
318 void resize(Display* dpy, Window win)
320 XWindowAttributes wa;
321 XGetWindowAttributes (dpy, win, &wa);
322 glViewport(0,0,wa.width, wa.height);
326 static pluginData*g_pd;
328 void sig_usr1(int i) {
329 g_pd->exit_request=1;
332 void swapbuffers(pluginData*pd)
334 glXSwapBuffers(pd->dpy,pd->win);
337 void plugin_process_handler(pluginData*pd, Window win, Visual*vis)
339 int i;
340 Display*dpy=XOpenDisplay(0);
341 XVisualInfo xvi;
342 GLXContext ctx;
344 g_pd=pd;
346 signal(SIGUSR1, sig_usr1);
348 Log("in plugin process...");
349 xvi.visualid=vis->visualid;
350 ctx=glXCreateContext(dpy,
351 XGetVisualInfo(dpy,VisualIDMask,&(xvi),&i),
352 0,GL_TRUE);
353 glXMakeCurrent(dpy,win,ctx);
355 if(glXIsDirect(dpy,ctx))
356 Log("+++ Direct rendering");
357 else Log("!!! Indirect rendering");
359 pd->swapbuffers=swapbuffers;
360 pd->dpy=dpy;
361 pd->win=win;
363 glugin_proc(pd);
365 Log("plugin killed, cleaning up.");
367 fclose(pd->pw);
368 fclose(pd->pr);
370 glXMakeCurrent(dpy, None, 0);
371 glXDestroyContext(dpy,ctx);
374 template <class T> void writedata(FILE*f, T x)
376 fwrite(&x,sizeof(T),1,f);
379 void host_newstream(pluginData* pd, NPStream* s){
380 writedata(pd->pw,(int)gln_new_stream);
381 writedata(pd->pw,s);
382 fflush(pd->pw);
385 void host_destroystream(pluginData*pd, NPStream*s){
386 writedata(pd->pw,(int)gln_destroy_stream);
387 writedata(pd->pw,s);
388 fflush(pd->pw);
391 void host_write(pluginData*pd,NPStream*s,int32 off, int32 siz, void*data){
392 writedata(pd->pw,(int)gln_stream_data);
393 writedata(pd->pw,s);
394 writedata(pd->pw,off);
395 writedata(pd->pw,siz);
396 fwrite(data,siz,1,pd->pw);
397 fflush(pd->pw);
400 void host_read_guest_requests(pluginData*){
402 Log("Reading guest requests");