e6f90bea14
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3531 fc73d0e0-1445-4013-8a0c-d673dee63da5
689 lines
17 KiB
C
689 lines
17 KiB
C
#include "quakedef.h"
|
|
#include "winquake.h"
|
|
#define bool int //we ain't c++ (grr microsoft stdbool.h gief!)
|
|
|
|
#ifdef _WIN32
|
|
#ifndef _WINDOWS
|
|
#define _WINDOWS //stupid GCC
|
|
#endif
|
|
#endif
|
|
|
|
#include "npapi/npupp.h"
|
|
#include "sys_plugfte.h"
|
|
|
|
#define Q_STRINGZ_TO_NPVARIANT(_val, _v) \
|
|
NP_BEGIN_MACRO \
|
|
NPString str = { _val, strlen(_val) }; \
|
|
(_v).type = NPVariantType_String; \
|
|
(_v).value.stringValue = str; \
|
|
NP_END_MACRO
|
|
#undef STRINGZ_TO_NPVARIANT
|
|
#define STRINGZ_TO_NPVARIANT Q_STRINGZ_TO_NPVARIANT
|
|
|
|
#define FIREFOX_BUGS_OVER_25MB
|
|
|
|
//TODO: player name input (before allowing them to join)
|
|
//TODO: fix active gl context (per thread, and we hijacked the browser's thread)
|
|
|
|
|
|
NPNetscapeFuncs *browserfuncs;
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
#ifndef GetWindowLongPtr
|
|
#define GetWindowLongPtr GetWindowLong
|
|
#endif
|
|
#ifndef SetWindowLongPtr
|
|
#define SetWindowLongPtr SetWindowLong
|
|
#define LONG_PTR LONG
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
qboolean NPFTE_BeginDownload(void *ctx, struct pipetype *ftype, char *url)
|
|
{
|
|
return NPERR_NO_ERROR==browserfuncs->geturlnotify(ctx, url, NULL, ftype);
|
|
}
|
|
|
|
void NPFTE_StatusChanged(struct context *ctx)
|
|
{
|
|
struct contextpublic *pub = (struct contextpublic*)ctx;
|
|
InvalidateRgn(pub->oldwnd, NULL, FALSE);
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
void DrawWndBack(struct context *ctx, HWND hWnd, HDC hdc, PAINTSTRUCT *p)
|
|
{
|
|
int width, height;
|
|
HBITMAP bmp = Plug_GetSplashBack(ctx, hdc, &width, &height);
|
|
if (bmp)
|
|
{
|
|
HDC memDC;
|
|
RECT irect;
|
|
|
|
memDC = CreateCompatibleDC(hdc);
|
|
SelectObject(memDC, bmp);
|
|
GetClientRect(hWnd, &irect);
|
|
StretchBlt(hdc, irect.left, irect.top, irect.right-irect.left,irect.bottom-irect.top, memDC, 0, 0, width, height, SRCCOPY);
|
|
SelectObject(memDC, NULL);
|
|
DeleteDC(memDC);
|
|
Plug_ReleaseSplashBack(ctx, bmp);
|
|
}
|
|
else
|
|
PatBlt(hdc, p->rcPaint.left, p->rcPaint.top, p->rcPaint.right-p->rcPaint.left,p->rcPaint.bottom-p->rcPaint.top,PATCOPY);
|
|
}
|
|
|
|
LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
struct context *ctx;
|
|
struct contextpublic *pub;
|
|
ctx = (struct context *)GetWindowLongPtr(hWnd, GWL_USERDATA);
|
|
if (!ctx)
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
pub = (struct contextpublic*)ctx;
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_USER:
|
|
/*if the plugin is somewhere in video code, the plugin might depend upon us being able to respond to window messages*/
|
|
/* while(ctx->queuedstreams)
|
|
{
|
|
struct qstream *strm;
|
|
strm = ctx->queuedstreams;
|
|
ctx->queuedstreams = strm->next;
|
|
|
|
if (!browserfuncs->geturlnotify(ctx->nppinstance, strm->url, NULL, strm->type))
|
|
{
|
|
VS_DebugLocation(__FILE__, __LINE__, "Starting Download %s", strm->url);
|
|
if (strm->type->wait == WAIT_YES)
|
|
ctx->waitingfordatafiles++;
|
|
}
|
|
free(strm);
|
|
}
|
|
*/
|
|
return TRUE;
|
|
|
|
case WM_PAINT:
|
|
if (pub->downloading)
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT paint;
|
|
char *s;
|
|
unsigned int progress;
|
|
unsigned int total;
|
|
|
|
progress = pub->dldone;
|
|
total = pub->dlsize;
|
|
|
|
hdc = BeginPaint(hWnd, &paint);
|
|
DrawWndBack(ctx, hWnd, hdc, &paint);
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
TextOutA(hdc, 0, 0, "Downloading Data, please wait", 16);
|
|
if (!progress && !total)
|
|
s = "connecting";
|
|
else if (total)
|
|
s = va("%i bytes (%i%%)", progress, (int)((100.0f*progress)/total));
|
|
else
|
|
s = va("%i bytes", progress);
|
|
TextOutA(hdc, 0, 32, s, strlen(s));
|
|
EndPaint(hWnd, &paint);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT paint;
|
|
char *s;
|
|
|
|
hdc = BeginPaint(hWnd, &paint);
|
|
DrawWndBack(ctx, hWnd, hdc, &paint);
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
if (!pub->running)
|
|
{
|
|
s = "Click to activate";
|
|
TextOutA(hdc, 0, 0, s, strlen(s));
|
|
|
|
if (pub->availver)
|
|
{
|
|
s = va("Your plugin may be incompatible");
|
|
TextOutA(hdc, 0, 32, s, strlen(s));
|
|
s = va("Version %3.2f was requested, you are using version %3.2f", pub->availver, (float)build_number());
|
|
TextOutA(hdc, 0, 48, s, strlen(s));
|
|
}
|
|
}
|
|
EndPaint(hWnd, &paint);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
SetActiveWindow(hWnd);
|
|
if (!Plug_StartContext(ctx))
|
|
Plug_StopContext(NULL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//I would call the previous wndproc... but that crashes firefox
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
|
|
#endif
|
|
|
|
static const struct browserfuncs npfte_browserfuncs =
|
|
{
|
|
NPFTE_BeginDownload,
|
|
NPFTE_StatusChanged
|
|
};
|
|
|
|
NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
|
|
uint16 mode, int16 argc, char* argn[],
|
|
char* argv[], NPSavedData* saved)
|
|
{
|
|
int i;
|
|
struct context *ctx;
|
|
|
|
if (!instance || instance->pdata)
|
|
{
|
|
return NPERR_INVALID_INSTANCE_ERROR;
|
|
}
|
|
if (mode != NP_EMBED && mode != NP_FULL)
|
|
{
|
|
return NPERR_INVALID_PLUGIN_ERROR;
|
|
}
|
|
|
|
ctx = Plug_CreateContext(instance, &npfte_browserfuncs);
|
|
instance->pdata = ctx;
|
|
if (!ctx)
|
|
{
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
}
|
|
|
|
//parse out the properties
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
Plug_SetString(ctx, Plug_FindProp(ctx, argn[i]), argv[i]);
|
|
}
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save)
|
|
{
|
|
struct context *ctx = instance->pdata;
|
|
struct contextpublic *pub = (struct contextpublic *)ctx;
|
|
|
|
if (!ctx)
|
|
return NPERR_INVALID_INSTANCE_ERROR;
|
|
|
|
#ifdef _WIN32
|
|
if (pub->oldwnd)
|
|
{
|
|
if (pub->oldproc)
|
|
SetWindowLongPtr(pub->oldwnd, GWL_WNDPROC, (LONG_PTR)pub->oldproc);
|
|
SetWindowLongPtr(pub->oldwnd, GWL_USERDATA, (LONG_PTR)NULL);
|
|
}
|
|
#endif
|
|
|
|
Plug_DestroyContext(ctx);
|
|
instance->pdata = NULL;
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window)
|
|
{
|
|
extern cvar_t vid_width;
|
|
struct context *ctx = instance->pdata;
|
|
struct contextpublic *pub = (struct contextpublic*)ctx;
|
|
|
|
#ifdef _WIN32
|
|
WNDPROC p;
|
|
|
|
if (!ctx)
|
|
return NPERR_INVALID_INSTANCE_ERROR;
|
|
|
|
//if the window changed
|
|
if (Plug_ChangeWindow(ctx, window->window, window->width, window->height))
|
|
{
|
|
//we switched window?
|
|
if (pub->oldwnd && pub->oldproc)
|
|
{
|
|
SetWindowLongPtr(pub->oldwnd, GWL_WNDPROC, (LONG_PTR)pub->oldproc);
|
|
}
|
|
pub->oldproc = NULL;
|
|
|
|
p = (WNDPROC)GetWindowLongPtr(window->window, GWL_WNDPROC);
|
|
if (p != MyPluginWndProc)
|
|
pub->oldproc = p;
|
|
pub->oldwnd = window->window;
|
|
|
|
SetWindowLongPtr(window->window, GWL_WNDPROC, (LONG_PTR)MyPluginWndProc);
|
|
SetWindowLongPtr(window->window, GWL_USERDATA, (LONG_PTR)ctx);
|
|
}
|
|
|
|
InvalidateRgn(window->window, NULL, FALSE);
|
|
#endif
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
|
|
NPStream* stream, NPBool seekable,
|
|
uint16* stype)
|
|
{
|
|
return NPERR_NO_ERROR;
|
|
/* struct context *ctx = instance->pdata;
|
|
struct qstream *qstr;
|
|
|
|
stream->pdata = qstr = malloc(sizeof(*qstr) + strlen(stream->url));
|
|
memset(qstr, 0, sizeof(*qstr));
|
|
strcpy(qstr->url, stream->url);
|
|
|
|
Plug_LockPlugin(ctx, true);
|
|
qstr->next = ctx->activestreams;
|
|
if (qstr->next)
|
|
qstr->next->prev = qstr;
|
|
ctx->activestreams = qstr;
|
|
Plug_LockPlugin(ctx, false);
|
|
|
|
if (!stream->notifyData)
|
|
{
|
|
//choose source type based on mime type
|
|
if (!strncmp(type, "text/x-quaketvident", 5))
|
|
stream->notifyData = &QTVFileDescriptor;
|
|
else if (!strcmp(type, "application/x-multiviewdemo"))
|
|
stream->notifyData = &DemoFileDescriptor;
|
|
|
|
//well that failed, try choosing based on extension
|
|
else if (!strcmp(COM_FileExtension(stream->url), "qtv"))
|
|
stream->notifyData = &QTVFileDescriptor;
|
|
|
|
else
|
|
return NPERR_INVALID_PARAM;
|
|
}
|
|
qstr->type = stream->notifyData;
|
|
|
|
if (qstr->type->needseeking)
|
|
{
|
|
*stype = NP_ASFILEONLY; //everything is a download
|
|
|
|
#ifdef FIREFOX_BUGS_OVER_25MB
|
|
*stype = NP_NORMAL;
|
|
qstr->pipe = FS_OpenTemp();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
*stype = NP_NORMAL;
|
|
qstr->pipe = VFSPIPE_Open();
|
|
}
|
|
|
|
return NPERR_NO_ERROR;*/
|
|
}
|
|
NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
|
|
NPReason reason)
|
|
{
|
|
return NPERR_NO_ERROR;
|
|
/* struct context *ctx = instance->pdata;
|
|
struct qstream *qstr = stream->pdata;
|
|
|
|
if (!qstr) //urm, got canceled before it finished downloading?
|
|
return NPERR_NO_ERROR;
|
|
|
|
if (qstr->type->wait == WAIT_YES)
|
|
{
|
|
ctx->waitingfordatafiles--;
|
|
}
|
|
|
|
if (qstr->next)
|
|
qstr->next->prev = qstr->prev;
|
|
if (qstr->prev)
|
|
qstr->prev->next = qstr->next;
|
|
else
|
|
ctx->activestreams = qstr->next;
|
|
|
|
if (qstr->type->wait == WAIT_NONACTIVE)
|
|
{
|
|
Plug_LockPlugin(ctx, true);
|
|
qstr->type->completionfunc(ctx, qstr->pipe, qstr->url);
|
|
Plug_LockPlugin(ctx, false);
|
|
}
|
|
else
|
|
{
|
|
qstr->next = ctx->donestreams;
|
|
ctx->donestreams = qstr;
|
|
}
|
|
|
|
if (qstr && qstr->type && qstr->type->wait)
|
|
{
|
|
InvalidateRgn(ctx->window.window, NULL, FALSE);
|
|
}
|
|
return NPERR_NO_ERROR;*/
|
|
}
|
|
int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream)
|
|
{
|
|
return 8192;
|
|
|
|
/* struct qstream *qstr = stream->pdata;
|
|
vfsfile_t *pipe = qstr?qstr->pipe:NULL;
|
|
|
|
if (pipe && pipe->seekingisabadplan)
|
|
return 1024*1024 - VFS_GETLEN(pipe);
|
|
else
|
|
return 8192;*/
|
|
}
|
|
int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset,
|
|
int32 len, void* buffer)
|
|
{
|
|
return NPERR_NO_ERROR;
|
|
/* int bytes = NPP_WriteReady(instance, stream);
|
|
struct context *ctx = instance->pdata;
|
|
struct qstream *qstr = stream->pdata;
|
|
|
|
if (qstr && qstr->type && qstr->type->wait)
|
|
{
|
|
qstr->offset = offset;
|
|
qstr->size = stream->end;
|
|
InvalidateRgn(ctx->window.window, NULL, FALSE);
|
|
}
|
|
|
|
if (!qstr || !qstr->pipe)
|
|
return bytes;
|
|
|
|
//we're not meant to read more bytes than we said we could read.
|
|
if (len > bytes)
|
|
len = bytes;
|
|
|
|
return VFS_WRITE(qstr->pipe, buffer, len);*/
|
|
}
|
|
void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
|
|
const char* fname)
|
|
{
|
|
return;
|
|
/* struct qstream *qstr = stream->pdata;
|
|
|
|
if (!qstr)
|
|
return;
|
|
|
|
if (qstr->pipe)
|
|
VFS_CLOSE(qstr->pipe);
|
|
qstr->pipe = VFSOS_Open(fname, "rb");
|
|
*/
|
|
}
|
|
|
|
void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint)
|
|
{
|
|
//we don't support printing.
|
|
//paper and ink doesn't give a good frame rate.
|
|
return;
|
|
}
|
|
int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event)
|
|
{
|
|
// MessageBox(NULL, "NPP_HandleEvent", "npapi", 0);
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
|
|
NPReason reason, void* notifyData)
|
|
{
|
|
}
|
|
|
|
struct npscript
|
|
{
|
|
NPObject obj;
|
|
|
|
struct context *ctx;
|
|
};
|
|
|
|
NPObject *npscript_allocate(NPP npp, NPClass *aClass)
|
|
{
|
|
struct npscript *obj;
|
|
obj = malloc(sizeof(*obj));
|
|
obj->obj._class = aClass;
|
|
obj->obj.referenceCount = 1;
|
|
obj->ctx = npp->pdata;
|
|
|
|
return (NPObject*)obj;
|
|
}
|
|
void npscript_deallocate(NPObject *npobj)
|
|
{
|
|
free(npobj);
|
|
}
|
|
void npscript_invalidate(NPObject *npobj)
|
|
{
|
|
struct npscript *obj = (struct npscript *)npobj;
|
|
obj->ctx = NULL;
|
|
}
|
|
bool npscript_hasMethod(NPObject *npobj, NPIdentifier name)
|
|
{
|
|
NPUTF8 *mname;
|
|
mname = browserfuncs->utf8fromidentifier(name);
|
|
return false;
|
|
}
|
|
bool npscript_invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
|
|
{
|
|
return false;
|
|
}
|
|
bool npscript_invokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)
|
|
{
|
|
return false;
|
|
}
|
|
bool npscript_hasProperty(NPObject *npobj, NPIdentifier name)
|
|
{
|
|
struct npscript *obj = (struct npscript *)npobj;
|
|
NPUTF8 *pname;
|
|
pname = browserfuncs->utf8fromidentifier(name);
|
|
|
|
if (Plug_FindProp(obj->ctx, pname))
|
|
return true;
|
|
return false;
|
|
}
|
|
bool npscript_getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
|
|
{
|
|
struct npscript *obj = (struct npscript *)npobj;
|
|
struct context *ctx = obj->ctx;
|
|
NPUTF8 *pname;
|
|
struct pscript_property *prop;
|
|
bool success = false;
|
|
char *strval;
|
|
int intval;
|
|
float floatval;
|
|
pname = browserfuncs->utf8fromidentifier(name);
|
|
|
|
Plug_LockPlugin(ctx, true);
|
|
prop = Plug_FindProp(obj->ctx, pname);
|
|
if (prop)
|
|
{
|
|
if (Plug_GetString(ctx, prop, &strval))
|
|
{
|
|
char *ns;
|
|
int len;
|
|
len = strlen(strval);
|
|
ns = browserfuncs->memalloc(len);
|
|
if (ns)
|
|
{
|
|
memcpy(ns, strval, len);
|
|
STRINGZ_TO_NPVARIANT(ns, *result);
|
|
success = true;
|
|
}
|
|
Plug_GotString(strval);
|
|
}
|
|
else if (Plug_GetInteger(ctx, prop, &intval))
|
|
{
|
|
INT32_TO_NPVARIANT(intval, *result);
|
|
success = true;
|
|
}
|
|
else if (Plug_GetFloat(ctx, prop, &floatval))
|
|
{
|
|
DOUBLE_TO_NPVARIANT(floatval, *result);
|
|
success = true;
|
|
}
|
|
}
|
|
Plug_LockPlugin(ctx, false);
|
|
return success;
|
|
}
|
|
bool npscript_setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
|
|
{
|
|
struct npscript *obj = (struct npscript *)npobj;
|
|
struct context *ctx = obj->ctx;
|
|
NPUTF8 *pname;
|
|
NPString str;
|
|
struct pscript_property *prop;
|
|
bool success = false;
|
|
pname = browserfuncs->utf8fromidentifier(name);
|
|
|
|
Plug_LockPlugin(ctx, true);
|
|
prop = Plug_FindProp(obj->ctx, pname);
|
|
if (prop)
|
|
{
|
|
success = true;
|
|
if (NPVARIANT_IS_STRING(*value))
|
|
{
|
|
char *t = NULL;
|
|
|
|
str = NPVARIANT_TO_STRING(*value);
|
|
if (str.utf8characters[str.utf8length] != 0)
|
|
{
|
|
t = malloc(str.utf8length+1);
|
|
memcpy(t, str.utf8characters, str.utf8length);
|
|
t[str.utf8length] = 0;
|
|
str.utf8characters = t;
|
|
}
|
|
Plug_SetString(ctx, prop, str.utf8characters);
|
|
if (t)
|
|
free(t);
|
|
}
|
|
else if (NPVARIANT_IS_INT32(*value))
|
|
Plug_SetInteger(ctx, prop, NPVARIANT_TO_INT32(*value));
|
|
else if (NPVARIANT_IS_BOOLEAN(*value))
|
|
Plug_SetInteger(ctx, prop, NPVARIANT_TO_BOOLEAN(*value));
|
|
else if (NPVARIANT_IS_DOUBLE(*value))
|
|
Plug_SetFloat(ctx, prop, NPVARIANT_TO_DOUBLE(*value));
|
|
else
|
|
success = false;
|
|
}
|
|
Plug_LockPlugin(ctx, false);
|
|
return success;
|
|
}
|
|
bool npscript_removeProperty(NPObject *npobj, NPIdentifier name)
|
|
{
|
|
return false;
|
|
}
|
|
bool npscript_enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)
|
|
{
|
|
return false;
|
|
}
|
|
bool npscript_construct(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
NPClass npscript_class =
|
|
{
|
|
NP_CLASS_STRUCT_VERSION,
|
|
|
|
npscript_allocate,
|
|
npscript_deallocate,
|
|
npscript_invalidate,
|
|
npscript_hasMethod,
|
|
npscript_invoke,
|
|
npscript_invokeDefault,
|
|
npscript_hasProperty,
|
|
npscript_getProperty,
|
|
npscript_setProperty,
|
|
npscript_removeProperty,
|
|
npscript_enumerate,
|
|
npscript_construct
|
|
};
|
|
|
|
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value)
|
|
{
|
|
switch(variable)
|
|
{
|
|
case NPPVpluginScriptableNPObject:
|
|
*(void**)value = browserfuncs->createobject(instance, &npscript_class);
|
|
return NPERR_NO_ERROR;
|
|
default:
|
|
return NPERR_INVALID_PARAM;
|
|
}
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value)
|
|
{
|
|
switch(variable)
|
|
{
|
|
default:
|
|
return NPERR_INVALID_PARAM;
|
|
}
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs)
|
|
{
|
|
browserfuncs = pFuncs;
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
NPError OSCALL NP_Shutdown(void)
|
|
{
|
|
/* if (contextlist)
|
|
{ //the browser isn't meant to call this when there's still instances left...
|
|
return NPERR_GENERIC_ERROR;
|
|
}
|
|
*/
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
NPError OSCALL NP_GetValue(void *instance, NPPVariable variable, void *value)
|
|
{
|
|
if (value == NULL)
|
|
return NPERR_INVALID_PARAM;
|
|
|
|
switch(variable)
|
|
{
|
|
case NPPVpluginNameString:
|
|
*(char**)value = "QTV Viewer";
|
|
break;
|
|
case NPPVpluginDescriptionString:
|
|
*(char**)value = "QTV Viewer";
|
|
break;
|
|
default:
|
|
return NPERR_INVALID_PARAM;
|
|
}
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
NPError OSCALL NP_GetEntryPoints (NPPluginFuncs* pFuncs)
|
|
{
|
|
if (pFuncs->size < sizeof(NPPluginFuncs))
|
|
return NPERR_INVALID_FUNCTABLE_ERROR;
|
|
pFuncs->size = sizeof(NPPluginFuncs);
|
|
|
|
pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
|
|
|
|
pFuncs->newp = NPP_New;
|
|
pFuncs->destroy = NPP_Destroy;
|
|
pFuncs->setwindow = NPP_SetWindow;
|
|
pFuncs->newstream = NPP_NewStream;
|
|
pFuncs->destroystream = NPP_DestroyStream;
|
|
pFuncs->asfile = NPP_StreamAsFile;
|
|
pFuncs->writeready = NPP_WriteReady;
|
|
pFuncs->write = NPP_Write;
|
|
pFuncs->print = NPP_Print;
|
|
pFuncs->event = NPP_HandleEvent;
|
|
pFuncs->urlnotify = NPP_URLNotify;
|
|
pFuncs->javaClass = NULL;
|
|
pFuncs->getvalue = NPP_GetValue;
|
|
pFuncs->setvalue = NPP_SetValue;
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
char *NP_GetMIMEDescription(void)
|
|
{
|
|
return "test/x-qtv:qtv:QTV Stream Description";
|
|
}
|