Removed dependence on java interfaces and use only one surface for both embedded and fullscreen surfaces.

This commit is contained in:
Derek Sollenberger
2010-01-11 12:31:49 -05:00
parent a0e762caea
commit d53b56d180
14 changed files with 444 additions and 366 deletions

View File

@@ -6,7 +6,7 @@
redistribute this Apple software. redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these In consideration of your agreement to abide by the following terms, and subject to these
terms, Apple grants you a personal, non-exclusive license, under Apple<EFBFBD>s copyrights in terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in
this original Apple software (the "Apple Software"), to use, reproduce, modify and this original Apple software (the "Apple Software"), to use, reproduce, modify and
redistribute the Apple Software, with or without modifications, in source and/or binary redistribute the Apple Software, with or without modifications, in source and/or binary
forms; provided that if you redistribute the Apple Software in its entirety and without forms; provided that if you redistribute the Apple Software in its entirety and without
@@ -45,25 +45,28 @@ int SubPlugin::getPluginHeight() {
return obj->window->height; return obj->window->height;
} }
void SurfaceSubPlugin::setJavaInterface(jobject javaInterface) { bool SurfaceSubPlugin::supportsDrawingModel(ANPDrawingModel model) {
return (model == kSurface_ANPDrawingModel);
}
// if one exists then free its reference and notify the object that it is no void SurfaceSubPlugin::setContext(jobject context) {
// longer attached to the native instance
JNIEnv* env = NULL; JNIEnv* env = NULL;
if (m_javaInterface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { if (gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
// detach the native code from the object // if one exists then free its global reference
jclass javaClass = env->GetObjectClass(m_javaInterface); if (m_context) {
jmethodID invalMethod = env->GetMethodID(javaClass, "invalidateNPP", "()V"); env->DeleteGlobalRef(m_context);
env->CallVoidMethod(m_javaInterface, invalMethod); m_context = NULL;
}
// delete the reference // create a new global ref
env->DeleteGlobalRef(m_javaInterface); if (context) {
m_javaInterface = NULL; context = env->NewGlobalRef(context);
} }
// set the value // set the value
m_javaInterface = javaInterface; m_context = context;
}
} }
static void pluginInvalidate(NPObject *obj); static void pluginInvalidate(NPObject *obj);

View File

@@ -6,7 +6,7 @@
redistribute this Apple software. redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these In consideration of your agreement to abide by the following terms, and subject to these
terms, Apple grants you a personal, non-exclusive license, under Apple<6C>s copyrights in terms, Apple grants you a personal, non-exclusive license, under Apple<6C>s copyrights in
this original Apple software (the "Apple Software"), to use, reproduce, modify and this original Apple software (the "Apple Software"), to use, reproduce, modify and
redistribute the Apple Software, with or without modifications, in source and/or binary redistribute the Apple Software, with or without modifications, in source and/or binary
forms; provided that if you redistribute the Apple Software in its entirety and without forms; provided that if you redistribute the Apple Software in its entirety and without
@@ -37,6 +37,13 @@
#include "main.h" #include "main.h"
#include <jni.h> #include <jni.h>
enum CustomEventTypes {
kSurfaceCreated_CustomEvent = 0,
kSurfaceChanged_CustomEvent = 1,
kSurfaceDestroyed_CustomEvent = 2,
};
typedef int32_t CustomEventType;
class SubPlugin { class SubPlugin {
public: public:
SubPlugin(NPP inst) : m_inst(inst) {} SubPlugin(NPP inst) : m_inst(inst) {}
@@ -55,16 +62,14 @@ private:
class SurfaceSubPlugin : public SubPlugin { class SurfaceSubPlugin : public SubPlugin {
public: public:
SurfaceSubPlugin(NPP inst) : SubPlugin(inst) {} SurfaceSubPlugin(NPP inst) : SubPlugin(inst) { m_context = NULL; }
virtual ~SurfaceSubPlugin() {} virtual ~SurfaceSubPlugin() {}
virtual bool isFixedSurface() = 0; virtual jobject getSurface() = 0;
virtual void surfaceCreated(jobject) = 0; virtual bool supportsDrawingModel(ANPDrawingModel);
virtual void surfaceChanged(int format, int width, int height) = 0;
virtual void surfaceDestroyed() = 0;
void setJavaInterface(jobject); void setContext(jobject context);
jobject m_javaInterface; jobject m_context;
}; };
enum PluginTypes { enum PluginTypes {

View File

@@ -54,9 +54,6 @@ static uint32_t getMSecs() {
BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) { BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) {
// initialize the java interface
m_javaInterface = NULL;
// initialize the drawing surface // initialize the drawing surface
m_surface = NULL; m_surface = NULL;
@@ -82,27 +79,44 @@ BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) {
} }
BackgroundPlugin::~BackgroundPlugin() { BackgroundPlugin::~BackgroundPlugin() {
setJavaInterface(NULL); setContext(NULL);
surfaceDestroyed(); destroySurface();
} }
bool BackgroundPlugin::supportsDrawingModel(ANPDrawingModel model) { jobject BackgroundPlugin::getSurface() {
return (model == kSurface_ANPDrawingModel);
if (m_surface) {
return m_surface;
} }
bool BackgroundPlugin::isFixedSurface() { // load the appropriate java class and instantiate it
return false; JNIEnv* env = NULL;
if (gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to get env");
return NULL;
} }
void BackgroundPlugin::surfaceCreated(jobject surface) { const char* className = "com.android.sampleplugin.BackgroundSurface";
m_surface = surface; jclass backgroundClass = gSystemI.loadJavaClass(inst(), className);
if(!backgroundClass) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to load class");
return NULL;
} }
void BackgroundPlugin::surfaceChanged(int format, int width, int height) { jmethodID constructor = env->GetMethodID(backgroundClass, "<init>", "(Landroid/content/Context;)V");
drawPlugin(width, height); jobject backgroundSurface = env->NewObject(backgroundClass, constructor, m_context);
if(!backgroundSurface) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to construct object");
return NULL;
} }
void BackgroundPlugin::surfaceDestroyed() { m_surface = env->NewGlobalRef(backgroundSurface);
return m_surface;
}
void BackgroundPlugin::destroySurface() {
JNIEnv* env = NULL; JNIEnv* env = NULL;
if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
env->DeleteGlobalRef(m_surface); env->DeleteGlobalRef(m_surface);
@@ -179,8 +193,10 @@ int16 BackgroundPlugin::handleEvent(const ANPEvent* evt) {
case kTouch_ANPEventType: case kTouch_ANPEventType:
if (kDown_ANPTouchAction == evt->data.touch.action) if (kDown_ANPTouchAction == evt->data.touch.action)
return kHandleLongPress_ANPTouchResult | kHandleDoubleTap_ANPTouchResult; return kHandleLongPress_ANPTouchResult | kHandleDoubleTap_ANPTouchResult;
else if (kLongPress_ANPTouchAction == evt->data.touch.action) else if (kLongPress_ANPTouchAction == evt->data.touch.action) {
browser->geturl(inst(), "javascript:alert('Detected long press event.')", 0); browser->geturl(inst(), "javascript:alert('Detected long press event.')", 0);
gWindowI.requestFullScreen(inst());
}
else if (kDoubleTap_ANPTouchAction == evt->data.touch.action) else if (kDoubleTap_ANPTouchAction == evt->data.touch.action)
browser->geturl(inst(), "javascript:alert('Detected double tap event.')", 0); browser->geturl(inst(), "javascript:alert('Detected double tap event.')", 0);
break; break;

View File

@@ -32,12 +32,8 @@ class BackgroundPlugin : public SurfaceSubPlugin {
public: public:
BackgroundPlugin(NPP inst); BackgroundPlugin(NPP inst);
virtual ~BackgroundPlugin(); virtual ~BackgroundPlugin();
virtual bool supportsDrawingModel(ANPDrawingModel);
virtual int16 handleEvent(const ANPEvent* evt); virtual int16 handleEvent(const ANPEvent* evt);
virtual void surfaceCreated(jobject surface); virtual jobject getSurface();
virtual void surfaceChanged(int format, int width, int height);
virtual void surfaceDestroyed();
virtual bool isFixedSurface();
// Timer Testing Variables // Timer Testing Variables
uint32_t mStartTime; uint32_t mStartTime;
@@ -53,6 +49,7 @@ public:
private: private:
void drawPlugin(int surfaceWidth, int surfaceHeight); void drawPlugin(int surfaceWidth, int surfaceHeight);
void destroySurface();
jobject m_surface; jobject m_surface;

View File

@@ -23,72 +23,48 @@
#define EXPORT __attribute__((visibility("default"))) #define EXPORT __attribute__((visibility("default")))
static SurfaceSubPlugin* getPluginObject(int npp) { extern ANPEventInterfaceV0 gEventI;
NPP instance = (NPP)npp;
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
if (obj && obj->activePlugin
&& obj->activePlugin->supportsDrawingModel(kSurface_ANPDrawingModel)) {
return static_cast<SurfaceSubPlugin*>(obj->activePlugin);
}
return NULL;
}
static jboolean javaInit(JNIEnv* env, jobject thiz, jint npp) {
SurfaceSubPlugin* obj = getPluginObject(npp);
if (obj) {
jobject globalObject = env->NewGlobalRef(thiz);
obj->setJavaInterface(globalObject);
return true;
} else {
return false;
}
}
static void surfaceCreated(JNIEnv* env, jobject thiz, jint npp, jobject surface) { static void surfaceCreated(JNIEnv* env, jobject thiz, jint npp, jobject surface) {
SurfaceSubPlugin* obj = getPluginObject(npp);
jobject globalSurface = env->NewGlobalRef(surface); // send custom event
obj->surfaceCreated(globalSurface); ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kCustom_ANPEventType;
event.data.other[0] = kSurfaceCreated_CustomEvent;
gEventI.postEvent((NPP)npp, &event);
} }
static void surfaceChanged(JNIEnv* env, jobject thiz, jint npp, jint format, jint width, jint height) { static void surfaceChanged(JNIEnv* env, jobject thiz, jint npp, jint format, jint width, jint height) {
SurfaceSubPlugin* obj = getPluginObject(npp); // send custom event
obj->surfaceChanged(format, width, height); ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kCustom_ANPEventType;
event.data.other[0] = kSurfaceChanged_CustomEvent;
event.data.other[1] = width;
event.data.other[2] = height;
gEventI.postEvent((NPP)npp, &event);
} }
static void surfaceDestroyed(JNIEnv* env, jobject thiz, jint npp) { static void surfaceDestroyed(JNIEnv* env, jobject thiz, jint npp) {
SurfaceSubPlugin* obj = getPluginObject(npp); // send custom event
if (obj) { ANPEvent event;
obj->surfaceDestroyed(); event.inSize = sizeof(ANPEvent);
} event.eventType = kCustom_ANPEventType;
} event.data.other[0] = kSurfaceDestroyed_CustomEvent;
static jint getSurfaceWidth(JNIEnv* env, jobject thiz, jint npp) { gEventI.postEvent((NPP)npp, &event);
SurfaceSubPlugin* obj = getPluginObject(npp);
return obj->getPluginWidth();
}
static jint getSurfaceHeight(JNIEnv* env, jobject thiz, jint npp) {
SurfaceSubPlugin* obj = getPluginObject(npp);
return obj->getPluginHeight();
}
static jboolean isFixedSurface(JNIEnv* env, jobject thiz, jint npp) {
SurfaceSubPlugin* obj = getPluginObject(npp);
return obj->isFixedSurface();
} }
/* /*
* JNI registration. * JNI registration.
*/ */
static JNINativeMethod gJavaSamplePluginMethods[] = { static JNINativeMethod gPaintSurfaceMethods[] = {
{ "nativeJavaInit", "(I)Z", (void*) javaInit }, { "nativeSurfaceCreated", "(I)V", (void*) surfaceCreated },
{ "nativeSurfaceCreated", "(ILandroid/view/View;)V", (void*) surfaceCreated },
{ "nativeSurfaceChanged", "(IIII)V", (void*) surfaceChanged }, { "nativeSurfaceChanged", "(IIII)V", (void*) surfaceChanged },
{ "nativeSurfaceDestroyed", "(I)V", (void*) surfaceDestroyed }, { "nativeSurfaceDestroyed", "(I)V", (void*) surfaceDestroyed },
{ "nativeGetSurfaceWidth", "(I)I", (void*) getSurfaceWidth },
{ "nativeGetSurfaceHeight", "(I)I", (void*) getSurfaceHeight },
{ "nativeIsFixedSurface", "(I)Z", (void*) isFixedSurface },
}; };
EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
@@ -99,8 +75,8 @@ EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return -1; return -1;
} }
jniRegisterNativeMethods(env, "com/android/sampleplugin/SamplePlugin", jniRegisterNativeMethods(env, "com/android/sampleplugin/PaintSurface",
gJavaSamplePluginMethods, NELEM(gJavaSamplePluginMethods)); gPaintSurfaceMethods, NELEM(gPaintSurfaceMethods));
return JNI_VERSION_1_4; return JNI_VERSION_1_4;
} }

View File

@@ -68,6 +68,7 @@ EXPORT void NP_Shutdown(void);
ANPAudioTrackInterfaceV0 gSoundI; ANPAudioTrackInterfaceV0 gSoundI;
ANPBitmapInterfaceV0 gBitmapI; ANPBitmapInterfaceV0 gBitmapI;
ANPCanvasInterfaceV0 gCanvasI; ANPCanvasInterfaceV0 gCanvasI;
ANPEventInterfaceV0 gEventI;
ANPLogInterfaceV0 gLogI; ANPLogInterfaceV0 gLogI;
ANPPaintInterfaceV0 gPaintI; ANPPaintInterfaceV0 gPaintI;
ANPPathInterfaceV0 gPathI; ANPPathInterfaceV0 gPathI;
@@ -115,6 +116,7 @@ NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs,
{ kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI }, { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI },
{ kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI }, { kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI },
{ kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI }, { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI },
{ kEventInterfaceV0_ANPGetValue, sizeof(gEventI), &gEventI },
{ kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI }, { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI },
{ kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI }, { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI },
{ kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI }, { kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI },
@@ -239,6 +241,22 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }
// if the plugin uses the surface drawing model then set the java context
if (model == kSurface_ANPDrawingModel) {
SurfaceSubPlugin* surfacePlugin = static_cast<SurfaceSubPlugin*>(obj->activePlugin);
jobject context;
NPError err = browser->getvalue(instance, kJavaContext_ANPGetValue,
static_cast<void*>(&context));
if (err) {
gLogI.log(kError_ANPLogType, "request context err: %d", err);
return err;
}
surfacePlugin->setContext(context);
}
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
@@ -406,6 +424,24 @@ NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
if (variable == kJavaSurface_ANPGetValue) {
//get the surface sub-plugin
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
if (obj && obj->activePlugin) {
if(obj->activePlugin->supportsDrawingModel(kSurface_ANPDrawingModel)) {
SurfaceSubPlugin* plugin = static_cast<SurfaceSubPlugin*>(obj->activePlugin);
jobject* surface = static_cast<jobject*>(value);
*surface = plugin->getSurface();
return NPERR_NO_ERROR;
} else {
gLogI.log(kError_ANPLogType,
"-- %p Tried to retrieve surface for non-surface plugin",
instance);
}
}
}
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }

