📄 plugin.c
字号:
/****************************************************************************** * Copyright (c) 1996 Netscape Communications. All rights reserved. ******************************************************************************//* * Modifications for the Linux Flash Plugin * by Olivier Debon <odebon@club-internet.fr> */static char *rcsid = "$Id: plugin.c,v 1.3 2004/12/22 19:36:20 tgc Exp $";#include <stdio.h>#include <string.h>#include <sys/time.h>#include <sys/ipc.h>#include <sys/shm.h>#include "npapi.h"#include "flash.h"#include <X11/Xlib.h>#include <X11/keysym.h>#include <X11/cursorfont.h>#include <X11/Xutil.h>#include <X11/extensions/XShm.h>#include <X11/Intrinsic.h>#include <X11/IntrinsicP.h>#include <X11/Core.h>#include <X11/CoreP.h>#include <pthread.h>#define PRINT 0#define FLASH_XEVENT_MASK (ExposureMask|ButtonReleaseMask|ButtonPressMask|PointerMotionMask|KeyPressMask|KeyReleaseMask)typedef struct _load { char *url; int level; char *data; long size; struct _ load *next;} LoadCtxt;typedef struct _PluginInstance{ long gInitDone; Display *dpy; GC gc; Window win; Pixmap canvas; XShmSegmentInfo segInfo; // Shared memory information Widget widget; XtIntervalId timer; struct timeval wd; long attributes; FlashHandle fh; FlashDisplay fd; int cursorOver; Cursor buttonCursor; LoadCtxt *loading;} PluginInstance;static void updateTimer(PluginInstance* This);static void flashEvent(Widget w, XtPointer client_data, XEvent *event, Boolean *dispatch);static void flashWakeUp(XtPointer client_data, XtIntervalId *id);static void getUrl( char * url, char *target, void *client_data);static void getSwf(char *url, int level, void *client_data);static void cursorOnOff(int, void *client_data);static long parseAttributes(int16 n, char *argn[], char *argv[]);static long FlashExecX11(PluginInstance *, long , XEvent *, struct timeval *);static long FlashGraphicInitX11(PluginInstance* This);static void FlashCopyX11(PluginInstance* This);static pthread_mutex_t synchro;#ifdef C6R5// Ugly but it makes it work if it is compiled on// a libc6 system and running with a libc5-netscapeint __sigsetjmp(){ return 0;}#endifchar*NPP_GetMIMEDescription(void){ return("application/x-shockwave-flash:swf:Flash Plugin;application/x-futuresplash:spl:Future Splash");}NPErrorNPP_GetValue(void *future, NPPVariable variable, void *value){ NPError err = NPERR_NO_ERROR; switch (variable) { case NPPVpluginNameString: *((char **)value) = PLUGIN_NAME; break; case NPPVpluginDescriptionString: *((char **)value) = "Flash Movie player " FLASH_VERSION_STRING " compatible with Shockwave Flash 4.0 " "<P>Shockwave is a trademark of <A HREF=\"http://www.macromedia.com\">Macromedia®</A>" "<P>GPLFLash homepage : <A HREF=\"http://gplflash.sf.net\">gplflash.sf.net</A>"; break; default: err = NPERR_GENERIC_ERROR; } return err;}NPErrorNPP_Initialize(void){ freopen("/dev/tty","w",stdout); freopen("/dev/tty","w",stderr); return NPERR_NO_ERROR;}jrefNPP_GetJavaClass(){ return NULL;}voidNPP_Shutdown(void){}NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved){ PluginInstance* This; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; instance->pdata = NPN_MemAlloc(sizeof(PluginInstance)); This = (PluginInstance*) instance->pdata; if (This != NULL) { This->fh = FlashNew(); This->gInitDone = 0; This->dpy = 0; This->win = 0; This->timer = 0; This->attributes = parseAttributes(argc, argn, argv); This->loading = 0; FlashSetGetUrlMethod(This->fh, getUrl, (void*)instance); FlashSetGetSwfMethod(This->fh, getSwf, (void*)instance); FlashSetCursorOnOffMethod(This->fh, cursorOnOff, (void*)instance); FlashSoundInit(This->fh, "/dev/dsp"); return NPERR_NO_ERROR; } else return NPERR_OUT_OF_MEMORY_ERROR;}NPError NPP_Destroy(NPP instance, NPSavedData** save){ PluginInstance* This; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; This = (PluginInstance*) instance->pdata; if (This != NULL) { pthread_mutex_lock(&synchro); if (This->timer) { XtRemoveTimeOut(This->timer); This->timer = 0; } if (This->fh) { XShmDetach(This->dpy, &This->segInfo); XSync(This->dpy,False); XFreePixmap(This->dpy, This->canvas); shmdt(This->segInfo.shmaddr); FlashClose(This->fh); This->fh = 0; } NPN_MemFree(instance->pdata); instance->pdata = NULL; pthread_mutex_unlock(&synchro); } return NPERR_NO_ERROR;}static voidupdateTimer(PluginInstance* This){ XtAppContext ctxt; struct timeval now; long delay; if (This->timer) { XtRemoveTimeOut(This->timer); } gettimeofday(&now,0); delay = (This->wd.tv_sec-now.tv_sec)*1000 + (This->wd.tv_usec-now.tv_usec)/1000; //fprintf(stderr,"Wakeup in %d ms\n", delay); if (delay < 20) { // OVERRUN !!! delay = 20; // Leave 20 ms } ctxt = XtWidgetToApplicationContext(This->widget); This->timer = XtAppAddTimeOut(ctxt, delay, (XtTimerCallbackProc) flashWakeUp, (XtPointer) This);}static voidflashEvent(Widget w, XtPointer client_data, XEvent *event, Boolean *dispatch){ PluginInstance* This; long cmd; long wakeUp; This = (PluginInstance*)client_data; if (This->fh) { cmd = FLASH_EVENT; wakeUp = FlashExecX11(This, cmd, event, &This->wd); if (This->fd.flash_refresh) { FlashCopyX11(This); } if (wakeUp) { updateTimer(This); } }}static voidflashWakeUp(XtPointer client_data, XtIntervalId *id){ pthread_mutex_lock(&synchro); PluginInstance* This; long cmd; long wakeUp; This = (PluginInstance*)client_data; if (This->fh) { cmd = FLASH_WAKEUP; wakeUp = FlashExecX11(This, cmd, 0, &This->wd); if (This->fd.flash_refresh) { FlashCopyX11(This); } /* If have to wake up next time */ if (wakeUp) { updateTimer(This); } else { if (This->timer) { XtRemoveTimeOut(This->timer); } This->timer = 0; } } pthread_mutex_unlock(&synchro);}NPError NPP_SetWindow(NPP instance, NPWindow* window){ PluginInstance* This; NPSetWindowCallbackStruct *ws;/* Window frame;*/ XWindowAttributes xwa; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; if (window == NULL) return NPERR_NO_ERROR; This = (PluginInstance*) instance->pdata; This->win = (Window) window->window; ws = (NPSetWindowCallbackStruct *)window->ws_info; This->dpy = ws->display; This->gc = DefaultGC(This->dpy, DefaultScreen(This->dpy)); This->widget = XtWindowToWidget(This->dpy,This->win); XGetWindowAttributes(This->dpy, This->win, &xwa); return NPERR_NO_ERROR;}NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype){/* NPByteRange range;*/ PluginInstance* This; LoadCtxt *l; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; This = (PluginInstance*) instance->pdata; // This is only for the very first movie if (This->loading == 0) { l = (LoadCtxt *)malloc(sizeof(LoadCtxt)); This->loading = l; l->next = 0; l->level = 0; l->data = 0; l->size = 0; l->url = strdup(stream->url); } return NPERR_NO_ERROR;}#define BUFFERSIZE (16*1024)int32 NPP_WriteReady(NPP instance, NPStream *stream){/* PluginInstance* This;*/ if (instance != NULL) { return BUFFERSIZE; } return 0;}int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer){ PluginInstance* This; if (instance != NULL) { int status; LoadCtxt *l; This = (PluginInstance*) instance->pdata; for(l = This->loading; l != 0; l = l->next) { if (l->url && strstr(stream->url, l->url)) { break; } } if (l == 0) return 0; // Should not happen if (l->data == 0) { l->data = (char *) malloc(len); } else { l->data = (char *) realloc(l->data, l->size+len); } memcpy(&l->data[offset], buffer, len); l->size += len; status = FlashParse(This->fh, l->level, l->data, l->size); if (status == FLASH_PARSE_ERROR) { free(l->data); l->data = 0; free(l->url); l->url = 0; return 0; } if (status & FLASH_PARSE_START) { if (!This->gInitDone && This->dpy) { FlashGraphicInitX11(This); XtAddEventHandler(This->widget, FLASH_XEVENT_MASK, True, (XtEventHandler) flashEvent, (XtPointer)This); This->gInitDone = 1; } } if (status & FLASH_PARSE_WAKEUP) { flashWakeUp((XtPointer)This, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -