Imported existing code
This commit is contained in:
511
indra/test_apps/llplugintest/media_plugin_test.cpp
Normal file
511
indra/test_apps/llplugintest/media_plugin_test.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
/**
|
||||
* @file demo_plugin.cpp
|
||||
* @brief Test plugin to be loaded by the llplugin testbed.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "indra_constants.h"
|
||||
|
||||
#include "lltimer.h" // for ms_sleep()
|
||||
#include "llpumpio.h"
|
||||
#include "llapr.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llpluginclassmedia.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "llmediaplugintest.h" // for GLUT headers
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class mediaPluginTest : public LLPluginClassMediaOwner
|
||||
{
|
||||
private:
|
||||
int mAppWindowWidth;
|
||||
int mAppWindowHeight;
|
||||
LLPluginClassMedia* mMediaSource;
|
||||
int mAppTextureWidth;
|
||||
int mAppTextureHeight;
|
||||
bool mAppTextureCoordsOpenGL;
|
||||
GLuint mAppTexture;
|
||||
std::string mAppWindowName;
|
||||
std::string mHomeUrl;
|
||||
std::string mLauncherFilename;
|
||||
std::string mPluginFilename;
|
||||
|
||||
LLPluginClassMedia *mPlugin;
|
||||
|
||||
public:
|
||||
mediaPluginTest(const std::string &launcher_filename, const std::string &plugin_filename) :
|
||||
mAppWindowWidth( 800 ),
|
||||
mAppWindowHeight( 600 ),
|
||||
mAppTextureWidth( 0 ),
|
||||
mAppTextureHeight( 0 ),
|
||||
mAppTextureCoordsOpenGL(false),
|
||||
mAppTexture( 0 ),
|
||||
mAppWindowName( "Media Simple Test" ),
|
||||
mHomeUrl( "" )
|
||||
{
|
||||
mLauncherFilename = launcher_filename;
|
||||
mMediaSource = new LLPluginClassMedia(this);
|
||||
mMediaSource->init(launcher_filename, plugin_filename);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
virtual ~mediaPluginTest()
|
||||
{
|
||||
delete mMediaSource;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void createTexture()
|
||||
{
|
||||
// create the texture used to display the browser data
|
||||
if(mMediaSource->textureValid())
|
||||
{
|
||||
mAppTextureWidth = mMediaSource->getTextureWidth();
|
||||
mAppTextureHeight = mMediaSource->getTextureHeight();
|
||||
mAppTextureCoordsOpenGL = mMediaSource->getTextureCoordsOpenGL();
|
||||
|
||||
if(mAppTexture != 0)
|
||||
{
|
||||
glDeleteTextures( 1, &mAppTexture );
|
||||
mAppTexture = 0;
|
||||
}
|
||||
|
||||
glGenTextures( 1, &mAppTexture );
|
||||
glBindTexture( GL_TEXTURE_2D, mAppTexture );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0,
|
||||
mMediaSource->getTextureFormatInternal(),
|
||||
mAppTextureWidth,
|
||||
mAppTextureHeight,
|
||||
0,
|
||||
mMediaSource->getTextureFormatPrimary(),
|
||||
mMediaSource->getTextureFormatType(),
|
||||
NULL );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void initGL()
|
||||
{
|
||||
// OpenGL initialization
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 0.5f);
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
glEnable( GL_CULL_FACE );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void reshape( int width, int height )
|
||||
{
|
||||
if ( height == 0 )
|
||||
height = 1;
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
|
||||
glViewport( 0, 0, width, height );
|
||||
glOrtho( 0.0f, width, height, 0.0f, -1.0f, 1.0f );
|
||||
|
||||
// we use these values elsewhere so save
|
||||
mAppWindowWidth = width;
|
||||
mAppWindowHeight = height;
|
||||
|
||||
// Request a media size change
|
||||
mMediaSource->setSize(width, height);
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
glutPostRedisplay();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void idle()
|
||||
{
|
||||
// lots of updates for smooth motion
|
||||
glutPostRedisplay();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void display()
|
||||
{
|
||||
mMediaSource->idle();
|
||||
|
||||
// Check whether the texture needs to be recreated.
|
||||
if(mMediaSource->textureValid())
|
||||
{
|
||||
if(
|
||||
(mAppTextureWidth != mMediaSource->getTextureWidth() || mAppTextureHeight != mMediaSource->getTextureHeight()) &&
|
||||
(mAppWindowWidth == mMediaSource->getWidth() && mAppWindowHeight == mMediaSource->getHeight())
|
||||
)
|
||||
{
|
||||
// Attempt to (re)create the texture
|
||||
createTexture();
|
||||
}
|
||||
}
|
||||
|
||||
// clear screen
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
if(mAppTexture != 0)
|
||||
{
|
||||
// use the browser texture
|
||||
glBindTexture( GL_TEXTURE_2D, mAppTexture );
|
||||
|
||||
// If dirty, update the texture.
|
||||
LLRect dirtyRect;
|
||||
if(!mMediaSource->textureValid())
|
||||
{
|
||||
// LL_DEBUGS("media_plugin_test") << "Resize in progress, skipping update..." << LL_ENDL;
|
||||
}
|
||||
else if(mAppWindowWidth != mMediaSource->getWidth() || mAppWindowHeight != mMediaSource->getHeight())
|
||||
{
|
||||
// A resize is in progress. Just wait for it...
|
||||
}
|
||||
else if(mMediaSource->getDirty(&dirtyRect))
|
||||
{
|
||||
// grab the page
|
||||
const unsigned char* pixels = mMediaSource->getBitsData();
|
||||
if ( pixels )
|
||||
{
|
||||
// write them into the texture
|
||||
|
||||
// Paranoia: intersect dirtyRect with (0, 0, mAppTextureWidth, mAppTextureHeight)?
|
||||
|
||||
int x_offset = dirtyRect.mLeft;
|
||||
int y_offset = dirtyRect.mBottom;
|
||||
int width = dirtyRect.mRight - dirtyRect.mLeft;
|
||||
int height = dirtyRect.mTop - dirtyRect.mBottom;
|
||||
|
||||
LL_DEBUGS("media_plugin_test") << "Updating, dirty rect is ("
|
||||
<< dirtyRect.mLeft << ", "
|
||||
<< dirtyRect.mTop << ", "
|
||||
<< dirtyRect.mRight << ", "
|
||||
<< dirtyRect.mBottom << "), update params are: ("
|
||||
<< x_offset << ", "
|
||||
<< y_offset << ", "
|
||||
<< width << ", "
|
||||
<< height << ")"
|
||||
<< LL_ENDL;
|
||||
|
||||
// Offset the pixels pointer properly
|
||||
pixels += (y_offset * mMediaSource->getTextureDepth() * mMediaSource->getTextureWidth());
|
||||
pixels += (x_offset * mMediaSource->getTextureDepth());
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, mMediaSource->getTextureWidth());
|
||||
|
||||
glTexSubImage2D( GL_TEXTURE_2D, 0,
|
||||
x_offset,
|
||||
y_offset,
|
||||
width,
|
||||
height,
|
||||
mMediaSource->getTextureFormatPrimary(),
|
||||
mMediaSource->getTextureFormatType(),
|
||||
pixels );
|
||||
|
||||
mMediaSource->resetDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// scale the texture so that it fits the screen
|
||||
GLdouble media_texture_x = mAppWindowWidth / (double)mAppTextureWidth;
|
||||
GLdouble media_texture_y = mAppWindowHeight / (double)mAppTextureHeight;
|
||||
|
||||
// draw the single quad full screen (orthographic)
|
||||
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glColor3f( 1.0f, 1.0f, 1.0f );
|
||||
glBegin( GL_QUADS );
|
||||
if(mAppTextureCoordsOpenGL)
|
||||
{
|
||||
// Render the texture as per opengl coords (where 0,0 is at the lower left)
|
||||
glTexCoord2d( 0, 0 );
|
||||
glVertex2d( 0, 0 );
|
||||
|
||||
glTexCoord2d( 0 , media_texture_y );
|
||||
glVertex2d( 0, mAppWindowHeight);
|
||||
|
||||
glTexCoord2d( media_texture_x, media_texture_y );
|
||||
glVertex2d( mAppWindowWidth , mAppWindowHeight);
|
||||
|
||||
glTexCoord2d( media_texture_x, 0 );
|
||||
glVertex2d( mAppWindowWidth, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Render the texture the "other way round" (where 0,0 is at the upper left)
|
||||
glTexCoord2d( 0, media_texture_y );
|
||||
glVertex2d( 0, 0 );
|
||||
|
||||
glTexCoord2d( 0 , 0 );
|
||||
glVertex2d( 0, mAppWindowHeight);
|
||||
|
||||
glTexCoord2d( media_texture_x, 0 );
|
||||
glVertex2d( mAppWindowWidth , mAppWindowHeight);
|
||||
|
||||
glTexCoord2d( media_texture_x, media_texture_y );
|
||||
glVertex2d( mAppWindowWidth, 0 );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
glutSwapBuffers();
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
MASK getModifiers(void)
|
||||
{
|
||||
MASK result = 0;
|
||||
|
||||
int modifiers = glutGetModifiers();
|
||||
|
||||
if(modifiers & GLUT_ACTIVE_SHIFT)
|
||||
result |= MASK_SHIFT;
|
||||
if(modifiers & GLUT_ACTIVE_CTRL)
|
||||
result |= MASK_CONTROL;
|
||||
if(modifiers & GLUT_ACTIVE_ALT)
|
||||
result |= MASK_ALT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void mouseButton( int button, int state, int x, int y )
|
||||
{
|
||||
// Texture has been scaled so it's 1:1 with screen pixels, so no need to scale mouse coords here.
|
||||
// x = ( x * mAppTextureWidth ) / mAppWindowWidth;
|
||||
// y = ( y * mAppTextureHeight ) / mAppWindowHeight;
|
||||
|
||||
if ( button == GLUT_LEFT_BUTTON )
|
||||
{
|
||||
if ( state == GLUT_DOWN )
|
||||
mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, getModifiers());
|
||||
else if ( state == GLUT_UP )
|
||||
mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, getModifiers());
|
||||
}
|
||||
|
||||
// force a GLUT update
|
||||
glutPostRedisplay();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void mouseMove( int x , int y )
|
||||
{
|
||||
// Texture has been scaled so it's 1:1 with screen pixels, so no need to scale mouse coords here.
|
||||
// x = ( x * mAppTextureWidth ) / mAppWindowWidth;
|
||||
// y = ( y * mAppTextureHeight ) / mAppWindowHeight;
|
||||
|
||||
// GLUT complains if I get the keyboard modifiers here, so just pretend there aren't any.
|
||||
mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0);
|
||||
|
||||
// force a GLUT update
|
||||
glutPostRedisplay();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void keyboard( unsigned char key )
|
||||
{
|
||||
mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, getModifiers());
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int getAppWindowWidth()
|
||||
{
|
||||
return mAppWindowWidth;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int getAppWindowHeight()
|
||||
{
|
||||
return mAppWindowHeight;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
std::string getAppWindowName()
|
||||
{
|
||||
return mAppWindowName;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
mediaPluginTest* gApplication;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void glutReshape( int width, int height )
|
||||
{
|
||||
if ( gApplication )
|
||||
gApplication->reshape( width, height );
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void glutDisplay()
|
||||
{
|
||||
if ( gApplication )
|
||||
gApplication->display();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void glutIdle()
|
||||
{
|
||||
if ( gApplication )
|
||||
gApplication->idle();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void glutKeyboard( unsigned char key, int x, int y )
|
||||
{
|
||||
if ( key == 27 )
|
||||
{
|
||||
delete gApplication;
|
||||
exit( 0 );
|
||||
};
|
||||
|
||||
if ( gApplication )
|
||||
gApplication->keyboard( key );
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void glutMouseMove( int x, int y )
|
||||
{
|
||||
if ( gApplication )
|
||||
gApplication->mouseMove( x, y );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void glutMouseButton( int button, int state, int x, int y )
|
||||
{
|
||||
if ( gApplication )
|
||||
gApplication->mouseButton( button, state, x, y );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
|
||||
ll_init_apr();
|
||||
|
||||
// Set up llerror logging
|
||||
{
|
||||
LLError::initForApplication(".");
|
||||
LLError::setDefaultLevel(LLError::LEVEL_INFO);
|
||||
}
|
||||
|
||||
std::string launcher_name;
|
||||
std::string plugin_name;
|
||||
|
||||
if(argc >= 3)
|
||||
{
|
||||
launcher_name = argv[1];
|
||||
plugin_name = argv[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LL_DARWIN
|
||||
// hardcoding the testbed arguments by default
|
||||
launcher_name = "plugin_process_host";
|
||||
plugin_name = "libdemo_media_plugin_quicktime.dylib";
|
||||
#elif LL_WINDOWS
|
||||
// hardcoding the testbed arguments by default
|
||||
launcher_name = "plugin_process_host.exe";
|
||||
plugin_name = "demo_media_plugin_quicktime.dll";
|
||||
#else
|
||||
LL_ERRS("plugin_process_launcher") << "usage: " << argv[0] << " launcher_filename plugin_filename" << LL_ENDL;
|
||||
#endif
|
||||
}
|
||||
|
||||
gApplication = new mediaPluginTest(launcher_name, plugin_name);
|
||||
|
||||
if ( gApplication )
|
||||
{
|
||||
glutInit( &argc, argv );
|
||||
glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
|
||||
|
||||
glutInitWindowPosition( 80, 0 );
|
||||
glutInitWindowSize( gApplication->getAppWindowWidth(), gApplication->getAppWindowHeight() );
|
||||
|
||||
glutCreateWindow( gApplication->getAppWindowName().c_str() );
|
||||
|
||||
glutKeyboardFunc( glutKeyboard );
|
||||
|
||||
glutMouseFunc( glutMouseButton );
|
||||
glutPassiveMotionFunc( glutMouseMove );
|
||||
glutMotionFunc( glutMouseMove );
|
||||
|
||||
glutDisplayFunc( glutDisplay );
|
||||
glutReshapeFunc( glutReshape );
|
||||
|
||||
glutIdleFunc( glutIdle );
|
||||
|
||||
gApplication->initGL();
|
||||
|
||||
glutMainLoop();
|
||||
|
||||
delete gApplication;
|
||||
};
|
||||
|
||||
ll_cleanup_apr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user