View File

@@ -35,6 +35,7 @@ extern ANPCanvasInterfaceV0 gCanvasI;
extern ANPPaintInterfaceV0 gPaintI; extern ANPPaintInterfaceV0 gPaintI;
extern ANPPathInterfaceV0 gPathI; extern ANPPathInterfaceV0 gPathI;
extern ANPSurfaceInterfaceV0 gSurfaceI; extern ANPSurfaceInterfaceV0 gSurfaceI;
extern ANPSystemInterfaceV0 gSystemI;
extern ANPTypefaceInterfaceV0 gTypefaceI; extern ANPTypefaceInterfaceV0 gTypefaceI;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -50,9 +51,6 @@ PaintPlugin::PaintPlugin(NPP inst) : SurfaceSubPlugin(inst) {
memset(&m_colorToggle, 0, sizeof(m_colorToggle)); memset(&m_colorToggle, 0, sizeof(m_colorToggle));
memset(&m_clearSurface, 0, sizeof(m_clearSurface)); memset(&m_clearSurface, 0, sizeof(m_clearSurface));
// initialize the java interface
m_javaInterface = NULL;
// initialize the drawing surface // initialize the drawing surface
m_surface = NULL; m_surface = NULL;
@@ -88,12 +86,9 @@ PaintPlugin::~PaintPlugin() {
gPathI.deletePath(m_touchPath); gPathI.deletePath(m_touchPath);
gPaintI.deletePaint(m_paintSurface); gPaintI.deletePaint(m_paintSurface);
gPaintI.deletePaint(m_paintButton); gPaintI.deletePaint(m_paintButton);
setJavaInterface(NULL);
surfaceDestroyed();
}
bool PaintPlugin::supportsDrawingModel(ANPDrawingModel model) { setContext(NULL);
return (model == kSurface_ANPDrawingModel); destroySurface();
} }
ANPCanvas* PaintPlugin::getCanvas(ANPRectI* dirtyRect) { ANPCanvas* PaintPlugin::getCanvas(ANPRectI* dirtyRect) {
@@ -215,29 +210,51 @@ const char* PaintPlugin::getColorText() {
return "Red"; return "Red";
} }
bool PaintPlugin::isFixedSurface() { jobject PaintPlugin::getSurface() {
return true; if (m_surface) {
return m_surface;
} }
void PaintPlugin::surfaceCreated(jobject surface) { // load the appropriate java class and instantiate it
m_surface = surface; JNIEnv* env = NULL;
drawCleanPlugin(); if (gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to get env");
return NULL;
}
const char* className = "com.android.sampleplugin.PaintSurface";
jclass paintClass = gSystemI.loadJavaClass(inst(), className);
if(!paintClass) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to load class");
return NULL;
} }
void PaintPlugin::surfaceChanged(int format, int width, int height) {
// get the plugin's dimensions according to the DOM
PluginObject *obj = (PluginObject*) inst()->pdata; PluginObject *obj = (PluginObject*) inst()->pdata;
const int pW = obj->window->width; const int pW = obj->window->width;
const int pH = obj->window->height; const int pH = obj->window->height;
// compare to the plugin's surface dimensions
if (pW != width || pH != height) jmethodID constructor = env->GetMethodID(paintClass, "<init>", "(Landroid/content/Context;III)V");
gLogI.log(kError_ANPLogType, jobject paintSurface = env->NewObject(paintClass, constructor, m_context, (int)inst(), pW, pH);
"----%p Invalid Surface Dimensions (%d,%d):(%d,%d)",
inst(), pW, pH, width, height); if(!paintSurface) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to construct object");
return NULL;
} }
void PaintPlugin::surfaceDestroyed() {
m_surface = env->NewGlobalRef(paintSurface);
return m_surface;
}
void PaintPlugin::destroySurface() {
JNIEnv* env = NULL; JNIEnv* env = NULL;
if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
// detach the native code from the object
jclass javaClass = env->GetObjectClass(m_surface);
jmethodID invalMethod = env->GetMethodID(javaClass, "invalidateNPP", "()V");
env->CallVoidMethod(m_surface, invalMethod);
env->DeleteGlobalRef(m_surface); env->DeleteGlobalRef(m_surface);
m_surface = NULL; m_surface = NULL;
} }
@@ -294,6 +311,35 @@ int16 PaintPlugin::handleEvent(const ANPEvent* evt) {
} }
return 1; return 1;
} }
case kCustom_ANPEventType: {
switch (evt->data.other[0]) {
case kSurfaceCreated_CustomEvent:
gLogI.log(kDebug_ANPLogType, " ---- customEvent: surfaceCreated");
drawCleanPlugin();
break;
case kSurfaceChanged_CustomEvent: {
gLogI.log(kDebug_ANPLogType, " ---- customEvent: surfaceChanged");
int width = evt->data.other[1];
int height = evt->data.other[2];
PluginObject *obj = (PluginObject*) inst()->pdata;
const int pW = obj->window->width;
const int pH = obj->window->height;
// compare to the plugin's surface dimensions
if (pW != width || pH != height)
gLogI.log(kError_ANPLogType,
"----%p Invalid Surface Dimensions (%d,%d):(%d,%d)",
inst(), pW, pH, width, height);
break;
}
case kSurfaceDestroyed_CustomEvent:
gLogI.log(kDebug_ANPLogType, " ---- customEvent: surfaceDestroyed");
break;
}
break; // end KCustom_ANPEventType
}
default: default:
break; break;
} }

