/* * npfile.c * * Netscape Client Plugin API * - Function that need to be implemented by plugin developers * * This file defines a "shell" plugin that plugin developers can use * as the basis for a real plugin. This shell just provides empty * implementations of all functions that the plugin can implement * that will be called by Netscape (the NPP_xxx methods defined in * npapi.h). * * Example usage of this plugin is: * * Other attributes specific to the TEXT_PLUGIN are * MODE=AsFile * MODE=AsFileOnly * This will work in StreamAsFile mode and print the name of the file. * MODE=Seek * This will work in seek mode on seekable streames and display * 20 bytes from the 10th byte. * NODATA * This will make the plugin take no data. WriteReady will always return * 0. * The above modes are provided for test purposes. * * dp Suresh * *---------------------------------------------------------------------- * PLUGIN DEVELOPERS: * Implement your plugins here. * A sample text plugin is implemented here. * All the sample plugin does is displays any file with a * ".txt" extension in a scrolled text window. It uses Motif. *---------------------------------------------------------------------- */ #include #include #include #include "npapi.h" #include #include #include #ifdef CONSOLE FILE* Console ; #endif FILE* TempFile ; char filename[64]; /*********************************************************************** * Instance state information about the plugin. * * PLUGIN DEVELOPERS: * Use this struct to hold per-instance information that you'll * need in the various functions in this file. ***********************************************************************/ typedef struct _PluginInstance { uint16 mode; Window window; Display *display; uint32 x, y; uint32 width, height; uint16 opmode; /* Reflects the MODE attribute in the embed */ NPBool nodata; /* Does not accept data */ } PluginInstance; /*********************************************************************** * * Empty implementations of plugin API functions * * PLUGIN DEVELOPERS: * You will need to implement these functions as required by your * plugin. * ***********************************************************************/ char* NPP_GetMIMEDescription(void) { return("audio/x-pn-realaudio-plugin:.ram:RealAudio"); } NPError NPP_GetValue(void *future, NPPVariable variable, void *value) { NPError err = NPERR_NO_ERROR; switch (variable) { case NPPVpluginNameString: *((char **)value) = "Realaudio plugin"; break; case NPPVpluginDescriptionString: *((char **)value) = "This plugins plays realaudio clips using a temporary file. " ; break; default: err = NPERR_GENERIC_ERROR; } return err; } NPError NPP_Initialize(void) { #ifdef CONSOLE Console = fopen ("/dev/console","w") ; if (Console == NULL) { fprintf (stderr,"Could not open console for output\n") ; exit (1); } fprintf (Console,"Plugin: Initialize\n") ; #endif /* CONSOLE */ return NPERR_NO_ERROR; } jref NPP_GetJavaClass() { return NULL; } void NPP_Shutdown(void) { #ifdef CONSOLE fprintf (Console,"Plugin: Shutdown\n") ; fclose(Console) ; #endif } NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) { int16 argc_ ; PluginInstance* This; argc_ = argc ; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; instance->pdata = NPN_MemAlloc(sizeof(PluginInstance)); This = (PluginInstance*) instance->pdata; if (This != NULL) { #ifdef P_TRACE if (mode == NP_EMBED) fprintf(stderr, "Mode EMBED\n") ; if (mode == NP_FULL) fprintf(stderr, "Mode FULL\n") ; while (argc_ > 0) { fprintf(stderr, "Args: %s\n",argv[argc-1]) ; } #endif /* mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h) */ This->mode = mode; This->window = (Window) 0; This->opmode = NP_NORMAL; This->nodata = FALSE; while (argc > 0) { if (!strcasecmp(argn[argc-1], "MODE") && argv[argc-1]) { #ifdef CONSOLE fprintf (Console,"Plugin: mode: %s\n",argv[argc-1]) ; #endif if (!strcasecmp(argv[argc-1], "seek")) This->opmode = NP_SEEK; if (!strcasecmp(argv[argc-1], "asfile")) This->opmode = NP_ASFILE; if (!strcasecmp(argv[argc-1], "asfileonly")) This->opmode = NP_ASFILEONLY; } else if (!strcasecmp(argn[argc-1], "NODATA")) This->nodata = TRUE; argc --; } /* PLUGIN DEVELOPERS: * Initialize fields of your plugin * instance data here. If the NPSavedData is non- * NULL, you can use that data (returned by you from * NPP_Destroy to set up the new plugin instance). */ 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; /* PLUGIN DEVELOPERS: * If desired, call NP_MemAlloc to create a * NPSavedDate structure containing any state information * that you want restored if this plugin instance is later * recreated. */ if (This != NULL) { NPN_MemFree(instance->pdata); instance->pdata = NULL; } return NPERR_NO_ERROR; } NPError NPP_SetWindow(NPP instance, NPWindow* window) { PluginInstance* This; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; if (window == NULL) return NPERR_NO_ERROR; This = (PluginInstance*) instance->pdata; This->x = window->x; This->y = window->y; This->width = window->width; This->height = window->height; /* * PLUGIN DEVELOPERS: * Before setting window to point to the * new window, you may wish to compare the new window * info to the previous window (if any) to note window * size changes, etc. */ if (This->window == (Window) window->window) { /* This is a plugin changing size */ } else { This->window = (Window) window->window; This->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display; } return NPERR_NO_ERROR; } NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) { NPByteRange range; PluginInstance* This; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; This = (PluginInstance*) instance->pdata; if (seekable && This->opmode == NP_SEEK) { *stype = NP_SEEK; range.offset = 10; range.length = 20; range.next = NULL; NPN_RequestRead(stream, &range); } else if (This->opmode == NP_ASFILE || This->opmode == NP_ASFILEONLY) *stype = This->opmode; sprintf (filename, "/tmp/NPplugin.%d", getpid ()); TempFile = open(filename,O_WRONLY|O_CREAT,0644) ; if (TempFile == NULL) { fprintf (stderr,"Could not open %s for output\n",filename) ; exit (1); } return NPERR_NO_ERROR; } /* PLUGIN DEVELOPERS: * These next 2 functions are directly relevant in a plug-in which * handles the data in a streaming manner. If you want zero bytes * because no buffer space is YET available, return 0. As long as * the stream has not been written to the plugin, Navigator will * continue trying to send bytes. If the plugin doesn't want them, * just return some large number from NPP_WriteReady(), and * ignore them in NPP_Write(). For a NP_ASFILE stream, they are * still called but can safely be ignored using this strategy. */ int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile * mode so we can take any size stream in our * write call (since we ignore it) */ int32 NPP_WriteReady(NPP instance, NPStream *stream) { PluginInstance* This; if (instance != NULL) This = (PluginInstance*) instance->pdata; /* Number of bytes ready to accept in NPP_Write() */ if (This->nodata) return 0; else return STREAMBUFSIZE; } int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) { if (instance != NULL) { PluginInstance* This = (PluginInstance*) instance->pdata; char *cbuf; /* If this was a NODATA plugin, then we should not be getting * this write call. */ if (This->nodata) fprintf(stderr, "TextPlugin ERROR: Although NODATA attribute was used (NPP_WriteReady returned 0),\nwe got a NPP_Write call. Tell Netscape about this.\n"); #ifdef CONSOLE fprintf(Console, "Plugin: write %d bytes\n",len) ; #endif len = write(TempFile, buffer, len) ; #ifdef CONSOLE fprintf(Console, "Plugin: wrote %d bytes, error %d\n",len,errno) ; #endif if (len < 0) len = 0 ; } return len; /* The number of bytes accepted */ } NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) { char command[64] ; PluginInstance* This; if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; This = (PluginInstance*) instance->pdata; sprintf (command, "raplayer %s\n", filename); system(command) ; unlink(filename) ; close(TempFile) ; return NPERR_NO_ERROR; } void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname) { PluginInstance* This; if (instance != NULL) This = (PluginInstance*) instance->pdata; fprintf(stderr, "Got NPP_StreamAsFile: %s.\n", (fname == NULL)?"null":fname); } void NPP_Print(NPP instance, NPPrint* printInfo) { if(printInfo == NULL) return; if (instance != NULL) { PluginInstance* This = (PluginInstance*) instance->pdata; if (printInfo->mode == NP_FULL) { /* * PLUGIN DEVELOPERS: * If your plugin would like to take over * printing completely when it is in full-screen mode, * set printInfo->pluginPrinted to TRUE and print your * plugin as you see fit. If your plugin wants Netscape * to handle printing in this case, set * printInfo->pluginPrinted to FALSE (the default) and * do nothing. If you do want to handle printing * yourself, printOne is true if the print button * (as opposed to the print menu) was clicked. * On the Macintosh, platformPrint is a THPrint; on * Windows, platformPrint is a structure * (defined in npapi.h) containing the printer name, port, * etc. */ void* platformPrint = printInfo->print.fullPrint.platformPrint; NPBool printOne = printInfo->print.fullPrint.printOne; /* Do the default*/ printInfo->print.fullPrint.pluginPrinted = FALSE; } else { /* If not fullscreen, we must be embedded */ /* * PLUGIN DEVELOPERS: * If your plugin is embedded, or is full-screen * but you returned false in pluginPrinted above, NPP_Print * will be called with mode == NP_EMBED. The NPWindow * in the printInfo gives the location and dimensions of * the embedded plugin on the printed page. On the * Macintosh, platformPrint is the printer port; on * Windows, platformPrint is the handle to the printing * device context. */ NPWindow* printWindow = &(printInfo->print.embedPrint.window); void* platformPrint = printInfo->print.embedPrint.platformPrint; } } }