summaryrefslogtreecommitdiffstats
path: root/src/npplayer.c
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-17 00:54:13 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-17 00:54:13 +0000
commit092be7678b67552cb3161fe162242bf8d3aeed2f (patch)
treebe0693f45b101252c370e40f6e84da2cd7a52f75 /src/npplayer.c
downloadkmplayer-092be7678b67552cb3161fe162242bf8d3aeed2f.tar.gz
kmplayer-092be7678b67552cb3161fe162242bf8d3aeed2f.zip
Added old abandoned KDE3 version of kmplayer
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kmplayer@1091557 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/npplayer.c')
-rw-r--r--src/npplayer.c1545
1 files changed, 1545 insertions, 0 deletions
diff --git a/src/npplayer.c b/src/npplayer.c
new file mode 100644
index 0000000..e7f67bb
--- /dev/null
+++ b/src/npplayer.c
@@ -0,0 +1,1545 @@
+/*
+* Copyright (C) 2007 Koos Vriezen <koos.vriezen@gmail.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/* gcc -o knpplayer `pkg-config --libs --cflags gtk+-x11-2.0` `pkg-config --libs --cflags dbus-glib-1` `pkg-config --libs gthread-2.0` npplayer.c
+
+http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
+http://dbus.freedesktop.org/doc/dbus/libdbus-tutorial.html
+*/
+
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include <glib/gprintf.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#define XP_UNIX
+#define MOZ_X11
+#include "moz-sdk/npupp.h"
+
+typedef const char* (* NP_LOADDS NP_GetMIMEDescriptionUPP)();
+typedef NPError (* NP_GetValueUPP)(void *inst, NPPVariable var, void *value);
+typedef NPError (* NP_InitializeUPP)(NPNetscapeFuncs*, NPPluginFuncs*);
+typedef NPError (* NP_ShutdownUPP)(void);
+
+static gchar *plugin;
+static gchar *object_url;
+static gchar *mimetype;
+
+static DBusConnection *dbus_connection;
+static char *service_name;
+static gchar *callback_service;
+static gchar *callback_path;
+static GModule *library;
+static GtkWidget *xembed;
+static Window socket_id;
+static Window parent_id;
+static int top_w, top_h;
+static int update_dimension_timer;
+static int stdin_read_watch;
+
+static NPPluginFuncs np_funcs; /* plugin functions */
+static NPP npp; /* single instance of the plugin */
+static NPWindow np_window;
+static NPObject *js_window;
+static NPObject *scriptable_peer;
+static NPSavedData *saved_data;
+static NPClass js_class;
+static GTree *stream_list;
+static gpointer current_stream_id;
+static uint32_t stream_chunk_size;
+static char stream_buf[32 * 1024];
+static unsigned int stream_buf_pos;
+static int stream_id_counter;
+static GTree *identifiers;
+static int js_obj_counter;
+typedef struct _StreamInfo {
+ NPStream np_stream;
+ /*unsigned int stream_buf_pos;*/
+ unsigned int stream_pos;
+ unsigned int total;
+ unsigned int reason;
+ char *url;
+ char *mimetype;
+ char *target;
+ bool notify;
+ bool called_plugin;
+ bool destroyed;
+} StreamInfo;
+struct JsObject;
+typedef struct _JsObject {
+ NPObject npobject;
+ struct _JsObject * parent;
+ char * name;
+} JsObject;
+
+static NP_GetMIMEDescriptionUPP npGetMIMEDescription;
+static NP_GetValueUPP npGetValue;
+static NP_InitializeUPP npInitialize;
+static NP_ShutdownUPP npShutdown;
+
+static void callFunction(int stream, const char *func, int first_arg_type, ...);
+static void readStdin (gpointer d, gint src, GdkInputCondition cond);
+static char * evaluate (const char *script);
+
+/*----------------%<---------------------------------------------------------*/
+
+static void print (const char * format, ...) {
+ va_list vl;
+ va_start (vl, format);
+ vprintf (format, vl);
+ va_end (vl);
+ fflush (stdout);
+}
+
+/*----------------%<---------------------------------------------------------*/
+
+static gint streamCompare (gconstpointer a, gconstpointer b) {
+ return (long)a - (long)b;
+}
+
+static void freeStream (StreamInfo *si) {
+ if (!g_tree_remove (stream_list, si->np_stream.ndata))
+ print ("WARNING freeStream not in tree\n");
+ g_free (si->url);
+ if (si->mimetype)
+ g_free (si->mimetype);
+ if (si->target)
+ g_free (si->target);
+ free (si);
+}
+
+static gboolean requestStream (void * p) {
+ StreamInfo *si = (StreamInfo *) g_tree_lookup (stream_list, p);
+ if (si) {
+ if (!callback_service)
+ current_stream_id = p;
+ if (!stdin_read_watch)
+ stdin_read_watch = gdk_input_add (0, GDK_INPUT_READ,readStdin,NULL);
+ if (si->target)
+ callFunction ((int)(long)p, "getUrl",
+ DBUS_TYPE_STRING, &si->url,
+ DBUS_TYPE_STRING, &si->target, DBUS_TYPE_INVALID);
+ else
+ callFunction ((int)(long)p, "getUrl",
+ DBUS_TYPE_STRING, &si->url, DBUS_TYPE_INVALID);
+ } else {
+ print ("requestStream %d not found", (long) p);
+ }
+ return 0; /* single shot */
+}
+
+static gboolean destroyStream (void * p) {
+ StreamInfo *si = (StreamInfo *) g_tree_lookup (stream_list, p);
+ print ("FIXME destroyStream\n");
+ if (si)
+ callFunction ((int)(long)p, "destroy", DBUS_TYPE_INVALID);
+ return 0; /* single shot */
+}
+
+static void removeStream (void * p) {
+ StreamInfo *si = (StreamInfo *) g_tree_lookup (stream_list, p);
+
+ if (si) {
+ print ("removeStream %d rec:%d reason %d\n", (long) p, si->stream_pos, si->reason);
+ if (!si->destroyed) {
+ if (si->called_plugin && !si->target) {
+ si->np_stream.end = si->total;
+ np_funcs.destroystream (npp, &si->np_stream, si->reason);
+ }
+ if (si->notify)
+ np_funcs.urlnotify (npp,
+ si->url, si->reason, si->np_stream.notifyData);
+ }
+ freeStream (si);
+ }
+}
+
+static int32_t writeStream (gpointer p, char *buf, uint32_t count) {
+ int32_t sz = -1;
+ StreamInfo *si = (StreamInfo *) g_tree_lookup (stream_list, p);
+ /*print ("writeStream found %d count %d\n", !!si, count);*/
+ if (si) {
+ if (si->reason > NPERR_NO_ERROR) {
+ sz = count; /* stream closed, skip remainings */
+ } else {
+ if (!si->called_plugin) {
+ uint16 stype = NP_NORMAL;
+ NPError err = np_funcs.newstream (npp, si->mimetype
+ ? si->mimetype
+ : "text/plain",
+ &si->np_stream, 0, &stype);
+ if (err != NPERR_NO_ERROR) {
+ g_printerr ("newstream error %d\n", err);
+ destroyStream (p);
+ return count; /* stream not accepted, skip remainings */
+ }
+ print ("newStream %d type:%d\n", (long) p, stype);
+ si->called_plugin = true;
+ }
+ if (count) /* urls with a target returns zero bytes */
+ sz = np_funcs.writeready (npp, &si->np_stream);
+ if (sz > 0) {
+ sz = np_funcs.write (npp, &si->np_stream, si->stream_pos,
+ (int32_t) count > sz ? sz : (int32_t) count, buf);
+ if (sz < 0) /*FIXME plugin destroys stream here*/
+ g_timeout_add (0, destroyStream, p);
+ } else {
+ sz = 0;
+ }
+ si->stream_pos += sz;
+ if (si->stream_pos == si->total) {
+ if (si->stream_pos || !count)
+ removeStream (p);
+ else
+ g_timeout_add (0, destroyStream, p);
+ }
+ }
+ }
+ return sz;
+}
+
+static StreamInfo *addStream (const char *url, const char *mime, const char *target, void *notify_data, bool notify) {
+ StreamInfo *si = (StreamInfo *) malloc (sizeof (StreamInfo));
+
+ memset (si, 0, sizeof (StreamInfo));
+ si->url = g_strdup (url);
+ si->np_stream.url = si->url;
+ if (mime)
+ si->mimetype = g_strdup (mime);
+ if (target)
+ si->target = g_strdup (target);
+ si->np_stream.notifyData = notify_data;
+ si->notify = notify;
+ si->np_stream.ndata = (void *) (long) (stream_id_counter++);
+ print ("add stream %d\n", (long) si->np_stream.ndata);
+ g_tree_insert (stream_list, si->np_stream.ndata, si);
+
+ g_timeout_add (0, requestStream, si->np_stream.ndata);
+
+ return si;
+}
+
+/*----------------%<---------------------------------------------------------*/
+
+static void createJsName (JsObject * obj, char **name, uint32_t * len) {
+ int slen = strlen (obj->name);
+ if (obj->parent) {
+ *len += slen + 1;
+ createJsName (obj->parent, name, len);
+ } else {
+ *name = (char *) malloc (*len + slen + 1);
+ *(*name + *len + slen) = 0;
+ *len = 0;
+ }
+ if (obj->parent) {
+ *(*name + *len) = '.';
+ *len += 1;
+ }
+ memcpy (*name + *len, obj->name, slen);
+ *len += slen;
+}
+
+static char *nsVariant2Str (const NPVariant *value) {
+ char *str;
+ switch (value->type) {
+ case NPVariantType_String:
+ str = (char *) malloc (value->value.stringValue.utf8length + 3);
+ sprintf (str, "'%s'", value->value.stringValue.utf8characters);
+ break;
+ case NPVariantType_Int32:
+ str = (char *) malloc (16);
+ snprintf (str, 15, "%d", value->value.intValue);
+ break;
+ case NPVariantType_Double:
+ str = (char *) malloc (64);
+ snprintf (str, 63, "%f", value->value.doubleValue);
+ break;
+ case NPVariantType_Bool:
+ str = strdup (value->value.boolValue ? "true" : "false");
+ break;
+ case NPVariantType_Null:
+ str = strdup ("null");
+ break;
+ case NPVariantType_Object:
+ if (&js_class == value->value.objectValue->_class) {
+ JsObject *jv = (JsObject *) value->value.objectValue;
+ char *val;
+ uint32_t vlen = 0;
+ createJsName (jv, &val, &vlen);
+ str = strdup (val);
+ free (val);
+ }
+ break;
+ default:
+ str = strdup ("");
+ break;
+ }
+ return str;
+}
+
+/*----------------%<---------------------------------------------------------*/
+
+static NPObject * nsCreateObject (NPP instance, NPClass *aClass) {
+ NPObject *obj;
+ if (aClass && aClass->allocate) {
+ obj = aClass->allocate (instance, aClass);
+ } else {
+ obj = (NPObject *) malloc (sizeof (NPObject));
+ memset (obj, 0, sizeof (NPObject));
+ obj->_class = aClass;
+ /*obj = js_class.allocate (instance, &js_class);/ *add null class*/
+ print ("NPN_CreateObject\n");
+ }
+ obj->referenceCount = 1;
+ return obj;
+}
+
+static NPObject *nsRetainObject (NPObject *npobj) {
+ /*print( "nsRetainObject %p\n", npobj);*/
+ npobj->referenceCount++;
+ return npobj;
+}
+
+static void nsReleaseObject (NPObject *obj) {
+ /*print ("NPN_ReleaseObject\n");*/
+ if (! (--obj->referenceCount))
+ obj->_class->deallocate (obj);
+}
+
+static NPError nsGetURL (NPP instance, const char* url, const char* target) {
+ (void)instance;
+ print ("nsGetURL %s %s\n", url, target ? target : "");
+ addStream (url, 0L, target, 0L, false);
+ return NPERR_NO_ERROR;
+}
+
+static NPError nsPostURL (NPP instance, const char *url,
+ const char *target, uint32 len, const char *buf, NPBool file) {
+ (void)instance; (void)len; (void)buf; (void)file;
+ print ("nsPostURL %s %s\n", url, target ? target : "");
+ addStream (url, 0L, target, 0L, false);
+ return NPERR_NO_ERROR;
+}
+
+static NPError nsRequestRead (NPStream *stream, NPByteRange *rangeList) {
+ (void)stream; (void)rangeList;
+ print ("nsRequestRead\n");
+ return NPERR_NO_ERROR;
+}
+
+static NPError nsNewStream (NPP instance, NPMIMEType type,
+ const char *target, NPStream **stream) {
+ (void)instance; (void)type; (void)stream; (void)target;
+ print ("nsNewStream\n");
+ return NPERR_NO_ERROR;
+}
+
+static int32 nsWrite (NPP instance, NPStream* stream, int32 len, void *buf) {
+ (void)instance; (void)len; (void)buf; (void)stream;
+ print ("nsWrite\n");
+ return 0;
+}
+
+static NPError nsDestroyStream (NPP instance, NPStream *stream, NPError reason) {
+ StreamInfo *si = (StreamInfo *) g_tree_lookup (stream_list, stream->ndata);
+ (void)instance;
+ print ("nsDestroyStream\n");
+ if (si) {
+ si->reason = reason;
+ si->destroyed = true;
+ g_timeout_add (0, destroyStream, stream->ndata);
+ return NPERR_NO_ERROR;
+ }
+ return NPERR_NO_DATA;
+}
+
+static void nsStatus (NPP instance, const char* message) {
+ (void)instance;
+ print ("NPN_Status %s\n", message ? message : "-");
+}
+
+static const char* nsUserAgent (NPP instance) {
+ (void)instance;
+ print ("NPN_UserAgent\n");
+ return "";
+}
+
+static void *nsAlloc (uint32 size) {
+ return malloc (size);
+}
+
+static void nsMemFree (void* ptr) {
+ free (ptr);
+}
+
+static uint32 nsMemFlush (uint32 size) {
+ (void)size;
+ print ("NPN_MemFlush\n");
+ return 0;
+}
+
+static void nsReloadPlugins (NPBool reloadPages) {
+ (void)reloadPages;
+ print ("NPN_ReloadPlugins\n");
+}
+
+static JRIEnv* nsGetJavaEnv () {
+ print ("NPN_GetJavaEnv\n");
+ return NULL;
+}
+
+static jref nsGetJavaPeer (NPP instance) {
+ (void)instance;
+ print ("NPN_GetJavaPeer\n");
+ return NULL;
+}
+
+static NPError nsGetURLNotify (NPP instance, const char* url, const char* target, void *notify) {
+ (void)instance;
+ print ("NPN_GetURLNotify %s %s\n", url, target ? target : "");
+ addStream (url, 0L, target, notify, true);
+ return NPERR_NO_ERROR;
+}
+
+static NPError nsPostURLNotify (NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void *notify) {
+ (void)instance; (void)len; (void)buf; (void)file;
+ print ("NPN_PostURLNotify\n");
+ addStream (url, 0L, target, notify, true);
+ return NPERR_NO_ERROR;
+}
+
+static NPError nsGetValue (NPP instance, NPNVariable variable, void *value) {
+ print ("NPN_GetValue %d\n", variable & ~NP_ABI_MASK);
+ switch (variable) {
+ case NPNVxDisplay:
+ *(void**)value = (void*)(long) gdk_x11_get_default_xdisplay ();
+ break;
+ case NPNVxtAppContext:
+ *(void**)value = NULL;
+ break;
+ case NPNVnetscapeWindow:
+ print ("NPNVnetscapeWindow\n");
+ break;
+ case NPNVjavascriptEnabledBool:
+ *(int*)value = 1;
+ break;
+ case NPNVasdEnabledBool:
+ *(int*)value = 0;
+ break;
+ case NPNVisOfflineBool:
+ *(int*)value = 0;
+ break;
+ case NPNVserviceManager:
+ *(int*)value = 0;
+ break;
+ case NPNVToolkit:
+ *(int*)value = NPNVGtk2;
+ break;
+ case NPNVSupportsXEmbedBool:
+ *(int*)value = 1;
+ break;
+ case NPNVWindowNPObject:
+ if (!js_window) {
+ JsObject *jo = (JsObject*) nsCreateObject (instance, &js_class);
+ jo->name = g_strdup ("window");
+ js_window = (NPObject *) jo;
+ }
+ *(NPObject**)value = nsRetainObject (js_window);
+ break;
+ case NPNVPluginElementNPObject: {
+ JsObject * obj = (JsObject *) nsCreateObject (instance, &js_class);
+ obj->name = g_strdup ("this");
+ *(NPObject**)value = (NPObject *) obj;
+ break;
+ }
+ default:
+ *(int*)value = 0;
+ print ("unknown value\n");
+ return NPERR_GENERIC_ERROR;
+ }
+ return NPERR_NO_ERROR;
+}
+
+static NPError nsSetValue (NPP instance, NPPVariable variable, void *value) {
+ /* NPPVpluginWindowBool */
+ (void)instance; (void)value;
+ print ("NPN_SetValue %d\n", variable & ~NP_ABI_MASK);
+ return NPERR_NO_ERROR;
+}
+
+static void nsInvalidateRect (NPP instance, NPRect *invalidRect) {
+ (void)instance; (void)invalidRect;
+ print ("NPN_InvalidateRect\n");
+}
+
+static void nsInvalidateRegion (NPP instance, NPRegion invalidRegion) {
+ (void)instance; (void)invalidRegion;
+ print ("NPN_InvalidateRegion\n");
+}
+
+static void nsForceRedraw (NPP instance) {
+ (void)instance;
+ print ("NPN_ForceRedraw\n");
+}
+
+static NPIdentifier nsGetStringIdentifier (const NPUTF8* name) {
+ /*print ("NPN_GetStringIdentifier %s\n", name);*/
+ gpointer id = g_tree_lookup (identifiers, name);
+ if (!id) {
+ id = strdup (name);
+ g_tree_insert (identifiers, id, id);
+ }
+ return id;
+}
+
+static void nsGetStringIdentifiers (const NPUTF8** names, int32_t nameCount,
+ NPIdentifier* ids) {
+ (void)names; (void)nameCount; (void)ids;
+ print ("NPN_GetStringIdentifiers\n");
+}
+
+static NPIdentifier nsGetIntIdentifier (int32_t intid) {
+ print ("NPN_GetIntIdentifier %d\n", intid);
+ return (NPIdentifier) (long) intid;
+}
+
+static bool nsIdentifierIsString (NPIdentifier name) {
+ print ("NPN_IdentifierIsString\n");
+ return !!g_tree_lookup (identifiers, name);
+}
+
+static NPUTF8 * nsUTF8FromIdentifier (NPIdentifier name) {
+ print ("NPN_UTF8FromIdentifier\n");
+ char *str = g_tree_lookup (identifiers, name);
+ if (str)
+ return strdup (str);
+ return NULL;
+}
+
+static int32_t nsIntFromIdentifier (NPIdentifier identifier) {
+ print ("NPN_IntFromIdentifier\n");
+ return (int32_t) (long) identifier;
+}
+
+static bool nsInvoke (NPP instance, NPObject * npobj, NPIdentifier method,
+ const NPVariant *args, uint32_t arg_count, NPVariant *result) {
+ (void)instance;
+ /*print ("NPN_Invoke %s\n", id);*/
+ return npobj->_class->invoke (npobj, method, args, arg_count, result);
+}
+
+static bool nsInvokeDefault (NPP instance, NPObject * npobj,
+ const NPVariant * args, uint32_t arg_count, NPVariant * result) {
+ (void)instance;
+ return npobj->_class->invokeDefault (npobj,args, arg_count, result);
+}
+
+static bool nsEvaluate (NPP instance, NPObject * npobj, NPString * script,
+ NPVariant * result) {
+ char * this_var;
+ char * this_var_type;
+ char * this_var_string;
+ char * jsscript;
+ (void) npobj; /*FIXME scope, search npobj window*/
+ print ("NPN_Evaluate:");
+
+ /* assign to a js variable */
+ this_var = (char *) malloc (64);
+ sprintf (this_var, "this.__kmplayer__obj_%d", js_obj_counter);
+
+ jsscript = (char *) malloc (strlen (this_var) + script->utf8length + 3);
+ sprintf (jsscript, "%s=%s;", this_var, script->utf8characters);
+ this_var_string = evaluate (jsscript);
+ free (jsscript);
+
+ if (this_var_string) {
+ /* get type of js this_var */
+ jsscript = (char *) malloc (strlen (this_var) + 9);
+ sprintf (jsscript, "typeof %s;", this_var);
+ this_var_type = evaluate (jsscript);
+ free (jsscript);
+
+ if (this_var_type) {
+ if (!strcasecmp (this_var_type, "undefined")) {
+ result->type = NPVariantType_Null;
+ } else if (!strcasecmp (this_var_type, "object")) {
+ JsObject *jo = (JsObject *)nsCreateObject (instance, &js_class);
+ js_obj_counter++;
+ result->type = NPVariantType_Object;
+ jo->name = g_strdup (this_var);
+ result->value.objectValue = (NPObject *)jo;
+ } else { /* FIXME numbers/void/undefined*/
+ result->type = NPVariantType_String;
+ result->value.stringValue.utf8characters =
+ g_strdup (this_var_string);
+ result->value.stringValue.utf8length=strlen (this_var_string)+1;
+ }
+ g_free (this_var_type);
+ }
+ g_free (this_var_string);
+ } else {
+ print (" => error\n");
+ return false;
+ }
+ free (this_var);
+
+ return true;
+}
+
+static bool nsGetProperty (NPP instance, NPObject * npobj,
+ NPIdentifier property, NPVariant * result) {
+ (void)instance;
+ return npobj->_class->getProperty (npobj, property, result);
+}
+
+static bool nsSetProperty (NPP instance, NPObject * npobj,
+ NPIdentifier property, const NPVariant *value) {
+ (void)instance;
+ return npobj->_class->setProperty (npobj, property, value);
+}
+
+static bool nsRemoveProperty (NPP inst, NPObject * npobj, NPIdentifier prop) {
+ (void)inst;
+ return npobj->_class->removeProperty (npobj, prop);
+}
+
+static bool nsHasProperty (NPP instance, NPObject * npobj, NPIdentifier prop) {
+ (void)instance;
+ return npobj->_class->hasProperty (npobj, prop);
+}
+
+static bool nsHasMethod (NPP instance, NPObject * npobj, NPIdentifier method) {
+ (void)instance;
+ return npobj->_class->hasMethod (npobj, method);
+}
+
+static void nsReleaseVariantValue (NPVariant * variant) {
+ /*print ("NPN_ReleaseVariantValue\n");*/
+ switch (variant->type) {
+ case NPVariantType_String:
+ if (variant->value.stringValue.utf8characters)
+ g_free ((char *) variant->value.stringValue.utf8characters);
+ break;
+ case NPVariantType_Object:
+ if (variant->value.objectValue)
+ nsReleaseObject (variant->value.objectValue);
+ break;
+ default:
+ break;
+ }
+ variant->type = NPVariantType_Null;
+}
+
+static void nsSetException (NPObject *npobj, const NPUTF8 *message) {
+ (void)npobj;
+ print ("NPN_SetException %s\n", message ? message : "-");
+}
+
+static bool nsPushPopupsEnabledState (NPP instance, NPBool enabled) {
+ (void)instance;
+ print ("NPN_PushPopupsEnabledState %d\n", enabled);
+ return false;
+}
+
+static bool nsPopPopupsEnabledState (NPP instance) {
+ (void)instance;
+ print ("NPN_PopPopupsEnabledState\n");
+ return false;
+}
+
+/*----------------%<---------------------------------------------------------*/
+
+static NPObject * windowClassAllocate (NPP instance, NPClass *aClass) {
+ (void)instance;
+ /*print ("windowClassAllocate\n");*/
+ JsObject * jo = (JsObject *) malloc (sizeof (JsObject));
+ memset (jo, 0, sizeof (JsObject));
+ jo->npobject._class = aClass;
+ return (NPObject *) jo;
+}
+
+static void windowClassDeallocate (NPObject *npobj) {
+ JsObject *jo = (JsObject *) npobj;
+ /*print ("windowClassDeallocate\n");*/
+ if (jo->parent) {
+ nsReleaseObject ((NPObject *) jo->parent);
+ } else if (jo->name && !strncmp (jo->name, "this.__kmplayer__obj_", 21)) {
+ char *script = (char *) malloc (strlen (jo->name) + 7);
+ char *result;
+ char *counter = strrchr (jo->name, '_');
+ sprintf (script, "%s=null;", jo->name);
+ result = evaluate (script);
+ free (script);
+ g_free (result);
+ if (counter) {
+ int c = strtol (counter +1, NULL, 10);
+ if (c == js_obj_counter -1)
+ js_obj_counter--; /*poor man's variable name reuse */
+ }
+ }
+ if (jo->name)
+ g_free (jo->name);
+ if (npobj == js_window) {
+ print ("WARNING deleting window object\n");
+ js_window = NULL;
+ }
+ free (npobj);
+}
+
+static void windowClassInvalidate (NPObject *npobj) {
+ (void)npobj;
+ print ("windowClassInvalidate\n");
+}
+
+static bool windowClassHasMethod (NPObject *npobj, NPIdentifier name) {
+ (void)npobj; (void)name;
+ print ("windowClassHasMehtod\n");
+ return false;
+}
+
+static bool windowClassInvoke (NPObject *npobj, NPIdentifier method,
+ const NPVariant *args, uint32_t arg_count, NPVariant *result) {
+ JsObject * jo = (JsObject *) npobj;
+ NPString str = { NULL, 0 };
+ char buf[512];
+ int pos, i;
+ bool res;
+ char * id = (char *) g_tree_lookup (identifiers, method);
+ /*print ("windowClassInvoke\n");*/
+
+ result->type = NPVariantType_Null;
+ result->value.objectValue = NULL;
+
+ if (!id) {
+ print ("Invoke invalid id\n");
+ return false;
+ }
+ print ("Invoke %s\n", id);
+ createJsName (jo, (char **)&str.utf8characters, &str.utf8length);
+ pos = snprintf (buf, sizeof (buf), "%s.%s(", str.utf8characters, id);
+ free ((char *) str.utf8characters);
+ for (i = 0; i < arg_count; i++) {
+ char *arg = nsVariant2Str (args + i);
+ pos += snprintf (buf + pos, sizeof (buf) - pos, i ? ",%s" : "%s", arg);
+ free (arg);
+ }
+ pos += snprintf (buf + pos, sizeof (buf) - pos, ")");
+
+ str.utf8characters = buf;
+ str.utf8length = pos;
+ res = nsEvaluate (npp, npobj, &str, result);
+
+ return true;
+}
+
+static bool windowClassInvokeDefault (NPObject *npobj,
+ const NPVariant *args, uint32_t arg_count, NPVariant *result) {
+ (void)npobj; (void)args; (void)arg_count; (void)result;
+ print ("windowClassInvokeDefault\n");
+ return false;
+}
+
+static bool windowClassHasProperty (NPObject *npobj, NPIdentifier name) {
+ (void)npobj; (void)name;
+ print ("windowClassHasProperty\n");
+ return false;
+}
+
+static bool windowClassGetProperty (NPObject *npobj, NPIdentifier property,
+ NPVariant *result) {
+ char * id = (char *) g_tree_lookup (identifiers, property);
+ JsObject jo;
+ NPString fullname = { NULL, 0 };
+ bool res;
+
+ print ("GetProperty %s\n", id);
+ result->type = NPVariantType_Null;
+ result->value.objectValue = NULL;
+
+ if (!id)
+ return false;
+
+ if (!strcmp (((JsObject *) npobj)->name, "window") &&
+ !strcmp (id, "top")) {
+ result->type = NPVariantType_Object;
+ result->value.objectValue = nsRetainObject (js_window);
+ return true;
+ }
+
+ jo.name = id;
+ jo.parent = (JsObject *) npobj;
+ createJsName (&jo, (char **)&fullname.utf8characters, &fullname.utf8length);
+
+ res = nsEvaluate (npp, npobj, &fullname, result);
+
+ free ((char *) fullname.utf8characters);
+
+ return res;
+}
+
+static bool windowClassSetProperty (NPObject *npobj, NPIdentifier property,
+ const NPVariant *value) {
+ char *id = (char *) g_tree_lookup (identifiers, property);
+ char *script, *var_name, *var_val, *res;
+ JsObject jo;
+ uint32_t len = 0;
+
+ if (!id)
+ return false;
+
+ jo.name = id;
+ jo.parent = (JsObject *) npobj;
+ createJsName (&jo, &var_name, &len);
+
+ var_val = nsVariant2Str (value);
+ script = (char *) malloc (len + strlen (var_val) + 3);
+ sprintf (script, "%s=%s;", var_name, var_val);
+ free (var_name);
+ free (var_val);
+ print ("SetProperty %s\n", script);
+
+ res = evaluate (script);
+ if (res)
+ g_free (res);
+ free (script);
+
+
+ return true;
+}
+
+static bool windowClassRemoveProperty (NPObject *npobj, NPIdentifier name) {
+ (void)npobj; (void)name;
+ print ("windowClassRemoveProperty\n");
+ return false;
+}
+
+
+/*----------------%<---------------------------------------------------------*/
+
+static void shutDownPlugin() {
+ if (scriptable_peer) {
+ nsReleaseObject (scriptable_peer);
+ scriptable_peer = NULL;
+ }
+ if (npShutdown) {
+ if (npp) {
+ np_funcs.destroy (npp, &saved_data);
+ free (npp);
+ npp = 0L;
+ }
+ npShutdown();
+ npShutdown = 0;
+ }
+}
+
+static void readStdin (gpointer p, gint src, GdkInputCondition cond) {
+ char *buf_ptr = stream_buf;
+ gsize bytes_read = read (src,
+ stream_buf + stream_buf_pos,
+ sizeof (stream_buf) - stream_buf_pos);
+ (void)cond; (void)p;
+ if (bytes_read > 0)
+ stream_buf_pos += bytes_read;
+
+ /*print ("readStdin %d\n", bytes_read);*/
+ while (buf_ptr < stream_buf + stream_buf_pos) {
+ uint32_t write_len;
+ int32_t bytes_written;
+
+ if (callback_service && !stream_chunk_size) {
+ /* read header info */
+ if (stream_buf + stream_buf_pos < buf_ptr + 2 * sizeof (uint32_t))
+ break; /* need more data */
+ current_stream_id = (gpointer)(long)*(uint32_t*)(buf_ptr);
+ stream_chunk_size = *((uint32_t *)(buf_ptr + sizeof (uint32_t)));
+ /*print ("header %d %d\n",(long)current_stream_id, stream_chunk_size);*/
+ buf_ptr += 2 * sizeof (uint32_t);
+ if (stream_chunk_size && stream_buf + stream_buf_pos == buf_ptr) {
+ stream_buf_pos = 0;
+ break; /* only read the header for chunk with data */
+ }
+ }
+ /* feed it to the stream */
+ write_len = stream_buf + stream_buf_pos - buf_ptr;
+ if (callback_service && write_len > stream_chunk_size)
+ write_len = stream_chunk_size;
+ bytes_written = writeStream (current_stream_id, buf_ptr, write_len);
+ if (bytes_written < 0) {
+ print ("couldn't write to stream %d\n", (long)current_stream_id);
+ bytes_written = write_len; /* assume stream destroyed, skip */
+ }
+
+ /* update chunk status */
+ if (bytes_written > 0) {
+ buf_ptr += bytes_written;
+ /*print ("update chunk %d %d\n", bytes_written, stream_chunk_size);*/
+ stream_chunk_size -= bytes_written;
+ } else {
+ /* FIXME if plugin didn't accept the data retry later, suspend stdin reading */
+ break;
+ }
+
+ }
+ /* update buffer */
+ /*print ("buffer written:%d bufpos:%d\n", buf_ptr-stream_buf, stream_buf_pos);*/
+ if (stream_buf + stream_buf_pos == buf_ptr) {
+ stream_buf_pos = 0;
+ } else {
+ g_assert (buf_ptr < stream_buf + stream_buf_pos);
+ stream_buf_pos -= (stream_buf + stream_buf_pos - buf_ptr);
+ memmove (stream_buf, buf_ptr, stream_buf_pos);
+ }
+ if (bytes_read <= 0) { /* eof of stdin, only for 'cat foo | knpplayer' */
+ StreamInfo*si=(StreamInfo*)g_tree_lookup(stream_list,current_stream_id);
+ si->reason = NPRES_DONE;
+ removeStream (current_stream_id);
+ if (stdin_read_watch) {
+ gdk_input_remove (stdin_read_watch);
+ stdin_read_watch = 0;
+ }
+ }
+}
+
+static int initPlugin (const char *plugin_lib) {
+ NPNetscapeFuncs ns_funcs;
+ NPError np_err;
+ char *pname;
+
+ print ("starting %s with %s\n", plugin_lib, object_url);
+ library = g_module_open (plugin_lib, G_MODULE_BIND_LAZY);
+ if (!library) {
+ print ("failed to load %s\n", plugin_lib);
+ return -1;
+ }
+ if (!g_module_symbol (library,
+ "NP_GetMIMEDescription", (gpointer *)&npGetMIMEDescription)) {
+ print ("undefined reference to load NP_GetMIMEDescription\n");
+ return -1;
+ }
+ if (!g_module_symbol (library,
+ "NP_GetValue", (gpointer *)&npGetValue)) {
+ print ("undefined reference to load NP_GetValue\n");
+ }
+ if (!g_module_symbol (library,
+ "NP_Initialize", (gpointer *)&npInitialize)) {
+ print ("undefined reference to load NP_Initialize\n");
+ return -1;
+ }
+ if (!g_module_symbol (library,
+ "NP_Shutdown", (gpointer *)&npShutdown)) {
+ print ("undefined reference to load NP_Shutdown\n");
+ return -1;
+ }
+ print ("startup succeeded %s\n", npGetMIMEDescription ());
+ memset (&ns_funcs, 0, sizeof (NPNetscapeFuncs));
+ ns_funcs.size = sizeof (NPNetscapeFuncs);
+ ns_funcs.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
+ ns_funcs.geturl = nsGetURL;
+ ns_funcs.posturl = nsPostURL;
+ ns_funcs.requestread = nsRequestRead;
+ ns_funcs.newstream = nsNewStream;
+ ns_funcs.write = nsWrite;
+ ns_funcs.destroystream = nsDestroyStream;
+ ns_funcs.status = nsStatus;
+ ns_funcs.uagent = nsUserAgent;
+ ns_funcs.memalloc = nsAlloc;
+ ns_funcs.memfree = nsMemFree;
+ ns_funcs.memflush = nsMemFlush;
+ ns_funcs.reloadplugins = nsReloadPlugins;
+ ns_funcs.getJavaEnv = nsGetJavaEnv;
+ ns_funcs.getJavaPeer = nsGetJavaPeer;
+ ns_funcs.geturlnotify = nsGetURLNotify;
+ ns_funcs.posturlnotify = nsPostURLNotify;
+ ns_funcs.getvalue = nsGetValue;
+ ns_funcs.setvalue = nsSetValue;
+ ns_funcs.invalidaterect = nsInvalidateRect;
+ ns_funcs.invalidateregion = nsInvalidateRegion;
+ ns_funcs.forceredraw = nsForceRedraw;
+ ns_funcs.getstringidentifier = nsGetStringIdentifier;
+ ns_funcs.getstringidentifiers = nsGetStringIdentifiers;
+ ns_funcs.getintidentifier = nsGetIntIdentifier;
+ ns_funcs.identifierisstring = nsIdentifierIsString;
+ ns_funcs.utf8fromidentifier = nsUTF8FromIdentifier;
+ ns_funcs.intfromidentifier = nsIntFromIdentifier;
+ ns_funcs.createobject = nsCreateObject;
+ ns_funcs.retainobject = nsRetainObject;
+ ns_funcs.releaseobject = nsReleaseObject;
+ ns_funcs.invoke = nsInvoke;
+ ns_funcs.invokeDefault = nsInvokeDefault;
+ ns_funcs.evaluate = nsEvaluate;
+ ns_funcs.getproperty = nsGetProperty;
+ ns_funcs.setproperty = nsSetProperty;
+ ns_funcs.removeproperty = nsRemoveProperty;
+ ns_funcs.hasproperty = nsHasProperty;
+ ns_funcs.hasmethod = nsHasMethod;
+ ns_funcs.releasevariantvalue = nsReleaseVariantValue;
+ ns_funcs.setexception = nsSetException;
+ ns_funcs.pushpopupsenabledstate = nsPushPopupsEnabledState;
+ ns_funcs.poppopupsenabledstate = nsPopPopupsEnabledState;
+
+ js_class.structVersion = NP_CLASS_STRUCT_VERSION;
+ js_class.allocate = windowClassAllocate;
+ js_class.deallocate = windowClassDeallocate;
+ js_class.invalidate = windowClassInvalidate;
+ js_class.hasMethod = windowClassHasMethod;
+ js_class.invoke = windowClassInvoke;
+ js_class.invokeDefault = windowClassInvokeDefault;
+ js_class.hasProperty = windowClassHasProperty;
+ js_class.getProperty = windowClassGetProperty;
+ js_class.setProperty = windowClassSetProperty;
+ js_class.removeProperty = windowClassRemoveProperty;
+
+ np_funcs.size = sizeof (NPPluginFuncs);
+
+ np_err = npInitialize (&ns_funcs, &np_funcs);
+ if (np_err != NPERR_NO_ERROR) {
+ print ("NP_Initialize failure %d\n", np_err);
+ npShutdown = 0;
+ return -1;
+ }
+ np_err = npGetValue (NULL, NPPVpluginNameString, &pname);
+ if (np_err == NPERR_NO_ERROR)
+ print ("NP_GetValue Name %s\n", pname);
+ np_err = npGetValue (NULL, NPPVpluginDescriptionString, &pname);
+ if (np_err == NPERR_NO_ERROR)
+ print ("NP_GetValue Description %s\n", pname);
+ return 0;
+}
+
+static int newPlugin (NPMIMEType mime, int16 argc, char *argn[], char *argv[]) {
+ NPSetWindowCallbackStruct ws_info;
+ NPError np_err;
+ Display *display;
+ int screen;
+ int i;
+ int needs_xembed;
+ uint32_t width = 0, height = 0;
+
+ for (i = 0; i < argc; i++) {
+ if (!strcasecmp (argn[i], "width"))
+ width = strtol (argv[i], 0L, 10);
+ else if (!strcasecmp (argn[i], "height"))
+ height = strtol (argv[i], 0L, 10);
+ }
+ if (width > 0 && height > 0)
+ callFunction (-1, "dimension",
+ DBUS_TYPE_UINT32, &width, DBUS_TYPE_UINT32, &height,
+ DBUS_TYPE_INVALID);
+
+ npp = (NPP_t*)malloc (sizeof (NPP_t));
+ memset (npp, 0, sizeof (NPP_t));
+ np_err = np_funcs.newp (mime, npp, NP_EMBED, argc, argn, argv, saved_data);
+ if (np_err != NPERR_NO_ERROR) {
+ print ("NPP_New failure %d %p %p\n", np_err, np_funcs, np_funcs.newp);
+ return -1;
+ }
+ if (np_funcs.getvalue) {
+ char *pname;
+ void *iid;
+ np_err = np_funcs.getvalue ((void*)npp,
+ NPPVpluginNameString, (void*)&pname);
+ if (np_err == NPERR_NO_ERROR)
+ print ("plugin name %s\n", pname);
+ np_err = np_funcs.getvalue ((void*)npp,
+ NPPVpluginNeedsXEmbed, (void*)&needs_xembed);
+ if (np_err != NPERR_NO_ERROR || !needs_xembed) {
+ print ("NPP_GetValue NPPVpluginNeedsXEmbed failure %d\n", np_err);
+ shutDownPlugin();
+ return -1;
+ }
+ np_err = np_funcs.getvalue ((void*)npp,
+ NPPVpluginScriptableIID, (void*)&iid);
+ np_err = np_funcs.getvalue ((void*)npp,
+ NPPVpluginScriptableNPObject, (void*)&scriptable_peer);
+ if (np_err != NPERR_NO_ERROR || !scriptable_peer)
+ print ("NPP_GetValue no NPPVpluginScriptableNPObject %d\n", np_err);
+ }
+ memset (&np_window, 0, sizeof (NPWindow));
+ display = gdk_x11_get_default_xdisplay ();
+ np_window.x = 0;
+ np_window.y = 0;
+ np_window.width = 1920;
+ np_window.height = 1200;
+ np_window.window = (void*)socket_id;
+ np_window.type = NPWindowTypeWindow;
+ ws_info.type = NP_SETWINDOW;
+ screen = DefaultScreen (display);
+ ws_info.display = (void*)(long)display;
+ ws_info.visual = (void*)(long)DefaultVisual (display, screen);
+ ws_info.colormap = DefaultColormap (display, screen);
+ ws_info.depth = DefaultDepth (display, screen);
+ print ("display %u %dx%d\n", socket_id, width, height);
+ np_window.ws_info = (void*)&ws_info;
+
+ GtkAllocation allocation;
+ allocation.x = 0;
+ allocation.y = 0;
+ allocation.width = np_window.width;
+ allocation.height = np_window.height;
+ gtk_widget_size_allocate (xembed, &allocation);
+
+ np_err = np_funcs.setwindow (npp, &np_window);
+
+ return 0;
+}
+
+static gpointer startPlugin (const char *url, const char *mime,
+ int argc, char *argn[], char *argv[]) {
+ StreamInfo *si;
+ if (!npp && (initPlugin (plugin) || newPlugin (mimetype, argc, argn, argv)))
+ return 0L;
+ si = addStream (url, mime, 0L, 0L, false);
+ return si;
+}
+
+/*----------------%<---------------------------------------------------------*/
+
+static StreamInfo *getStreamInfo (const char *path, gpointer *stream_id) {
+ const char *p = strrchr (path, '_');
+ *stream_id = p ? (gpointer) strtol (p+1, NULL, 10) : NULL;
+ return (StreamInfo *) g_tree_lookup (stream_list, *stream_id);
+}
+
+static DBusHandlerResult dbusFilter (DBusConnection * connection,
+ DBusMessage *msg, void * user_data) {
+ DBusMessageIter args;
+ const char *sender = dbus_message_get_sender (msg);
+ const char *iface = "org.kde.kmplayer.backend";
+ (void)user_data; (void)connection;
+ if (!dbus_message_has_destination (msg, service_name))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ print ("dbusFilter %s %s\n", sender,dbus_message_get_interface (msg));
+ if (dbus_message_is_method_call (msg, iface, "play")) {
+ DBusMessageIter ait;
+ char *param = 0;
+ unsigned int params;
+ char **argn = NULL;
+ char **argv = NULL;
+ int i;
+ if (!dbus_message_iter_init (msg, &args) ||
+ DBUS_TYPE_STRING != dbus_message_iter_get_arg_type (&args)) {
+ g_printerr ("missing url arg");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ dbus_message_iter_get_basic (&args, &param);
+ object_url = g_strdup (param);
+ if (!dbus_message_iter_next (&args) ||
+ DBUS_TYPE_STRING != dbus_message_iter_get_arg_type (&args)) {
+ g_printerr ("missing mimetype arg");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ dbus_message_iter_get_basic (&args, &param);
+ mimetype = g_strdup (param);
+ if (!dbus_message_iter_next (&args) ||
+ DBUS_TYPE_STRING != dbus_message_iter_get_arg_type (&args)) {
+ g_printerr ("missing plugin arg");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ dbus_message_iter_get_basic (&args, &param);
+ plugin = g_strdup (param);
+ if (!dbus_message_iter_next (&args) ||
+ DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type (&args)) {
+ g_printerr ("missing param count arg");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ dbus_message_iter_get_basic (&args, &params);
+ if (params > 0 && params < 100) {
+ argn = (char**) malloc (params * sizeof (char *));
+ argv = (char**) malloc (params * sizeof (char *));
+ }
+ if (!dbus_message_iter_next (&args) ||
+ DBUS_TYPE_ARRAY != dbus_message_iter_get_arg_type (&args)) {
+ g_printerr ("missing params array");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ dbus_message_iter_recurse (&args, &ait);
+ for (i = 0; i < params; i++) {
+ char *key, *value;
+ DBusMessageIter di;
+ if (dbus_message_iter_get_arg_type (&ait) != DBUS_TYPE_DICT_ENTRY)
+ break;
+ dbus_message_iter_recurse (&ait, &di);
+ if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type (&di))
+ break;
+ dbus_message_iter_get_basic (&di, &key);
+ if (!dbus_message_iter_next (&di) ||
+ DBUS_TYPE_STRING != dbus_message_iter_get_arg_type (&di))
+ break;
+ dbus_message_iter_get_basic (&di, &value);
+ argn[i] = g_strdup (key);
+ argv[i] = g_strdup (value);
+ print ("param %d:%s='%s'\n", i + 1, argn[i], value);
+ if (!dbus_message_iter_next (&ait))
+ params = i + 1;
+ }
+ print ("play %s %s %s params:%d\n", object_url,
+ mimetype ? mimetype : "", plugin, i);
+ startPlugin (object_url, mimetype, i, argn, argv);
+ } else if (dbus_message_is_method_call (msg, iface, "redirected")) {
+ char *url = 0;
+ gpointer stream_id;
+ StreamInfo *si = getStreamInfo(dbus_message_get_path (msg), &stream_id);
+ if (si && dbus_message_iter_init (msg, &args) &&
+ DBUS_TYPE_STRING == dbus_message_iter_get_arg_type (&args)) {
+ dbus_message_iter_get_basic (&args, &url);
+ free (si->url);
+ si->url = g_strdup (url);
+ si->np_stream.url = si->url;
+ print ("redirect %d (had data %d) to %s\n", (long)stream_id, si->called_plugin, url);
+ }
+ } else if (dbus_message_is_method_call (msg, iface, "eof")) {
+ gpointer stream_id;
+ StreamInfo *si = getStreamInfo(dbus_message_get_path (msg), &stream_id);
+ if (si && dbus_message_iter_init (msg, &args) &&
+ DBUS_TYPE_UINT32 == dbus_message_iter_get_arg_type (&args)) {
+ dbus_message_iter_get_basic (&args, &si->total);
+ if (dbus_message_iter_next (&args) &&
+ DBUS_TYPE_UINT32 == dbus_message_iter_get_arg_type (&args)) {
+ dbus_message_iter_get_basic (&args, &si->reason);
+ print ("eof %d bytes:%d reason:%d\n", (long)stream_id, si->total, si->reason);
+ if (si->stream_pos == si->total || si->destroyed)
+ removeStream (stream_id);
+ }
+ }
+ } else if (dbus_message_is_method_call (msg, iface, "quit")) {
+ print ("quit\n");
+ shutDownPlugin();
+ gtk_main_quit();
+ } else if (dbus_message_is_method_call (msg, iface, "streamInfo")) {
+ gpointer stream_id;
+ StreamInfo *si = getStreamInfo(dbus_message_get_path (msg), &stream_id);
+ const char *mime;
+ uint32_t length;
+ if (si && dbus_message_iter_init (msg, &args) &&
+ DBUS_TYPE_STRING == dbus_message_iter_get_arg_type (&args)) {
+ dbus_message_iter_get_basic (&args, &mime);
+ if (*mime) {
+ if (si->mimetype)
+ g_free (si->mimetype);
+ si->mimetype = g_strdup (mime);
+ }
+ if (dbus_message_iter_next (&args) &&
+ DBUS_TYPE_UINT32 == dbus_message_iter_get_arg_type (&args)) {
+ dbus_message_iter_get_basic (&args, &length);
+ si->np_stream.end = length;
+ }
+ print ("streamInfo %d size:%d mime:%s\n", (long)stream_id, length,
+ mime ? mime : "");
+ }
+ } else {
+ print ("unknown message\n");
+ }
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void callFunction(int stream,const char *func, int first_arg_type, ...) {
+ char path[64];
+ strncpy (path, callback_path, sizeof (path) -1);
+ if (stream > -1) {
+ int len = strlen (path);
+ snprintf (path + len, sizeof (path) - len, "/stream_%d", stream);
+ }
+ print ("call %s.%s()\n", path, func);
+ if (callback_service) {
+ va_list var_args;
+ DBusMessage *msg = dbus_message_new_method_call (
+ callback_service,
+ path,
+ "org.kde.kmplayer.callback",
+ func);
+ if (first_arg_type != DBUS_TYPE_INVALID) {
+ va_start (var_args, first_arg_type);
+ dbus_message_append_args_valist (msg, first_arg_type, var_args);
+ va_end (var_args);
+ }
+ dbus_message_set_no_reply (msg, TRUE);
+ dbus_connection_send (dbus_connection, msg, NULL);
+ dbus_message_unref (msg);
+ dbus_connection_flush (dbus_connection);
+ }
+}
+
+static char * evaluate (const char *script) {
+ char * ret = NULL;
+ print ("evaluate %s", script);
+ if (callback_service) {
+ DBusMessage *rmsg;
+ DBusMessage *msg = dbus_message_new_method_call (
+ callback_service,
+ callback_path,
+ "org.kde.kmplayer.callback",
+ "evaluate");
+ dbus_message_append_args (
+ msg, DBUS_TYPE_STRING, &script, DBUS_TYPE_INVALID);
+ rmsg = dbus_connection_send_with_reply_and_block (dbus_connection,
+ msg, 2000, NULL);
+ if (rmsg) {
+ DBusMessageIter it;
+ if (dbus_message_iter_init (rmsg, &it) &&
+ DBUS_TYPE_STRING == dbus_message_iter_get_arg_type (&it)) {
+ char * param;
+ dbus_message_iter_get_basic (&it, &param);
+ ret = g_strdup (param);
+ }
+ dbus_message_unref (rmsg);
+ print (" => %s\n", ret);
+ }
+ dbus_message_unref (msg);
+ } else {
+ print (" => NA\n");
+ }
+ return ret;
+}
+
+/*----------------%<---------------------------------------------------------*/
+
+static void pluginAdded (GtkSocket *socket, gpointer d) {
+ /*(void)socket;*/ (void)d;
+ print ("pluginAdded\n");
+ if (socket->plug_window) {
+ gpointer user_data = NULL;
+ gdk_window_get_user_data (socket->plug_window, &user_data);
+ if (!user_data) {
+ /**
+ * GtkSocket resets plugins XSelectInput in
+ * _gtk_socket_add_window
+ * _gtk_socket_windowing_select_plug_window_input
+ **/
+ XSelectInput (gdk_x11_get_default_xdisplay (),
+ gdk_x11_drawable_get_xid (socket->plug_window),
+ KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ KeymapStateMask |
+ ButtonMotionMask |
+ PointerMotionMask |
+ EnterWindowMask | LeaveWindowMask |
+ FocusChangeMask |
+ ExposureMask |
+ StructureNotifyMask |
+ SubstructureRedirectMask |
+ PropertyChangeMask
+ );
+ }
+ }
+ callFunction (-1, "plugged", DBUS_TYPE_INVALID);
+}
+
+static void windowCreatedEvent (GtkWidget *w, gpointer d) {
+ (void)d;
+ print ("windowCreatedEvent\n");
+ socket_id = gtk_socket_get_id (GTK_SOCKET (xembed));
+ if (parent_id) {
+ print ("windowCreatedEvent %p\n", GTK_PLUG (w)->socket_window);
+ if (!GTK_PLUG (w)->socket_window)
+ gtk_plug_construct (GTK_PLUG (w), parent_id);
+ gdk_window_reparent( w->window,
+ GTK_PLUG (w)->socket_window
+ ? GTK_PLUG (w)->socket_window
+ : gdk_window_foreign_new (parent_id),
+ 0, 0);
+ gtk_widget_show_all (w);
+ /*XReparentWindow (gdk_x11_drawable_get_xdisplay (w->window),
+ gdk_x11_drawable_get_xid (w->window),
+ parent_id,
+ 0, 0);*/
+ }
+ if (!callback_service) {
+ char *argn[] = { "WIDTH", "HEIGHT", "debug", "SRC" };
+ char *argv[] = { "440", "330", g_strdup("yes"), g_strdup(object_url) };
+ startPlugin (object_url, mimetype, 4, argn, argv);
+ }
+}
+
+static void embeddedEvent (GtkPlug *plug, gpointer d) {
+ (void)plug; (void)d;
+ print ("embeddedEvent\n");
+}
+
+static gboolean updateDimension (void * p) {
+ (void)p;
+ if (np_window.window) {
+ if (np_window.width != top_w || np_window.height != top_h) {
+ np_window.width = top_w;
+ np_window.height = top_h;
+ np_funcs.setwindow (npp, &np_window);
+ }
+ update_dimension_timer = 0;
+ return 0; /* single shot */
+ } else {
+ return 1;
+ }
+}
+
+static gboolean configureEvent(GtkWidget *w, GdkEventConfigure *e, gpointer d) {
+ (void)w; (void)d;
+ if (e->width != top_w || e->height != top_h) {
+ top_w = e->width;
+ top_h = e->height;
+ if (!update_dimension_timer)
+ update_dimension_timer = g_timeout_add (100, updateDimension, NULL);
+ }
+ return FALSE;
+}
+
+static gboolean windowCloseEvent (GtkWidget *w, GdkEvent *e, gpointer d) {
+ (void)w; (void)e; (void)d;
+ shutDownPlugin();
+ return FALSE;
+}
+
+static void windowDestroyEvent (GtkWidget *w, gpointer d) {
+ (void)w; (void)d;
+ gtk_main_quit();
+}
+
+static gboolean initPlayer (void * p) {
+ GtkWidget *window;
+ GdkColormap *color_map;
+ GdkColor bg_color;
+ (void)p;
+
+ window = callback_service
+ ? gtk_plug_new (parent_id)
+ : gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (G_OBJECT (window), "delete_event",
+ G_CALLBACK (windowCloseEvent), NULL);
+ g_signal_connect (G_OBJECT (window), "destroy",
+ G_CALLBACK (windowDestroyEvent), NULL);
+ g_signal_connect_after (G_OBJECT (window), "realize",
+ GTK_SIGNAL_FUNC (windowCreatedEvent), NULL);
+ g_signal_connect (G_OBJECT (window), "configure-event",
+ GTK_SIGNAL_FUNC (configureEvent), NULL);
+
+ xembed = gtk_socket_new();
+ g_signal_connect (G_OBJECT (xembed), "plug-added",
+ GTK_SIGNAL_FUNC (pluginAdded), NULL);
+
+ color_map = gdk_colormap_get_system();
+ gdk_colormap_query_color (color_map, 0, &bg_color);
+ gtk_widget_modify_bg (xembed, GTK_STATE_NORMAL, &bg_color);
+
+ gtk_container_add (GTK_CONTAINER (window), xembed);
+
+ if (!parent_id) {
+ gtk_widget_set_size_request (window, 440, 330);
+ gtk_widget_show_all (window);
+ } else {
+ g_signal_connect (G_OBJECT (window), "embedded",
+ GTK_SIGNAL_FUNC (embeddedEvent), NULL);
+ gtk_widget_set_size_request (window, 1920, 1200);
+ gtk_widget_realize (window);
+ }
+
+ if (callback_service && callback_path) {
+ DBusError dberr;
+ const char *serv = "type='method_call',interface='org.kde.kmplayer.backend'";
+ char myname[64];
+
+ dbus_error_init (&dberr);
+ dbus_connection = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
+ if (!dbus_connection) {
+ g_printerr ("Failed to open connection to bus: %s\n",
+ dberr.message);
+ exit (1);
+ }
+ g_sprintf (myname, "org.kde.kmplayer.npplayer-%d", getpid ());
+ service_name = g_strdup (myname);
+ print ("using service %s was '%s'\n", service_name, dbus_bus_get_unique_name (dbus_connection));
+ dbus_connection_setup_with_g_main (dbus_connection, 0L);
+ dbus_bus_request_name (dbus_connection, service_name,
+ DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
+ if (dbus_error_is_set (&dberr)) {
+ g_printerr ("Failed to register name: %s\n", dberr.message);
+ dbus_connection_unref (dbus_connection);
+ return -1;
+ }
+ dbus_bus_add_match (dbus_connection, serv, &dberr);
+ if (dbus_error_is_set (&dberr)) {
+ g_printerr ("dbus_bus_add_match error: %s\n", dberr.message);
+ dbus_connection_unref (dbus_connection);
+ return -1;
+ }
+ dbus_connection_add_filter (dbus_connection, dbusFilter, 0L, 0L);
+
+ /* TODO: remove DBUS_BUS_SESSION and create a private connection */
+ callFunction (-1, "running",
+ DBUS_TYPE_STRING, &service_name, DBUS_TYPE_INVALID);
+
+ dbus_connection_flush (dbus_connection);
+ }
+ return 0; /* single shot */
+}
+
+int main (int argc, char **argv) {
+ int i;
+
+ XInitThreads ();
+ g_thread_init (NULL);
+ gtk_init (&argc, &argv);
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp (argv[i], "-p") && ++i < argc) {
+ plugin = g_strdup (argv[i]);
+ } else if (!strcmp (argv[i], "-cb") && ++i < argc) {
+ gchar *cb = g_strdup (argv[i]);
+ gchar *path = strchr(cb, '/');
+ if (path) {
+ callback_path = g_strdup (path);
+ *path = 0;
+ }
+ callback_service = g_strdup (cb);
+ g_free (cb);
+ } else if (!strcmp (argv[i], "-m") && ++i < argc) {
+ mimetype = g_strdup (argv[i]);
+ } else if (!strcmp (argv [i], "-wid") && ++i < argc) {
+ parent_id = strtol (argv[i], 0L, 10);
+ } else
+ object_url = g_strdup (argv[i]);
+ }
+ if (!callback_service && !(object_url && mimetype && plugin)) {
+ g_fprintf(stderr, "Usage: %s <-m mimetype -p plugin url|-cb service -wid id>\n", argv[0]);
+ return 1;
+ }
+
+ identifiers = g_tree_new (strcmp);
+ stream_list = g_tree_new (streamCompare);
+
+ g_timeout_add (0, initPlayer, NULL);
+
+ fcntl (0, F_SETFL, fcntl (0, F_GETFL) | O_NONBLOCK);
+
+ print ("entering gtk_main\n");
+
+ gtk_main();
+
+ if (dbus_connection)
+ dbus_connection_unref (dbus_connection);
+
+ return 0;
+}