View File

@@ -33,18 +33,15 @@ class PaintPlugin : public SurfaceSubPlugin {
public: public:
PaintPlugin(NPP inst); PaintPlugin(NPP inst);
virtual ~PaintPlugin(); virtual ~PaintPlugin();
virtual bool supportsDrawingModel(ANPDrawingModel);
virtual int16 handleEvent(const ANPEvent* evt); virtual int16 handleEvent(const ANPEvent* evt);
virtual void surfaceCreated(jobject surface); virtual jobject getSurface();
virtual void surfaceChanged(int format, int width, int height);
virtual void surfaceDestroyed();
virtual bool isFixedSurface();
private: private:
void drawCleanPlugin(ANPCanvas* canvas = NULL); void drawCleanPlugin(ANPCanvas* canvas = NULL);
ANPCanvas* getCanvas(ANPRectI* dirtyRect = NULL); ANPCanvas* getCanvas(ANPRectI* dirtyRect = NULL);
ANPCanvas* getCanvas(ANPRectF* dirtyRect); ANPCanvas* getCanvas(ANPRectF* dirtyRect);
const char* getColorText(); const char* getColorText();
void destroySurface();
void paintMouse(int x, int y); void paintMouse(int x, int y);
void paintTouch(); void paintTouch();
void releaseCanvas(ANPCanvas*); void releaseCanvas(ANPCanvas*);

View File

@@ -38,6 +38,7 @@ extern ANPCanvasInterfaceV0 gCanvasI;
extern ANPLogInterfaceV0 gLogI; extern ANPLogInterfaceV0 gLogI;
extern ANPPaintInterfaceV0 gPaintI; extern ANPPaintInterfaceV0 gPaintI;
extern ANPSurfaceInterfaceV0 gSurfaceI; extern ANPSurfaceInterfaceV0 gSurfaceI;
extern ANPSystemInterfaceV0 gSystemI;
extern ANPTypefaceInterfaceV0 gTypefaceI; extern ANPTypefaceInterfaceV0 gTypefaceI;
extern ANPWindowInterfaceV0 gWindowI; extern ANPWindowInterfaceV0 gWindowI;
@@ -45,9 +46,6 @@ extern ANPWindowInterfaceV0 gWindowI;
VideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) { VideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) {
// initialize the java interface
m_javaInterface = NULL;
// initialize the drawing surface // initialize the drawing surface
m_surface = NULL; m_surface = NULL;
@@ -60,30 +58,44 @@ VideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) {
} }
VideoPlugin::~VideoPlugin() { VideoPlugin::~VideoPlugin() {
setJavaInterface(NULL); setContext(NULL);
surfaceDestroyed(); destroySurface();
} }
bool VideoPlugin::supportsDrawingModel(ANPDrawingModel model) { jobject VideoPlugin::getSurface() {
return (model == kSurface_ANPDrawingModel);
if (m_surface) {
return m_surface;
} }
bool VideoPlugin::isFixedSurface() { // load the appropriate java class and instantiate it
return true; JNIEnv* env = NULL;
if (gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to get env");
return NULL;
} }
void VideoPlugin::surfaceCreated(jobject surface) { const char* className = "com.android.sampleplugin.VideoSurface";
m_surface = surface; jclass videoClass = gSystemI.loadJavaClass(inst(), className);
drawPlugin();
if(!videoClass) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to load class");
return NULL;
} }
void VideoPlugin::surfaceChanged(int format, int width, int height) { jmethodID constructor = env->GetMethodID(videoClass, "<init>", "(Landroid/content/Context;)V");
gLogI.log(kDebug_ANPLogType, "----%p SurfaceChanged Event: %d", jobject videoSurface = env->NewObject(videoClass, constructor, m_context);
inst(), format);
drawPlugin(); if(!videoSurface) {
gLogI.log(kError_ANPLogType, " ---- getSurface: failed to construct object");
return NULL;
} }
void VideoPlugin::surfaceDestroyed() { m_surface = env->NewGlobalRef(videoSurface);
return m_surface;
}
void VideoPlugin::destroySurface() {
JNIEnv* env = NULL; JNIEnv* env = NULL;
if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { if (m_surface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
env->DeleteGlobalRef(m_surface); env->DeleteGlobalRef(m_surface);
@@ -91,59 +103,19 @@ void VideoPlugin::surfaceDestroyed() {
} }
} }
void VideoPlugin::drawPlugin() {
ANPBitmap bitmap;
JNIEnv* env = NULL;
if (!m_surface || gVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK ||
!gSurfaceI.lock(env, m_surface, &bitmap, NULL)) {
gLogI.log(kError_ANPLogType, "----%p Unable to Lock Surface", inst());
return;
}
ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
// get the plugin's dimensions according to the DOM
PluginObject *obj = (PluginObject*) inst()->pdata;
const int pW = obj->window->width;
const int pH = obj->window->height;
// compare DOM dimensions to the plugin's surface dimensions
if (pW != bitmap.width || pH != bitmap.height)
gLogI.log(kError_ANPLogType,
"----%p Invalid Surface Dimensions (%d,%d):(%d,%d)",
inst(), pW, pH, bitmap.width, bitmap.height);
// set constants
const int fontSize = 16;
const int leftMargin = 10;
gCanvasI.drawColor(canvas, 0xFFCDCDCD);
ANPPaint* paint = gPaintI.newPaint();
gPaintI.setFlags(paint, gPaintI.getFlags(paint) | kAntiAlias_ANPPaintFlag);
gPaintI.setColor(paint, 0xFFFF0000);
gPaintI.setTextSize(paint, fontSize);
ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
gPaintI.setTypeface(paint, tf);
gTypefaceI.unref(tf);
ANPFontMetrics fm;
gPaintI.getFontMetrics(paint, &fm);
gPaintI.setColor(paint, 0xFF0000FF);
const char c[] = "Touch anywhere on the plugin to begin video playback!";
gCanvasI.drawText(canvas, c, sizeof(c)-1, leftMargin, -fm.fTop, paint);
// clean up variables and unlock the surface
gPaintI.deletePaint(paint);
gCanvasI.deleteCanvas(canvas);
gSurfaceI.unlock(env, m_surface);
}
int16 VideoPlugin::handleEvent(const ANPEvent* evt) { int16 VideoPlugin::handleEvent(const ANPEvent* evt) {
switch (evt->eventType) { switch (evt->eventType) {
case kLifecycle_ANPEventType: {
switch (evt->data.lifecycle.action) {
case kEnterFullScreen_ANPLifecycleAction:
gLogI.log(kDebug_ANPLogType, " ---- %p entering fullscreen", inst());
break;
case kExitFullScreen_ANPLifecycleAction:
gLogI.log(kDebug_ANPLogType, " ---- %p exiting fullscreen", inst());
break;
}
break; // end kLifecycle_ANPEventType
}
case kDraw_ANPEventType: case kDraw_ANPEventType:
gLogI.log(kError_ANPLogType, " ------ %p the plugin did not request draw events", inst()); gLogI.log(kError_ANPLogType, " ------ %p the plugin did not request draw events", inst());
break; break;

View File

@@ -32,15 +32,11 @@ class VideoPlugin : public SurfaceSubPlugin {
public: public:
VideoPlugin(NPP inst); VideoPlugin(NPP inst);
virtual ~VideoPlugin(); virtual ~VideoPlugin();
virtual bool supportsDrawingModel(ANPDrawingModel);
virtual int16 handleEvent(const ANPEvent* evt); virtual int16 handleEvent(const ANPEvent* evt);
virtual void surfaceCreated(jobject surface); virtual jobject getSurface();
virtual void surfaceChanged(int format, int width, int height);
virtual void surfaceDestroyed();
virtual bool isFixedSurface();
private: private:
void drawPlugin(); void destroySurface();
jobject m_surface; jobject m_surface;
}; };

View File

@@ -0,0 +1,19 @@
package com.android.sampleplugin;
import android.content.Context;
import android.graphics.Color;
import android.widget.TextView;
public class BackgroundSurface extends TextView {
public BackgroundSurface(Context context) {
super(context);
this.setBackgroundColor(Color.BLACK);
this.setTextColor(Color.WHITE);
this.setText("This is a java background plugin");
// ensure that the view system is aware that we will be drawing
this.setWillNotDraw(false);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2009, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.android.sampleplugin;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
public class PaintSurface extends SurfaceView {
static {
//needed for jni calls
System.loadLibrary("sampleplugin");
}
private final int npp;
private boolean validNPP = true;
private Object nppLock = new Object();
public PaintSurface(Context context, int NPP, int width, int height) {
super(context);
this.npp = NPP;
this.getHolder().setFormat(PixelFormat.RGBA_8888);
this.getHolder().addCallback(new Callback() {
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceChanged(npp, format, width, height);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceCreated(npp);
}
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceDestroyed(npp);
}
}
}
});
// sets the plugin's surface to a fixed size
this.getHolder().setFixedSize(width, height);
// ensure that the view system is aware that we will be drawing
this.setWillNotDraw(false);
}
// called by JNI
private void invalidateNPP() {
synchronized (nppLock) {
validNPP = false;
}
}
private native void nativeSurfaceCreated(int npp);
private native void nativeSurfaceChanged(int npp, int format, int width, int height);
private native void nativeSurfaceDestroyed(int npp);
}

View File

@@ -24,161 +24,14 @@
*/ */
package com.android.sampleplugin; package com.android.sampleplugin;
import com.android.sampleplugin.graphics.CubeRenderer; import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.content.Context; public class SamplePlugin extends Service {
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.view.ViewGroup.LayoutParams;
import android.webkit.plugin.NativePlugin;
import android.webkit.plugin.SurfaceDrawingModel;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.widget.VideoView;
public class SamplePlugin implements NativePlugin { @Override
public IBinder onBind(Intent intent) {
static { // TODO Auto-generated method stub
//needed for jni calls return null;
System.loadLibrary("sampleplugin"); }}
}
private int npp;
private Context context;
private SurfaceDrawingModel embeddedSurface;
private SurfaceDrawingModel fullScreenSurface;
private boolean validNPP = false;
private Object nppLock = new Object();
public void initializePlugin(int npp, Context context) {
this.npp = npp;
this.context = context;
this.validNPP = nativeJavaInit(npp);
}
public SurfaceDrawingModel getEmbeddedSurface() {
if (embeddedSurface == null) {
embeddedSurface = new EmbeddedSurface();
}
return embeddedSurface;
}
public SurfaceDrawingModel getFullScreenSurface() {
if (fullScreenSurface == null) {
fullScreenSurface = new FullScreenSurface();
}
return fullScreenSurface;
}
// called by JNI
private void invalidateNPP() {
synchronized (nppLock) {
validNPP = false;
}
}
private native boolean nativeJavaInit(int npp);
private native void nativeSurfaceCreated(int npp, View surfaceView);
private native void nativeSurfaceChanged(int npp, int format, int width, int height);
private native void nativeSurfaceDestroyed(int npp);
private native int nativeGetSurfaceWidth(int npp);
private native int nativeGetSurfaceHeight(int npp);
private native boolean nativeIsFixedSurface(int npp);
private class EmbeddedSurface implements SurfaceDrawingModel {
public View getSurface() {
final SurfaceView view = new SurfaceView(context);
/* You can do all sorts of interesting operations on the surface view
* here. We illustrate a few of the important operations below.
*/
//TODO get pixel format from the subplugin (via jni)
view.getHolder().setFormat(PixelFormat.RGBA_8888);
view.getHolder().addCallback(new Callback() {
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceChanged(npp, format, width, height);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceCreated(npp, view);
}
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceDestroyed(npp);
}
}
}
});
// TODO provide way for native plugin code to reset the size
if (nativeIsFixedSurface(npp)) {
int width = nativeGetSurfaceWidth(npp);
int height = nativeGetSurfaceHeight(npp);
view.getHolder().setFixedSize(width, height);
}
// ensure that the view system is aware that we will be drawing
view.setWillNotDraw(false);
return view;
}
}
private class FullScreenSurface implements SurfaceDrawingModel {
public View getSurface() {
/* TODO make this aware of the plugin instance and get the video file
* from the plugin.
*/
FrameLayout layout = new FrameLayout(context);
LayoutParams fp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
layout.setLayoutParams(fp);
// VideoView video = new VideoView(context);
// LayoutParams vp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
// layout.setLayoutParams(vp);
GLSurfaceView gl = new GLSurfaceView(context);
LayoutParams gp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
layout.setLayoutParams(gp);
layout.addView(gl);
// layout.addView(video);
// Tell the cube renderer that we want to render a translucent version
// of the cube:
gl.setRenderer(new CubeRenderer(false));
gl.setWindowType(WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY);
// video.setVideoPath("/sdcard/test_video.3gp");
// video.setMediaController(new MediaController(context));
// video.requestFocus();
// ensure that the view system is aware that we will be drawing
layout.setWillNotDraw(false);
return layout;
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2009, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.android.sampleplugin;
import com.android.sampleplugin.graphics.CubeRenderer;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.widget.VideoView;
public class VideoSurface extends FrameLayout {
public VideoSurface(Context context) {
super(context);
LayoutParams fp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
this.setLayoutParams(fp);
// VideoView video = new VideoView(context);
// LayoutParams vp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
// vp.setLayoutParams(vp);
GLSurfaceView gl = new GLSurfaceView(context);
LayoutParams gp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
gl.setLayoutParams(gp);
this.addView(gl);
// this.addView(video);
// Tell the cube renderer that we want to render a translucent version
// of the cube:
gl.setRenderer(new CubeRenderer(false));
gl.setWindowType(WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY);
// video.setVideoPath("/sdcard/test_video.3gp");
// video.setMediaController(new MediaController(context));
// video.requestFocus();
// ensure that the view system is aware that we will be drawing
this.setWillNotDraw(false);
}
}