summaryrefslogtreecommitdiffstats
path: root/src/plugin.c
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-11 08:58:33 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-11 08:58:33 +0000
commit0006f17705952577867a9b7ddc9078372b44c442 (patch)
tree17831b026b53497764350ec5f9e484de7d2f3cdc /src/plugin.c
downloadkaffeine-mozilla-0006f17705952577867a9b7ddc9078372b44c442.tar.gz
kaffeine-mozilla-0006f17705952577867a9b7ddc9078372b44c442.zip
Added Kaffeine plugin for Mozilla
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kaffeine-mozilla@1101894 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/plugin.c')
-rw-r--r--src/plugin.c582
1 files changed, 582 insertions, 0 deletions
diff --git a/src/plugin.c b/src/plugin.c
new file mode 100644
index 0000000..abab8ab
--- /dev/null
+++ b/src/plugin.c
@@ -0,0 +1,582 @@
+/***************************************************************************
+ plugin.c
+ A modified gxine mozilla plugin,
+ to start kaffeine instead of gxine :-)
+ -------------------
+ begin : Wen Oct 30 2003
+ revision : $Revision: 1.1.1.1 $
+ last modified : $Date: 2004/05/12 08:12:52 $
+ copyright : (C) 2003-2004 by J. Kofler
+ email : kaffeine@gmx.net
+ ***************************************************************************/
+
+
+/*
+ * Copyright (C) 2000-2004 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Id: plugin.c,v 1.22 2003/04/08 22:07:47 guenter Exp
+ *
+ * xine plugin for mozilla
+ *
+ */
+
+
+
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <signal.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Text.h>
+#include <X11/Xaw/AsciiText.h>
+
+#include <stdio.h>
+#include <math.h>
+#include <unistd.h>
+
+
+#define XP_UNIX
+
+#include "npapi.h"
+#include "plugin.h"
+
+
+/* define LOG to write debug messages to /tmp/kaffeine_plugin.log */
+/*
+#define LOG
+*/
+
+
+#define STATUS_STR_SIZE 1024
+
+static char IsInitialised=0;
+
+/* global */
+typedef struct {
+
+ char *url;
+ int kaffeine_started;
+
+} plugin_global_t;
+
+static plugin_global_t globals;
+
+/* per-instance */
+typedef struct {
+
+ Display *display;
+ Screen *screen;
+ Window window;
+ Widget top_level;
+ int width,height;
+
+ int autostart;
+ int imageWindow;
+
+ char status_str[STATUS_STR_SIZE];
+
+ Pixel black, white;
+
+ int is_visible;
+} plugin_instance_t;
+
+
+static void xprintf (const char *format, ...) {
+
+#ifdef LOG
+ static FILE *log_fd=NULL;
+
+ va_list argp;
+
+ if (!log_fd) {
+
+ log_fd = fopen ("/tmp/kaffeine_plugin.log", "a+");
+
+ if (log_fd) {
+
+ setvbuf (log_fd, NULL, _IONBF, 0);
+
+ fprintf (log_fd, "\n---------------------------------------------\n\n");
+
+ }
+ }
+
+ va_start (argp, format);
+
+ if (log_fd) vfprintf (log_fd, format, argp);
+
+ va_end (argp);
+#endif
+}
+
+char *NPP_GetMIMEDescription(void) {
+
+ xprintf("NPP_GetMIMEDescription:\n");
+
+ return "video/mpeg: mpeg, mpg, mpe: MPEG animation;"
+ "video/x-mpeg: mpeg, mpg, mpe: MPEG animation;"
+ "audio/mpeg2: mp2: MPEG audio;"
+ "audio/x-mpeg2: mp2: MPEG audio;"
+ "audio/mpeg3: mp3: MPEG audio;"
+ "audio/x-mpeg3: mp3: MPEG audio;"
+ "audio/mpeg: mpa,abs,mpega: MPEG audio;"
+ "audio/x-mpeg: mpa,abs,mpega: MPEG audio;"
+ "video/quicktime: mov,qt: Quicktime animation;"
+ "video/x-quicktime: mov,qt: Quicktime animation;"
+ "video/msvideo: avi: AVI animation;"
+ "video/x-msvideo: avi: AVI animation;"
+ "application/x-mplayer2: asf,asx,asp: mplayer2;"
+ "video/x-ms-asf-plugin: asf,asx,asp: mms animation;"
+ "audio/x-pn-realaudio-plugin: rpm: Real audio;"
+ "audio/x-ogg: ogg,ogm: OGG Media;"
+ "audio/x-scpls: pls: MPEG audio;"
+ "audio/x-ms-wma: wma: Microsoft Media Audio;"
+ "video/x-ms-wmv: wmv: Microsoft Media Video;"
+ "audio/x-mpegurl: m3u: Streaming-MPEG-Audio;"
+ ;
+}
+
+NPError NPP_GetValue(void *future, NPPVariable variable, void *value){
+
+ NPError err = NPERR_NO_ERROR;
+ xprintf("NPP_GetValue: variable=%d\n", variable);
+
+ switch (variable) {
+ case NPPVpluginNameString:
+ *((char **)value) = "Kaffeine Starter Plugin";
+ break;
+ case NPPVpluginDescriptionString:
+ *((char **)value) =
+ "Will start external Kaffeine Media Player for embedded media streams.";
+ break;
+ default:
+ err = NPERR_GENERIC_ERROR;
+ }
+ return err;
+}
+
+NPError NPP_Initialize(void) {
+
+ xprintf("NPP_Initialize:\n");
+ if(!IsInitialised){
+
+ IsInitialised=1;
+
+ globals.url = NULL;
+ globals.kaffeine_started = 0;
+
+ }
+ return NPERR_NO_ERROR;
+}
+
+
+void * NPP_GetJavaClass() {
+ xprintf("NPP_GetJavaClass:\n");
+ return NULL;
+}
+
+void NPP_Shutdown(void) {
+ xprintf("NPP_Shutdown:\n");
+}
+
+static void print_status (plugin_instance_t *this, const char *format, ...) {
+
+ va_list argp;
+
+ va_start (argp, format);
+
+ vsnprintf (this->status_str, STATUS_STR_SIZE, format, argp);
+
+ va_end (argp);
+
+#if 0
+ paint_it (this);
+#endif
+}
+
+/* fork2() -- like fork, but the new process is immediately orphaned
+ * (won't leave a zombie when it exits)
+ * Returns 1 to the parent, not any meaningful pid.
+ * The parent cannot wait() for the new process (it's unrelated).
+ */
+
+/* This version assumes that you *haven't* caught or ignored SIGCHLD. */
+/* If you have, then you should just be using fork() instead anyway. */
+
+static int fork2() {
+ pid_t pid;
+ int status;
+
+ sigset_t set,oset;
+ sigfillset(& set);
+ xprintf (">>>>>>>>Forking<<<<<<<<,\n");
+ sigprocmask(SIG_SETMASK,&set,&oset);
+
+ if (!(pid = fork())) {
+ xprintf ("child\n");
+ switch (fork()) {
+ case 0:
+ xprintf ("child 2\n");
+ sigprocmask(SIG_SETMASK,&oset,&set);
+ return 0;
+ case -1:
+ xprintf ("fork 2 failed!\n");
+ _exit(errno); /* assumes all errnos are <256 */
+ default:
+ xprintf ("parent 2\n");
+ _exit(0);
+ }
+ }
+
+ xprintf ("parent, child pid =%d\n", pid);
+
+ if (pid < 0 || waitpid(pid,&status,0) < 0) {
+ xprintf ("waitpid failed! (pid==%d)\n", pid);
+ sigprocmask(SIG_SETMASK,&oset,&set);
+ return -1;
+ }
+ sigprocmask(SIG_SETMASK,&oset,&set);
+
+ xprintf ("waitpid done\n");
+
+ if (WIFEXITED(status))
+ if (WEXITSTATUS(status) == 0) {
+ xprintf ("fork 2 succeeded\n");
+ return 1;
+ } else
+ errno = WEXITSTATUS(status);
+ else
+ errno = EINTR; /* well, sort of :-) */
+
+ xprintf ("parent done\n");
+
+ return -1;
+}
+
+static void launch_kaffeine(plugin_instance_t *this) {
+
+ if (!globals.url) {
+ xprintf ("launch_kaffeine: no url!\n");
+ return;
+ }
+
+ if (!fork2()) {
+
+ xprintf ("launch_kaffeine: url = %s\n", globals.url);
+
+ execlp("kaffeine","" , globals.url, NULL);
+
+ if (execlp("kaffeine", NULL) == -1) {
+ perror("Error while launching Kaffeine");
+ _exit(0);
+ }
+ }
+
+ xprintf ("Kaffeine launched.\n");
+
+ globals.kaffeine_started = 1;
+}
+
+static void got_url (const char *url_) {
+
+ if (strstr (url_, ":/"))
+ globals.url = strdup (url_);
+ else
+ xprintf ("got_url: ignoring this url (%s) because it is a relative one.\n",
+ url_);
+
+}
+
+NPError NPP_New(NPMIMEType pluginType, NPP instance,
+ uint16 mode,
+ int16 argc, char* argn[], char* argv[],
+ NPSavedData* saved) {
+
+ plugin_instance_t* this;
+ xprintf("NPP_New:\n");
+
+ if (instance == NULL)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ instance->pdata = NPN_MemAlloc(sizeof(plugin_instance_t));
+
+ this = (plugin_instance_t*) instance->pdata;
+
+ globals.url = NULL;
+ this->autostart = 0;
+ this->imageWindow = 1;
+
+ if (this != NULL) {
+
+ int i;
+
+ /* parse args */
+
+ for (i=0; i<argc; i++) {
+
+ xprintf ("plugin: argument '%s'='%s'\n",
+ argn[i], argv[i]);
+
+ if (!strcasecmp (argn[i], "href")) {
+ got_url (argv[i]);
+ xprintf ("got href url %s\n", globals.url);
+ } else if (!strcasecmp (argn[i], "src") && !globals.url) {
+ got_url (argv[i]);
+ xprintf ("got src url %s\n", globals.url);
+ } else if (!strcasecmp (argn[i], "autostart")) {
+ this->autostart = !strcasecmp (argv[i], "true");
+ xprintf ("got autostart %d\n", this->autostart);
+ } else if (!strcasecmp (argn[i], "controls")) {
+ this->imageWindow = !strcasecmp (argv[i], "imagewindow");
+ if (!this->imageWindow)
+ xprintf("This is no ImageWindow!\n");
+ }
+
+ }
+
+ if ( globals.url && !globals.kaffeine_started && this->imageWindow )
+ launch_kaffeine(this);
+
+ xprintf ("plugin: NPP_New done\n");
+
+ return NPERR_NO_ERROR;
+ } else {
+ xprintf ("plugin: out of memory :(\n");
+
+ return NPERR_OUT_OF_MEMORY_ERROR;
+ }
+}
+
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window) {
+
+ plugin_instance_t* this;
+ Widget hello, box;
+
+ xprintf("NPP_SetWindow: 42\n");
+
+ if (instance == NULL) {
+ xprintf("NPERR_INVALID_INSTANCE_ERROR\n");
+ return NPERR_INVALID_INSTANCE_ERROR;
+ }
+
+ if (window == NULL) {
+ xprintf("window == NULL, NPERR_NO_ERROR\n");
+ return NPERR_NO_ERROR;
+ }
+
+ this = (plugin_instance_t*) instance->pdata;
+
+ this->display = ((NPSetWindowCallbackStruct *) window->ws_info)->display;
+ this->window = (Window) window->window;
+ this->width = window->width;
+ this->height = window->height;
+ this->top_level = XtWindowToWidget (this->display, this->window);
+ this->screen = XtScreen (this->top_level);
+
+ xprintf("x=%lu, y=%lu, w=%lu, h=%lu\n", window->x, window->y, window->width, window->height);
+ xprintf("window = %lu NPERR_NO_ERROR\n", this->window);
+
+ this->black = BlackPixelOfScreen (this->screen);
+ this->white = WhitePixelOfScreen (this->screen);
+
+ XResizeWindow(this->display,
+ this->window, this->width, this->height);
+ /* XSetWindowBackground (this, this->window, this->black); */
+ XSync (this->display, FALSE);
+
+
+
+ box = XtVaCreateManagedWidget ("form", formWidgetClass, this->top_level,
+ XtNbackground, this->black,
+ XtNwidth, this->width,
+ XtNheight, this->height, NULL);
+
+ if (this->imageWindow) {
+ hello = XtVaCreateManagedWidget ("Kaffeine Starter Plugin", labelWidgetClass, box,
+ XtNbackground, this->black,
+ XtNforeground, this->white,
+ XtNwidth, this->width,
+ XtNheight, this->height, NULL); }
+
+
+ XtRealizeWidget (box);
+
+
+ xprintf("NPP_SetWindow: done.\n");
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** save) {
+
+ plugin_instance_t* this;
+ xprintf("NPP_Destroy:\n");
+
+ if (instance == NULL)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ this = (plugin_instance_t*) instance->pdata;
+
+ if (this != NULL) {
+
+ NPN_MemFree(instance->pdata);
+ instance->pdata = NULL;
+
+ }
+
+ globals.kaffeine_started = FALSE;
+
+ xprintf("NPP_Destroy: closed.\n");
+
+ return NPERR_NO_ERROR;
+}
+
+
+NPError NPP_NewStream (NPP instance,
+ NPMIMEType type,
+ NPStream *stream,
+ NPBool seekable,
+ uint16 *stype) {
+
+ /* NPByteRange range; */
+ plugin_instance_t *this;
+
+ xprintf("NPP_NewStream:\n");
+
+ if (instance == NULL)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ this = (plugin_instance_t*) instance->pdata;
+
+ xprintf("NPP_NewStream: url is %s \n", stream->url);
+
+
+ got_url (stream->url);
+
+ if (!globals.kaffeine_started) {
+
+ /*
+ * now start kaffeine as an orphaned child
+ */
+
+ launch_kaffeine(this);
+ xprintf ("NPP_NewStream: Kaffeine started successfully\n");
+
+ }
+
+ xprintf ("NPP_NewStream: done\n");
+
+ 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) {
+
+ plugin_instance_t* this;
+ xprintf("NPP_WriteReady:\n");
+ if (instance != NULL)
+ this = (plugin_instance_t*) instance->pdata;
+
+ return STREAMBUFSIZE;
+}
+
+
+int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) {
+
+ xprintf("NPP_Write:\n");
+ /*
+ if (instance != NULL) {
+ plugin_instance_t* this = (plugin_instance_t*) instance->pdata;
+ }
+ */
+
+ return -1; /* close stream */
+}
+
+
+NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
+
+ plugin_instance_t* this;
+
+ xprintf("NPP_DestroyStream: \n");
+ if (instance == NULL)
+ return NPERR_INVALID_INSTANCE_ERROR;
+ this = (plugin_instance_t*) instance->pdata;
+
+ return NPERR_NO_ERROR;
+}
+
+
+void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname) {
+
+ plugin_instance_t* this;
+
+ xprintf("NPP_StreamAsFile:\n");
+ if (instance != NULL)
+ this = (plugin_instance_t*) instance->pdata;
+}
+
+
+void NPP_Print(NPP instance, NPPrint* printInfo) {
+
+ xprintf("NPP_Print:\n");
+ if(printInfo == NULL)
+ return;
+
+ xprintf("NPP_Print: Not implemented. \n");
+}
+
+int16 NPP_HandleEvent(NPP instance, void* ev) {
+
+ xprintf("NPP_HandleEvent\n");
+
+ return 1;
+}