From ab9e83030671f0d309eada847af7055213dfe501 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 24 Mar 2015 00:42:42 +0100 Subject: Refer to new QuickTime third party package with fixes for VS2013 & re-add QuickTime media plugin --- indra/media_plugins/CMakeLists.txt | 8 +++++--- indra/media_plugins/quicktime/CMakeLists.txt | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 85318aea3b..956e8fe890 100755 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -2,9 +2,11 @@ add_subdirectory(base) -add_subdirectory(webkit) +### add_subdirectory(webkit) -add_subdirectory(gstreamer010) +if (LINUX) + add_subdirectory(gstreamer010) +endif (LINUX) if (WINDOWS OR DARWIN) add_subdirectory(quicktime) @@ -14,4 +16,4 @@ if (WINDOWS) add_subdirectory(winmmshim) endif (WINDOWS) -add_subdirectory(example) +### add_subdirectory(example) diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt index 58391007ff..d7a1874bf3 100755 --- a/indra/media_plugins/quicktime/CMakeLists.txt +++ b/indra/media_plugins/quicktime/CMakeLists.txt @@ -63,7 +63,8 @@ if (WINDOWS) set_target_properties( media_plugin_quicktime PROPERTIES - LINK_FLAGS "/MANIFEST:NO" + LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD" ) endif (WINDOWS) -- cgit v1.2.3 From dbdef626d650de288697848977155e223cbba9ad Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 24 Mar 2015 17:22:58 -0700 Subject: Add new media plugin (currently renders squares as example) in preparation for new CEF code --- indra/media_plugins/CMakeLists.txt | 4 +- indra/media_plugins/cef/CMakeLists.txt | 86 ++++++ indra/media_plugins/cef/media_plugin_cef.cpp | 413 +++++++++++++++++++++++++++ 3 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 indra/media_plugins/cef/CMakeLists.txt create mode 100644 indra/media_plugins/cef/media_plugin_cef.cpp (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 956e8fe890..0e0f84d1fd 100755 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -2,7 +2,9 @@ add_subdirectory(base) -### add_subdirectory(webkit) +if (WINDOWS) + add_subdirectory(cef) +endif (WINDOWS) if (LINUX) add_subdirectory(gstreamer010) diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt new file mode 100644 index 0000000000..663303f0eb --- /dev/null +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -0,0 +1,86 @@ +# -*- cmake -*- + +project(media_plugin_cef) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(OpenGL) + +include(CEFPlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ) + + +### media_plugin_cef + +if(NOT WORD_SIZE EQUAL 32) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif(NOT WORD_SIZE EQUAL 32) + +set(media_plugin_cef_SOURCE_FILES + media_plugin_cef.cpp + ) + +add_library(media_plugin_cef + SHARED + ${media_plugin_cef_SOURCE_FILES} +) + +target_link_libraries(media_plugin_cef + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${CEF_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_cef + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + media_plugin_cef + PROPERTIES + LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD" + ) +endif (WINDOWS) + +if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_cef + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + +endif (DARWIN) diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp new file mode 100644 index 0000000000..ada297373a --- /dev/null +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -0,0 +1,413 @@ +/** + * @file media_plugin_cef.cpp + * @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system + * + * @cond + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * 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; + * version 2.1 of the License only. + * + * 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 + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#include "linden_common.h" + +#include "llgl.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginCEF : + public MediaPluginBase +{ + public: + MediaPluginCEF( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); + ~MediaPluginCEF(); + + /*virtual*/ void receiveMessage( const char* message_string ); + + private: + bool init(); + void update( F64 milliseconds ); + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 10 }; + unsigned char* mBackgroundPixels; + int mColorR[ ENumObjects ]; + int mColorG[ ENumObjects ]; + int mColorB[ ENumObjects ]; + int mXpos[ ENumObjects ]; + int mYpos[ ENumObjects ]; + int mXInc[ ENumObjects ]; + int mYInc[ ENumObjects ]; + int mBlockSize[ ENumObjects ]; + bool mMouseButtonDown; + bool mStopAction; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginCEF::MediaPluginCEF( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : + MediaPluginBase( host_send_func, host_user_data ) +{ + mFirstTime = true; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mMouseButtonDown = false; + mStopAction = false; + mLastUpdateTime = 0; + mBackgroundPixels = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginCEF::~MediaPluginCEF() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::receiveMessage( const char* message_string ) +{ +// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "CEF plugin 1.0..0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if(message_name == "load_uri") + { + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + if(event == "down") + { + + } + else if(event == "up") + { + } + else if(event == "double_click") + { + } + } + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) +{ + // make sure we don't write outside the buffer + if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) + return; + + if ( mBackgroundPixels != NULL ) + { + unsigned char *pixel = mBackgroundPixels; + pixel += y * mWidth * mDepth; + pixel += ( x * mDepth ); + pixel[ 0 ] = b; + pixel[ 1 ] = g; + pixel[ 2 ] = r; + + setDirty( x, y, x + 1, y + 1 ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::update( F64 milliseconds ) +{ + if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) + return; + + if ( mPixels == 0 ) + return; + + if ( mFirstTime ) + { + for( int n = 0; n < ENumObjects; ++n ) + { + mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); + mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); + + mColorR[ n ] = rand() % 0x60 + 0x60; + mColorG[ n ] = rand() % 0x60 + 0x60; + mColorB[ n ] = rand() % 0x60 + 0x60; + + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + + mBlockSize[ n ] = rand() % 0x30 + 0x10; + }; + + delete [] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; + + mFirstTime = false; + }; + + if ( mStopAction ) + return; + + if ( time( NULL ) > mLastUpdateTime + 3 ) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for ( int y1 = 0; y1 < num_squares; ++y1 ) + { + for ( int x1 = 0; x1 < num_squares; ++x1 ) + { + int px_start = mWidth * x1 / num_squares; + int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; + + for( int y2 = py_start; y2 < py_end; ++y2 ) + { + for( int x2 = px_start; x2 < px_end; ++x2 ) + { + int rowspan = mWidth * mDepth; + + if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; + } + else + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; + }; + }; + }; + }; + }; + + time( &mLastUpdateTime ); + }; + + memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); + + for( int n = 0; n < ENumObjects; ++n ) + { + if ( rand() % 50 == 0 ) + { + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + }; + + if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) + mXInc[ n ]= -mXInc[ n ]; + + if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) + mYInc[ n ]= -mYInc[ n ]; + + mXpos[ n ] += mXInc[ n ]; + mYpos[ n ] += mYInc[ n ]; + + for( int y = 0; y < mBlockSize[ n ]; ++y ) + { + for( int x = 0; x < mBlockSize[ n ]; ++x ) + { + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; + }; + }; + }; + + setDirty( 0, 0, mWidth, mHeight ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginCEF::init() +{ + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); + message.setValue( "name", "Example Plugin" ); + sendMessage( message ); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data ) +{ + MediaPluginCEF* self = new MediaPluginCEF( host_send_func, host_user_data ); + *plugin_send_func = MediaPluginCEF::staticReceiveMessage; + *plugin_user_data = ( void* )self; + + return 0; +} + -- cgit v1.2.3 From d368babe7cc84ac6d8532e9d2438620cfa6d172d Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 25 Mar 2015 16:16:51 -0700 Subject: Make VS2013 look inside include/cef folder for headers --- indra/media_plugins/cef/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index 663303f0eb..7465fe727a 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} + ${CEF_INCLUDE_DIR} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} -- cgit v1.2.3 From 834a94caec7691a957c0816f38ac00d765fa5021 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 26 Mar 2015 04:35:13 +0100 Subject: point to new cef tpl with right headers, update cmaake and viewer_manifest logic to copy files to right place --- indra/media_plugins/cef/media_plugin_cef.cpp | 574 +++++++++++---------------- 1 file changed, 238 insertions(+), 336 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index ada297373a..7f0f40bcaa 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -34,380 +34,282 @@ #include "llpluginmessageclasses.h" #include "media_plugin_base.h" +#include +#include "llCEFLib.h" + #include //////////////////////////////////////////////////////////////////////////////// // class MediaPluginCEF : - public MediaPluginBase + public MediaPluginBase { - public: - MediaPluginCEF( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); - ~MediaPluginCEF(); - - /*virtual*/ void receiveMessage( const char* message_string ); - - private: - bool init(); - void update( F64 milliseconds ); - void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); - bool mFirstTime; - - time_t mLastUpdateTime; - enum Constants { ENumObjects = 10 }; - unsigned char* mBackgroundPixels; - int mColorR[ ENumObjects ]; - int mColorG[ ENumObjects ]; - int mColorB[ ENumObjects ]; - int mXpos[ ENumObjects ]; - int mYpos[ ENumObjects ]; - int mXInc[ ENumObjects ]; - int mYInc[ ENumObjects ]; - int mBlockSize[ ENumObjects ]; - bool mMouseButtonDown; - bool mStopAction; +public: + MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginCEF(); + + /*virtual*/ void receiveMessage(const char* message_string); + +private: + bool init(); + void update(F64 milliseconds); + bool mFirstTime; + + // TODO FIX ME + void pageChangedCallback(unsigned char* pixels, int width, int height) + { + if (mPixels && pixels) + { + memcpy(mPixels, pixels, width * height * mDepth); + setDirty(0, 0, mWidth, mHeight); + } + } + + void MediaPluginCEF::postDebugMessage(const std::string& msg); + + bool mEnableMediaPluginDebugging; + LLCEFLib* mLLCEFLib; }; //////////////////////////////////////////////////////////////////////////////// // -MediaPluginCEF::MediaPluginCEF( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : - MediaPluginBase( host_send_func, host_user_data ) +MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : +MediaPluginBase(host_send_func, host_user_data) { - mFirstTime = true; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mMouseButtonDown = false; - mStopAction = false; - mLastUpdateTime = 0; - mBackgroundPixels = 0; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mEnableMediaPluginDebugging = false; + + mLLCEFLib = new LLCEFLib(); } //////////////////////////////////////////////////////////////////////////////// // MediaPluginCEF::~MediaPluginCEF() { + mLLCEFLib->reset(); } //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::receiveMessage( const char* message_string ) +void MediaPluginCEF::postDebugMessage(const std::string& msg) { -// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "CEF plugin 1.0..0"; - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - F64 time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - }; - }; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - } - else if(message_name == "load_uri") - { - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - if(event == "down") - { - - } - else if(event == "up") - { - } - else if(event == "double_click") - { - } - } - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } + if (mEnableMediaPluginDebugging) + { + std::stringstream str; + str << "@Media Msg> " << msg; + + LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); + debug_message.setValue("message_text", str.str()); + debug_message.setValue("message_level", "info"); + sendMessage(debug_message); + } } //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) +void MediaPluginCEF::receiveMessage(const char* message_string) { - // make sure we don't write outside the buffer - if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) - return; - - if ( mBackgroundPixels != NULL ) - { - unsigned char *pixel = mBackgroundPixels; - pixel += y * mWidth * mDepth; - pixel += ( x * mDepth ); - pixel[ 0 ] = b; - pixel[ 1 ] = g; - pixel[ 2 ] = r; - - setDirty( x, y, x + 1, y + 1 ); - }; + // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "Example plugin 1.0..0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + mLLCEFLib->update(); + } + else if (message_name == "cleanup") + { + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { + // std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + // std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if (message_name == "init") + { + + mLLCEFLib->setPageChangedCallback(std::bind(&MediaPluginCEF::pageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + + bool result = mLLCEFLib->init(1024, 1024); + if (!result) + { + MessageBoxA(0, "FAIL INIT", 0, 0); + } + + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_BGRA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", false); + sendMessage(message); + } + else if (message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if (!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + mLLCEFLib->setSize(mWidth, mHeight); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if (message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + mLLCEFLib->navigate(uri); + } + else if (message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + //S32 button = message_in.getValueS32("button"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + + + //std::string modifiers = message_in.getValue("modifiers"); + + if (event == "down") + { + mLLCEFLib->mouseButton(0, true, x, y); + + std::stringstream str; + str << "Mouse down at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "up") + { + mLLCEFLib->mouseButton(0, false, x, y); + } + else if (event == "double_click") + { + } + else + { + mLLCEFLib->mouseMove(x, y); + } + } + else + if (message_name == "enable_media_plugin_debugging") + { + mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); + } + } + else + { + // std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } } -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::update( F64 milliseconds ) -{ - if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) - return; - - if ( mPixels == 0 ) - return; - - if ( mFirstTime ) - { - for( int n = 0; n < ENumObjects; ++n ) - { - mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); - mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); - - mColorR[ n ] = rand() % 0x60 + 0x60; - mColorG[ n ] = rand() % 0x60 + 0x60; - mColorB[ n ] = rand() % 0x60 + 0x60; - - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - - mBlockSize[ n ] = rand() % 0x30 + 0x10; - }; - - delete [] mBackgroundPixels; - - mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; - - mFirstTime = false; - }; - - if ( mStopAction ) - return; - - if ( time( NULL ) > mLastUpdateTime + 3 ) - { - const int num_squares = rand() % 20 + 4; - int sqr1_r = rand() % 0x80 + 0x20; - int sqr1_g = rand() % 0x80 + 0x20; - int sqr1_b = rand() % 0x80 + 0x20; - int sqr2_r = rand() % 0x80 + 0x20; - int sqr2_g = rand() % 0x80 + 0x20; - int sqr2_b = rand() % 0x80 + 0x20; - - for ( int y1 = 0; y1 < num_squares; ++y1 ) - { - for ( int x1 = 0; x1 < num_squares; ++x1 ) - { - int px_start = mWidth * x1 / num_squares; - int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; - int py_start = mHeight * y1 / num_squares; - int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; - - for( int y2 = py_start; y2 < py_end; ++y2 ) - { - for( int x2 = px_start; x2 < px_end; ++x2 ) - { - int rowspan = mWidth * mDepth; - - if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; - } - else - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; - }; - }; - }; - }; - }; - - time( &mLastUpdateTime ); - }; - - memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); - - for( int n = 0; n < ENumObjects; ++n ) - { - if ( rand() % 50 == 0 ) - { - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - }; - - if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) - mXInc[ n ]= -mXInc[ n ]; - - if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) - mYInc[ n ]= -mYInc[ n ]; - - mXpos[ n ] += mXInc[ n ]; - mYpos[ n ] += mYInc[ n ]; - - for( int y = 0; y < mBlockSize[ n ]; ++y ) - { - for( int x = 0; x < mBlockSize[ n ]; ++x ) - { - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; - }; - }; - }; - - setDirty( 0, 0, mWidth, mHeight ); -}; - //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::init() { - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); - message.setValue( "name", "Example Plugin" ); - sendMessage( message ); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "Example Plugin"); + sendMessage(message); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // -int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data ) +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) { - MediaPluginCEF* self = new MediaPluginCEF( host_send_func, host_user_data ); - *plugin_send_func = MediaPluginCEF::staticReceiveMessage; - *plugin_user_data = ( void* )self; + MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); + *plugin_send_func = MediaPluginCEF::staticReceiveMessage; + *plugin_user_data = (void*)self; - return 0; + return 0; } - -- cgit v1.2.3 From efffc4b0748d1fe950f46aaafe3ded679536d934 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Sat, 28 Mar 2015 01:49:20 +0100 Subject: add support for keyboard (rudimentary & broken), mouse wheel and open links in same page --- indra/media_plugins/cef/media_plugin_cef.cpp | 136 ++++++++++++++++++--------- 1 file changed, 90 insertions(+), 46 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 7f0f40bcaa..2e8e419e02 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -1,30 +1,30 @@ /** - * @file media_plugin_cef.cpp - * @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system - * - * @cond - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ +* @file media_plugin_cef.cpp +* @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system +* +* @cond +* $LicenseInfo:firstyear=2008&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* 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; +* version 2.1 of the License only. +* +* 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 +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +* @endcond +*/ #include "linden_common.h" @@ -37,7 +37,7 @@ #include #include "llCEFLib.h" -#include +#include // remove me //////////////////////////////////////////////////////////////////////////////// // @@ -48,19 +48,21 @@ public: MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); ~MediaPluginCEF(); - /*virtual*/ void receiveMessage(const char* message_string); + /*virtual*/ + void receiveMessage(const char* message_string); private: bool init(); - void update(F64 milliseconds); - bool mFirstTime; - // TODO FIX ME + // TODO FIX ME void pageChangedCallback(unsigned char* pixels, int width, int height) { if (mPixels && pixels) { - memcpy(mPixels, pixels, width * height * mDepth); + if (mWidth == width && mHeight == height) + { + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + } setDirty(0, 0, mWidth, mHeight); } } @@ -80,7 +82,7 @@ MediaPluginBase(host_send_func, host_user_data) mHeight = 0; mDepth = 4; mPixels = 0; - mEnableMediaPluginDebugging = false; + mEnableMediaPluginDebugging = true; mLLCEFLib = new LLCEFLib(); } @@ -96,7 +98,7 @@ MediaPluginCEF::~MediaPluginCEF() // void MediaPluginCEF::postDebugMessage(const std::string& msg) { - if (mEnableMediaPluginDebugging) + //if (mEnableMediaPluginDebugging) { std::stringstream str; str << "@Media Msg> " << msg; @@ -160,7 +162,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { if (mPixels == iter->second.mAddress) { - // This is the currently active pixel buffer. Make sure we stop drawing to it. mPixels = NULL; mTextureSegmentName.clear(); } @@ -168,17 +169,16 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else { - // std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; } - // Send the response so it can be cleaned up. LLPluginMessage message("base", "shm_remove_response"); message.setValue("name", name); sendMessage(message); } else { - // std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) @@ -191,7 +191,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) bool result = mLLCEFLib->init(1024, 1024); if (!result) { - MessageBoxA(0, "FAIL INIT", 0, 0); + //MessageBoxA(0, "FAIL INIT", 0, 0); } // Plugin gets to decide the texture parameters to use. @@ -252,14 +252,12 @@ void MediaPluginCEF::receiveMessage(const char* message_string) S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); - - //std::string modifiers = message_in.getValue("modifiers"); if (event == "down") { mLLCEFLib->mouseButton(0, true, x, y); - + mLLCEFLib->setFocus(true); std::stringstream str; str << "Mouse down at = " << x << ", " << y; postDebugMessage(str.str()); @@ -276,15 +274,61 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->mouseMove(x, y); } } - else - if (message_name == "enable_media_plugin_debugging") + else if (message_name == "scroll_event") + { + S32 y = message_in.getValueS32("y"); + const int scaling_factor = 40; + y *= -scaling_factor; + + mLLCEFLib->mouseWheel(y); + } + else if (message_name == "text_event") + { + std::string event = message_in.getValue("event"); + S32 key = message_in.getValue("text")[0]; + std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + //int native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + + //if (event == "down") + { + mLLCEFLib->keyPress(key, true); + } + //else + //if (event == "up") { - mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); + mLLCEFLib->keyPress(key, false); } + } + else if (message_name == "key_event") + { + std::string event = message_in.getValue("event"); + //S32 key = message_in.getValueS32("key"); + std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + int native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + native_scan_code = 8; + + if (event == "down") + { + mLLCEFLib->keyPress(native_scan_code, true); + } + else + if (event == "up") + { + mLLCEFLib->keyPress(native_scan_code, false); + } + } + else if (message_name == "enable_media_plugin_debugging") + { + mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); + } } else { - // std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; }; } } -- cgit v1.2.3 From 3728730839bf670ae22dd644aa1905e8e9c34560 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 4 Jun 2015 16:27:33 -0700 Subject: Add CEF into OS X build --- indra/media_plugins/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 0e0f84d1fd..24eb3947b4 100755 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -2,16 +2,13 @@ add_subdirectory(base) -if (WINDOWS) - add_subdirectory(cef) -endif (WINDOWS) - if (LINUX) add_subdirectory(gstreamer010) endif (LINUX) if (WINDOWS OR DARWIN) add_subdirectory(quicktime) + add_subdirectory(cef) endif (WINDOWS OR DARWIN) if (WINDOWS) -- cgit v1.2.3 From 6c203273574dfa23e4363144db63378df60bb3fe Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Mon, 8 Jun 2015 16:47:16 -0700 Subject: Fixed for OS X version - in progress --- indra/media_plugins/cef/media_plugin_cef.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 2e8e419e02..098dd67c0d 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -34,7 +34,8 @@ #include "llpluginmessageclasses.h" #include "media_plugin_base.h" -#include +#include "../../../build-darwin-i386/packages/include/boost/function.hpp" +#include "../../../build-darwin-i386/packages/include/boost/bind.hpp" #include "llCEFLib.h" #include // remove me @@ -67,7 +68,7 @@ private: } } - void MediaPluginCEF::postDebugMessage(const std::string& msg); + void postDebugMessage(const std::string& msg); bool mEnableMediaPluginDebugging; LLCEFLib* mLLCEFLib; @@ -186,9 +187,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) if (message_name == "init") { - mLLCEFLib->setPageChangedCallback(std::bind(&MediaPluginCEF::pageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + mLLCEFLib->setPageChangedCallback(boost::bind(&MediaPluginCEF::pageChangedCallback, this, _1, _2, _3)); - bool result = mLLCEFLib->init(1024, 1024); + LLCEFLibSettings settings; + settings.inital_width = 1024; + settings.inital_height = 1024; + settings.javascript_enabled = true; + settings.cookies_enabled = true; + bool result = mLLCEFLib->init(settings); if (!result) { //MessageBoxA(0, "FAIL INIT", 0, 0); -- cgit v1.2.3 From d80a24803d0865e0bef13bc059b416eed548494d Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 22 Jun 2015 16:14:13 -0700 Subject: I can't believe I really added these lines - pretend you didn't see them --- indra/media_plugins/cef/media_plugin_cef.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 098dd67c0d..187c6a241d 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -34,8 +34,8 @@ #include "llpluginmessageclasses.h" #include "media_plugin_base.h" -#include "../../../build-darwin-i386/packages/include/boost/function.hpp" -#include "../../../build-darwin-i386/packages/include/boost/bind.hpp" +#include "boost/function.hpp" +#include "boost/bind.hpp" #include "llCEFLib.h" #include // remove me -- cgit v1.2.3 From f7908a50294adff3456436074075a677a9c6239b Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 30 Jun 2015 00:07:58 +0100 Subject: Point to new version of LLCefLib with support for second life URLs, version string, navigation commands --- indra/media_plugins/cef/media_plugin_cef.cpp | 143 +++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 19 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 187c6a241d..3b82071ae8 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -38,8 +38,6 @@ #include "boost/bind.hpp" #include "llCEFLib.h" -#include // remove me - //////////////////////////////////////////////////////////////////////////////// // class MediaPluginCEF : @@ -55,19 +53,15 @@ public: private: bool init(); - // TODO FIX ME - void pageChangedCallback(unsigned char* pixels, int width, int height) - { - if (mPixels && pixels) - { - if (mWidth == width && mHeight == height) - { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); - } - setDirty(0, 0, mWidth, mHeight); - } - } - + void pageChangedCallback(unsigned char* pixels, int width, int height); + void onCustomSchemeURLCallback(std::string url); + void onConsoleMessageCallback(std::string message, std::string source, int line); + void onStatusMessageCallback(std::string value); + void onTitleChangeCallback(std::string title); + void onLoadStartCallback(); + void onLoadEndCallback(int httpStatusCode); + void onNavigateURLCallback(std::string url); + void postDebugMessage(const std::string& msg); bool mEnableMediaPluginDebugging; @@ -99,7 +93,7 @@ MediaPluginCEF::~MediaPluginCEF() // void MediaPluginCEF::postDebugMessage(const std::string& msg) { - //if (mEnableMediaPluginDebugging) + if (mEnableMediaPluginDebugging) { std::stringstream str; str << "@Media Msg> " << msg; @@ -111,6 +105,89 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg) } } +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::pageChangedCallback(unsigned char* pixels, int width, int height) +{ + if (mPixels && pixels) + { + if (mWidth == width && mHeight == height) + { + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + } + setDirty(0, 0, mWidth, mHeight); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + message.setValue("uri", url); + message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) +{ + std::stringstream str; + str << "Console message: " << message << " in file(" << source << ") at line " << line; + postDebugMessage(str.str()); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onStatusMessageCallback(std::string value) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); + message.setValue("status", value); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onTitleChangeCallback(std::string title) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadStartCallback() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueS32("result_code", httpStatusCode); + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onNavigateURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", url); + sendMessage(message); +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::receiveMessage(const char* message_string) @@ -133,7 +210,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; message.setValueLLSD("versions", versions); - std::string plugin_version = "Example plugin 1.0..0"; + std::string plugin_version = "CEF plugin 1.0.0"; message.setValue("plugin_version", plugin_version); sendMessage(message); } @@ -186,8 +263,15 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { if (message_name == "init") { - + // event callbacks from LLCefLib mLLCEFLib->setPageChangedCallback(boost::bind(&MediaPluginCEF::pageChangedCallback, this, _1, _2, _3)); + mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1)); + mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3)); + mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1)); + mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); + mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); + mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); + mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); LLCEFLibSettings settings; settings.inital_width = 1024; @@ -197,6 +281,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) bool result = mLLCEFLib->init(settings); if (!result) { +// TODO - return something to indicate failure //MessageBoxA(0, "FAIL INIT", 0, 0); } @@ -332,6 +417,26 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); } } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if (message_name == "browse_stop") + { + mLLCEFLib->stop(); + } + else if (message_name == "browse_reload") + { + bool ignore_cache = true; + mLLCEFLib->reload(ignore_cache); + } + else if (message_name == "browse_forward") + { + mLLCEFLib->goForward(); + } + else if (message_name == "browse_back") + { + mLLCEFLib->goBack(); + } + } else { //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; @@ -344,7 +449,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) bool MediaPluginCEF::init() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", "Example Plugin"); + message.setValue("name", "CEF Plugin"); sendMessage(message); return true; -- cgit v1.2.3 From d89b4109f9ac3f1ef95480823df292bbc8200347 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 2 Jul 2015 09:39:41 -0700 Subject: 2015 and we still care about line endings.. sigh --- indra/media_plugins/cef/media_plugin_cef.cpp | 100 ++++++++++++++------------- 1 file changed, 53 insertions(+), 47 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 3b82071ae8..358b35bbe2 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -53,15 +53,15 @@ public: private: bool init(); - void pageChangedCallback(unsigned char* pixels, int width, int height); - void onCustomSchemeURLCallback(std::string url); - void onConsoleMessageCallback(std::string message, std::string source, int line); - void onStatusMessageCallback(std::string value); - void onTitleChangeCallback(std::string title); - void onLoadStartCallback(); - void onLoadEndCallback(int httpStatusCode); - void onNavigateURLCallback(std::string url); - + void pageChangedCallback(unsigned char* pixels, int width, int height); + void onCustomSchemeURLCallback(std::string url); + void onConsoleMessageCallback(std::string message, std::string source, int line); + void onStatusMessageCallback(std::string value); + void onTitleChangeCallback(std::string title); + void onLoadStartCallback(); + void onLoadEndCallback(int httpStatusCode); + void onNavigateURLCallback(std::string url); + void postDebugMessage(const std::string& msg); bool mEnableMediaPluginDebugging; @@ -123,10 +123,10 @@ void MediaPluginCEF::pageChangedCallback(unsigned char* pixels, int width, int h // void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); - message.setValue("uri", url); - message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + message.setValue("uri", url); + message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// @@ -142,8 +142,8 @@ void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string s // void MediaPluginCEF::onStatusMessageCallback(std::string value) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); - message.setValue("status", value); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); + message.setValue("status", value); sendMessage(message); } @@ -151,19 +151,19 @@ void MediaPluginCEF::onStatusMessageCallback(std::string value) // void MediaPluginCEF::onTitleChangeCallback(std::string title) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", title); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onLoadStartCallback() { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); sendMessage(message); } @@ -171,11 +171,11 @@ void MediaPluginCEF::onLoadStartCallback() // void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueS32("result_code", httpStatusCode); - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueS32("result_code", httpStatusCode); + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); sendMessage(message); } @@ -183,9 +183,9 @@ void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) // void MediaPluginCEF::onNavigateURLCallback(std::string url) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", url); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", url); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// @@ -419,23 +419,28 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) { - if (message_name == "browse_stop") - { - mLLCEFLib->stop(); - } - else if (message_name == "browse_reload") - { - bool ignore_cache = true; - mLLCEFLib->reload(ignore_cache); - } - else if (message_name == "browse_forward") - { - mLLCEFLib->goForward(); - } - else if (message_name == "browse_back") - { - mLLCEFLib->goBack(); - } + if (message_name == "set_page_zoom_factor") + { + F32 factor = (F32)message_in.getValueReal("factor"); + mLLCEFLib->setPageZoom(factor); + } + if (message_name == "browse_stop") + { + mLLCEFLib->stop(); + } + else if (message_name == "browse_reload") + { + bool ignore_cache = true; + mLLCEFLib->reload(ignore_cache); + } + else if (message_name == "browse_forward") + { + mLLCEFLib->goForward(); + } + else if (message_name == "browse_back") + { + mLLCEFLib->goBack(); + } } else { @@ -468,3 +473,4 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, return 0; } + -- cgit v1.2.3 From adb0706aa0f3778fda9921172eaabefd3177dbdc Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 2 Jul 2015 23:56:19 +0100 Subject: plugin and llceflib code for improved mouse support --- indra/media_plugins/cef/media_plugin_cef.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 358b35bbe2..ccb8a93f87 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -339,26 +339,35 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (message_name == "mouse_event") { std::string event = message_in.getValue("event"); - //S32 button = message_in.getValueS32("button"); + S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); //std::string modifiers = message_in.getValue("modifiers"); + S32 button = message_in.getValueS32("button"); + EMouseButton btn = MB_MOUSE_BUTTON_LEFT; + if (button == 0) btn = MB_MOUSE_BUTTON_LEFT; + if (button == 1) btn = MB_MOUSE_BUTTON_RIGHT; + if (button == 2) btn = MB_MOUSE_BUTTON_MIDDLE; + if (event == "down") { - mLLCEFLib->mouseButton(0, true, x, y); - mLLCEFLib->setFocus(true); + mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); std::stringstream str; str << "Mouse down at = " << x << ", " << y; postDebugMessage(str.str()); } else if (event == "up") { - mLLCEFLib->mouseButton(0, false, x, y); + mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); + std::stringstream str; + str << "Mouse up at = " << x << ", " << y; + postDebugMessage(str.str()); } else if (event == "double_click") { + // TODO: do we need this ? } else { -- cgit v1.2.3 From ca49ad736a06aa796610f068f6419c39b8535251 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 10 Jul 2015 01:01:07 +0100 Subject: Initial support for keyboard (in progress) but includes many viewer changes to plumb in Key Up events --- indra/media_plugins/cef/media_plugin_cef.cpp | 189 +++++++++++++++++++++++---- 1 file changed, 161 insertions(+), 28 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index ccb8a93f87..f4ffd6d634 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -27,6 +27,7 @@ */ #include "linden_common.h" +#include "indra_constants.h" // for indra keyboard codes #include "llgl.h" #include "llplugininstance.h" @@ -64,6 +65,12 @@ private: void postDebugMessage(const std::string& msg); + + EKeyboardModifier decodeModifiers(std::string &modifiers); + void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); + void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); + void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); + bool mEnableMediaPluginDebugging; LLCEFLib* mLLCEFLib; }; @@ -273,15 +280,15 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); - LLCEFLibSettings settings; - settings.inital_width = 1024; - settings.inital_height = 1024; - settings.javascript_enabled = true; - settings.cookies_enabled = true; + LLCEFLibSettings settings; + settings.inital_width = 1024; + settings.inital_height = 1024; + settings.javascript_enabled = true; + settings.cookies_enabled = true; bool result = mLLCEFLib->init(settings); if (!result) { -// TODO - return something to indicate failure + // TODO - return something to indicate failure //MessageBoxA(0, "FAIL INIT", 0, 0); } @@ -339,7 +346,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (message_name == "mouse_event") { std::string event = message_in.getValue("event"); - + S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); @@ -354,6 +361,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) if (event == "down") { mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); + mLLCEFLib->setFocus(true); + std::stringstream str; str << "Mouse down at = " << x << ", " << y; postDebugMessage(str.str()); @@ -361,6 +370,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (event == "up") { mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); + std::stringstream str; str << "Mouse up at = " << x << ", " << y; postDebugMessage(str.str()); @@ -384,42 +394,31 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "text_event") { - std::string event = message_in.getValue("event"); - S32 key = message_in.getValue("text")[0]; + std::string text = message_in.getValue("text"); std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - //int native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - - //if (event == "down") - { - mLLCEFLib->keyPress(key, true); - } - //else - //if (event == "up") - { - mLLCEFLib->keyPress(key, false); - } + unicodeInput(text, decodeModifiers(modifiers), native_key_data); } else if (message_name == "key_event") { std::string event = message_in.getValue("event"); - //S32 key = message_in.getValueS32("key"); + S32 key = message_in.getValueS32("key"); std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - int native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_scan_code = 8; - + // Treat unknown events as key-up for safety. + EKeyEvent key_event = KE_KEY_UP; if (event == "down") { - mLLCEFLib->keyPress(native_scan_code, true); + key_event = KE_KEY_DOWN; } - else - if (event == "up") + else if (event == "repeat") { - mLLCEFLib->keyPress(native_scan_code, false); + key_event = KE_KEY_REPEAT; } + + keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); } else if (message_name == "enable_media_plugin_debugging") { @@ -458,6 +457,140 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } } +EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) +{ + int result = 0; + + if (modifiers.find("shift") != std::string::npos) + result |= KM_MODIFIER_SHIFT; + + if (modifiers.find("alt") != std::string::npos) + result |= KM_MODIFIER_ALT; + + if (modifiers.find("control") != std::string::npos) + result |= KM_MODIFIER_CONTROL; + + if (modifiers.find("meta") != std::string::npos) + result |= KM_MODIFIER_META; + + return (EKeyboardModifier)result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers) +{ + native_scan_code = 0; + native_virtual_key = 0; + native_modifiers = 0; + + if (native_key_data.isMap()) + { +#if LL_DARWIN + native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); + native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); +#elif LL_WINDOWS + native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + // TODO: I don't think we need to do anything with native modifiers here -- please verify +#endif + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +{ + // The incoming values for 'key' will be the ones from indra_constants.h + std::string utf8_text; + + if (key < 128) + { + // Low-ascii characters need to get passed through. + utf8_text = (char)key; + } + + // Any special-case handling we want to do for particular keys... + switch ((KEY)key) + { + // ASCII codes for some standard keys + case KEY_BACKSPACE: utf8_text = (char)8; break; + case KEY_TAB: utf8_text = (char)9; break; + case KEY_RETURN: utf8_text = (char)13; break; + case KEY_PAD_RETURN: utf8_text = (char)13; break; + case KEY_ESCAPE: utf8_text = (char)27; break; + + default: + break; + } + + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); + + //std::stringstream str; + //str << "@@@@@ KEYBOARD EVENT native_modifiers = " << native_modifiers; + //postDebugMessage(str.str()); + + mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + + + std::stringstream str; + str << "@@@@@@@@@@@@@@@@ MediaPluginCEF::keyEvent"; + postDebugMessage(str.str()); + + //uint32_t msg = native_key_data["msg"].asInteger(); + //uint32_t wparam = native_key_data["w_param"].asInteger(); + //uint64_t lparam = native_key_data["l_param"].asInteger(); + + //std::stringstream str; + //str << "@@@@@@@@@@@@@@@@ keyEvent Native message" << msg << ", " << wparam << ", " << lparam; + //postDebugMessage(str.str()); + + //mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); + + + //checkEditState(); +}; + +void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +{ + uint32_t key = KEY_NONE; + + if (utf8str.size() == 1) + { + // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character. + // In this case, use it as the key value. + key = utf8str[0]; + } + + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); + + std::stringstream str; + str << "@@@@@@@@@@@@@@@@ MediaPluginCEF::unicodeInput"; + postDebugMessage(str.str()); + + //uint32_t msg = native_key_data["msg"].asInteger(); + //uint32_t wparam = native_key_data["w_param"].asInteger(); + //uint64_t lparam = native_key_data["l_param"].asInteger(); + + //std::stringstream str; + //str << "@@@@@@@@@@@@@@@@ unicodeInput Native message" << msg << ", " << wparam << ", " << lparam; + //postDebugMessage(str.str()); + + //mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); + + mLLCEFLib->keyboardEvent(KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + mLLCEFLib->keyboardEvent(KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + + // checkEditState(); +}; + //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::init() -- cgit v1.2.3 From 83a9ae7b3c66e87179362f0da9fa7a378b1527e2 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 15 Jul 2015 02:27:33 +0100 Subject: New keyboard code for windows that uses system messages directly and works ok. Points to new LLCEFLib --- indra/media_plugins/cef/media_plugin_cef.cpp | 90 +++------------------------- 1 file changed, 9 insertions(+), 81 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f4ffd6d634..c1724fba3e 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -30,6 +30,7 @@ #include "indra_constants.h" // for indra keyboard codes #include "llgl.h" +#include "llsdutil.h" #include "llplugininstance.h" #include "llpluginmessage.h" #include "llpluginmessageclasses.h" @@ -502,93 +503,20 @@ void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& nat // void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { - // The incoming values for 'key' will be the ones from indra_constants.h - std::string utf8_text; + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - if (key < 128) - { - // Low-ascii characters need to get passed through. - utf8_text = (char)key; - } - - // Any special-case handling we want to do for particular keys... - switch ((KEY)key) - { - // ASCII codes for some standard keys - case KEY_BACKSPACE: utf8_text = (char)8; break; - case KEY_TAB: utf8_text = (char)9; break; - case KEY_RETURN: utf8_text = (char)13; break; - case KEY_PAD_RETURN: utf8_text = (char)13; break; - case KEY_ESCAPE: utf8_text = (char)27; break; - - default: - break; - } - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - //std::stringstream str; - //str << "@@@@@ KEYBOARD EVENT native_modifiers = " << native_modifiers; - //postDebugMessage(str.str()); - - mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - - - std::stringstream str; - str << "@@@@@@@@@@@@@@@@ MediaPluginCEF::keyEvent"; - postDebugMessage(str.str()); - - //uint32_t msg = native_key_data["msg"].asInteger(); - //uint32_t wparam = native_key_data["w_param"].asInteger(); - //uint64_t lparam = native_key_data["l_param"].asInteger(); - - //std::stringstream str; - //str << "@@@@@@@@@@@@@@@@ keyEvent Native message" << msg << ", " << wparam << ", " << lparam; - //postDebugMessage(str.str()); - - //mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); - - - //checkEditState(); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); }; void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { - uint32_t key = KEY_NONE; - - if (utf8str.size() == 1) - { - // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character. - // In this case, use it as the key value. - key = utf8str[0]; - } - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - std::stringstream str; - str << "@@@@@@@@@@@@@@@@ MediaPluginCEF::unicodeInput"; - postDebugMessage(str.str()); - - //uint32_t msg = native_key_data["msg"].asInteger(); - //uint32_t wparam = native_key_data["w_param"].asInteger(); - //uint64_t lparam = native_key_data["l_param"].asInteger(); - - //std::stringstream str; - //str << "@@@@@@@@@@@@@@@@ unicodeInput Native message" << msg << ", " << wparam << ", " << lparam; - //postDebugMessage(str.str()); - - //mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); - - mLLCEFLib->keyboardEvent(KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - mLLCEFLib->keyboardEvent(KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - // checkEditState(); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); }; //////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 224cfc6ec0624561d433afe8a38598f132def913 Mon Sep 17 00:00:00 2001 From: callum Date: Wed, 15 Jul 2015 18:43:57 -0700 Subject: Still making small changes to try to fix OS X keyboards --- indra/media_plugins/cef/media_plugin_cef.cpp | 53 ++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index c1724fba3e..f07eef28f4 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -403,6 +403,20 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "key_event") { +#if LL_DARWIN + std::string event = message_in.getValue("event"); + S32 key = message_in.getValueS32("key"); + if (event == "down") + { + mLLCEFLib->keyPress(key, true); + } + else if (event == "up") + { + mLLCEFLib->keyPress(key, false); + } + +#elif LL_WINDOWS + std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); std::string modifiers = message_in.getValue("modifiers"); @@ -420,6 +434,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); + +#endif + } else if (message_name == "enable_media_plugin_debugging") { @@ -495,7 +512,7 @@ void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& nat native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); // TODO: I don't think we need to do anything with native modifiers here -- please verify -#endif +#endif }; }; @@ -503,20 +520,50 @@ void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& nat // void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { +#if LL_DARWIN + std::string utf8_text; + + if (key < 128) + { + utf8_text = (char)key; + } + + switch ((KEY)key) + { + case KEY_BACKSPACE: utf8_text = (char)8; break; + case KEY_TAB: utf8_text = (char)9; break; + case KEY_RETURN: utf8_text = (char)13; break; + case KEY_PAD_RETURN: utf8_text = (char)13; break; + case KEY_ESCAPE: utf8_text = (char)27; break; + + default: + break; + } + + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); + + mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); +#elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); +#endif }; void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { +#if LL_DARWIN + mLLCEFLib->keyPress(utf8str[0], true); +#elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); +#endif }; //////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 0d6d281cb3c54b08eb845199ba24992bddcf9bae Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 16 Jul 2015 16:11:19 -0700 Subject: Point to LLCEFLib with updated 2357 version and support for setting language for embedded browser --- indra/media_plugins/cef/media_plugin_cef.cpp | 1193 +++++++++++++------------- 1 file changed, 600 insertions(+), 593 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f07eef28f4..70a8eb5d9b 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -1,593 +1,600 @@ -/** -* @file media_plugin_cef.cpp -* @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system -* -* @cond -* $LicenseInfo:firstyear=2008&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* 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; -* version 2.1 of the License only. -* -* 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 -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -* @endcond -*/ - -#include "linden_common.h" -#include "indra_constants.h" // for indra keyboard codes - -#include "llgl.h" -#include "llsdutil.h" -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#include "boost/function.hpp" -#include "boost/bind.hpp" -#include "llCEFLib.h" - -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginCEF : - public MediaPluginBase -{ -public: - MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginCEF(); - - /*virtual*/ - void receiveMessage(const char* message_string); - -private: - bool init(); - - void pageChangedCallback(unsigned char* pixels, int width, int height); - void onCustomSchemeURLCallback(std::string url); - void onConsoleMessageCallback(std::string message, std::string source, int line); - void onStatusMessageCallback(std::string value); - void onTitleChangeCallback(std::string title); - void onLoadStartCallback(); - void onLoadEndCallback(int httpStatusCode); - void onNavigateURLCallback(std::string url); - - void postDebugMessage(const std::string& msg); - - - EKeyboardModifier decodeModifiers(std::string &modifiers); - void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); - void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); - void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); - - bool mEnableMediaPluginDebugging; - LLCEFLib* mLLCEFLib; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : -MediaPluginBase(host_send_func, host_user_data) -{ - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mEnableMediaPluginDebugging = true; - - mLLCEFLib = new LLCEFLib(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginCEF::~MediaPluginCEF() -{ - mLLCEFLib->reset(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::postDebugMessage(const std::string& msg) -{ - if (mEnableMediaPluginDebugging) - { - std::stringstream str; - str << "@Media Msg> " << msg; - - LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); - debug_message.setValue("message_text", str.str()); - debug_message.setValue("message_level", "info"); - sendMessage(debug_message); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::pageChangedCallback(unsigned char* pixels, int width, int height) -{ - if (mPixels && pixels) - { - if (mWidth == width && mHeight == height) - { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); - } - setDirty(0, 0, mWidth, mHeight); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); - message.setValue("uri", url); - message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) -{ - std::stringstream str; - str << "Console message: " << message << " in file(" << source << ") at line " << line; - postDebugMessage(str.str()); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onStatusMessageCallback(std::string value) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); - message.setValue("status", value); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onTitleChangeCallback(std::string title) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", title); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onLoadStartCallback() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueS32("result_code", httpStatusCode); - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onNavigateURLCallback(std::string url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", url); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::receiveMessage(const char* message_string) -{ - // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if (message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if (message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "CEF plugin 1.0.0"; - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if (message_name == "idle") - { - mLLCEFLib->update(); - } - else if (message_name == "cleanup") - { - } - else if (message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if (message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - if (mPixels == iter->second.mAddress) - { - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if (message_name == "init") - { - // event callbacks from LLCefLib - mLLCEFLib->setPageChangedCallback(boost::bind(&MediaPluginCEF::pageChangedCallback, this, _1, _2, _3)); - mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1)); - mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3)); - mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1)); - mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); - mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); - mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); - mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); - - LLCEFLibSettings settings; - settings.inital_width = 1024; - settings.inital_height = 1024; - settings.javascript_enabled = true; - settings.cookies_enabled = true; - bool result = mLLCEFLib->init(settings); - if (!result) - { - // TODO - return something to indicate failure - //MessageBoxA(0, "FAIL INIT", 0, 0); - } - - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_BGRA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", false); - sendMessage(message); - } - else if (message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - if (!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - }; - }; - - mLLCEFLib->setSize(mWidth, mHeight); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - } - else if (message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - mLLCEFLib->navigate(uri); - } - else if (message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - //std::string modifiers = message_in.getValue("modifiers"); - - S32 button = message_in.getValueS32("button"); - EMouseButton btn = MB_MOUSE_BUTTON_LEFT; - if (button == 0) btn = MB_MOUSE_BUTTON_LEFT; - if (button == 1) btn = MB_MOUSE_BUTTON_RIGHT; - if (button == 2) btn = MB_MOUSE_BUTTON_MIDDLE; - - if (event == "down") - { - mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); - mLLCEFLib->setFocus(true); - - std::stringstream str; - str << "Mouse down at = " << x << ", " << y; - postDebugMessage(str.str()); - } - else if (event == "up") - { - mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); - - std::stringstream str; - str << "Mouse up at = " << x << ", " << y; - postDebugMessage(str.str()); - } - else if (event == "double_click") - { - // TODO: do we need this ? - } - else - { - mLLCEFLib->mouseMove(x, y); - } - } - else if (message_name == "scroll_event") - { - S32 y = message_in.getValueS32("y"); - const int scaling_factor = 40; - y *= -scaling_factor; - - mLLCEFLib->mouseWheel(y); - } - else if (message_name == "text_event") - { - std::string text = message_in.getValue("text"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - unicodeInput(text, decodeModifiers(modifiers), native_key_data); - } - else if (message_name == "key_event") - { -#if LL_DARWIN - std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - if (event == "down") - { - mLLCEFLib->keyPress(key, true); - } - else if (event == "up") - { - mLLCEFLib->keyPress(key, false); - } - -#elif LL_WINDOWS - - std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - // Treat unknown events as key-up for safety. - EKeyEvent key_event = KE_KEY_UP; - if (event == "down") - { - key_event = KE_KEY_DOWN; - } - else if (event == "repeat") - { - key_event = KE_KEY_REPEAT; - } - - keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); - -#endif - - } - else if (message_name == "enable_media_plugin_debugging") - { - mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) - { - if (message_name == "set_page_zoom_factor") - { - F32 factor = (F32)message_in.getValueReal("factor"); - mLLCEFLib->setPageZoom(factor); - } - if (message_name == "browse_stop") - { - mLLCEFLib->stop(); - } - else if (message_name == "browse_reload") - { - bool ignore_cache = true; - mLLCEFLib->reload(ignore_cache); - } - else if (message_name == "browse_forward") - { - mLLCEFLib->goForward(); - } - else if (message_name == "browse_back") - { - mLLCEFLib->goBack(); - } - } - else - { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } -} - -EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) -{ - int result = 0; - - if (modifiers.find("shift") != std::string::npos) - result |= KM_MODIFIER_SHIFT; - - if (modifiers.find("alt") != std::string::npos) - result |= KM_MODIFIER_ALT; - - if (modifiers.find("control") != std::string::npos) - result |= KM_MODIFIER_CONTROL; - - if (modifiers.find("meta") != std::string::npos) - result |= KM_MODIFIER_META; - - return (EKeyboardModifier)result; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers) -{ - native_scan_code = 0; - native_virtual_key = 0; - native_modifiers = 0; - - if (native_key_data.isMap()) - { -#if LL_DARWIN - native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#elif LL_WINDOWS - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - // TODO: I don't think we need to do anything with native modifiers here -- please verify -#endif - }; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) -{ -#if LL_DARWIN - std::string utf8_text; - - if (key < 128) - { - utf8_text = (char)key; - } - - switch ((KEY)key) - { - case KEY_BACKSPACE: utf8_text = (char)8; break; - case KEY_TAB: utf8_text = (char)9; break; - case KEY_RETURN: utf8_text = (char)13; break; - case KEY_PAD_RETURN: utf8_text = (char)13; break; - case KEY_ESCAPE: utf8_text = (char)27; break; - - default: - break; - } - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); -#elif LL_WINDOWS - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); -#endif -}; - -void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) -{ -#if LL_DARWIN - mLLCEFLib->keyPress(utf8str[0], true); -#elif LL_WINDOWS - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); -#endif -}; - -//////////////////////////////////////////////////////////////////////////////// -// -bool MediaPluginCEF::init() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", "CEF Plugin"); - sendMessage(message); - - return true; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data) -{ - MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); - *plugin_send_func = MediaPluginCEF::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; -} - +/** +* @file media_plugin_cef.cpp +* @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system +* +* @cond +* $LicenseInfo:firstyear=2008&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* 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; +* version 2.1 of the License only. +* +* 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 +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +* @endcond +*/ + +#include "linden_common.h" +#include "indra_constants.h" // for indra keyboard codes + +#include "llgl.h" +#include "llsdutil.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include "boost/function.hpp" +#include "boost/bind.hpp" +#include "llCEFLib.h" + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginCEF : + public MediaPluginBase +{ +public: + MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginCEF(); + + /*virtual*/ + void receiveMessage(const char* message_string); + +private: + bool init(); + + void pageChangedCallback(unsigned char* pixels, int width, int height); + void onCustomSchemeURLCallback(std::string url); + void onConsoleMessageCallback(std::string message, std::string source, int line); + void onStatusMessageCallback(std::string value); + void onTitleChangeCallback(std::string title); + void onLoadStartCallback(); + void onLoadEndCallback(int httpStatusCode); + void onNavigateURLCallback(std::string url); + + void postDebugMessage(const std::string& msg); + + + EKeyboardModifier decodeModifiers(std::string &modifiers); + void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); + void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); + void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); + + bool mEnableMediaPluginDebugging; + std::string mHostLanguage; + LLCEFLib* mLLCEFLib; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : +MediaPluginBase(host_send_func, host_user_data) +{ + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mEnableMediaPluginDebugging = true; + mHostLanguage = "en"; + + mLLCEFLib = new LLCEFLib(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginCEF::~MediaPluginCEF() +{ + mLLCEFLib->reset(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::postDebugMessage(const std::string& msg) +{ + if (mEnableMediaPluginDebugging) + { + std::stringstream str; + str << "@Media Msg> " << msg; + + LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); + debug_message.setValue("message_text", str.str()); + debug_message.setValue("message_level", "info"); + sendMessage(debug_message); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::pageChangedCallback(unsigned char* pixels, int width, int height) +{ + if (mPixels && pixels) + { + if (mWidth == width && mHeight == height) + { + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + } + setDirty(0, 0, mWidth, mHeight); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + message.setValue("uri", url); + message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) +{ + std::stringstream str; + str << "Console message: " << message << " in file(" << source << ") at line " << line; + postDebugMessage(str.str()); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onStatusMessageCallback(std::string value) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); + message.setValue("status", value); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onTitleChangeCallback(std::string title) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadStartCallback() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueS32("result_code", httpStatusCode); + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onNavigateURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", url); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::receiveMessage(const char* message_string) +{ + // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "CEF plugin 1.0.0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + mLLCEFLib->update(); + } + else if (message_name == "cleanup") + { + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if (message_name == "init") + { + // event callbacks from LLCefLib + mLLCEFLib->setPageChangedCallback(boost::bind(&MediaPluginCEF::pageChangedCallback, this, _1, _2, _3)); + mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1)); + mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3)); + mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1)); + mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); + mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); + mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); + mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); + + LLCEFLibSettings settings; + settings.inital_width = 1024; + settings.inital_height = 1024; + settings.javascript_enabled = true; + settings.cookies_enabled = true; + settings.accept_language_list = mHostLanguage; + bool result = mLLCEFLib->init(settings); + if (!result) + { + // TODO - return something to indicate failure + //MessageBoxA(0, "FAIL INIT", 0, 0); + } + + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_BGRA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", false); + sendMessage(message); + } + else if (message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if (!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + mLLCEFLib->setSize(mWidth, mHeight); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if (message_name == "set_language_code") + { + mHostLanguage = message_in.getValue("language"); + } + else if (message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + mLLCEFLib->navigate(uri); + } + else if (message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + //std::string modifiers = message_in.getValue("modifiers"); + + S32 button = message_in.getValueS32("button"); + EMouseButton btn = MB_MOUSE_BUTTON_LEFT; + if (button == 0) btn = MB_MOUSE_BUTTON_LEFT; + if (button == 1) btn = MB_MOUSE_BUTTON_RIGHT; + if (button == 2) btn = MB_MOUSE_BUTTON_MIDDLE; + + if (event == "down") + { + mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); + mLLCEFLib->setFocus(true); + + std::stringstream str; + str << "Mouse down at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "up") + { + mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); + + std::stringstream str; + str << "Mouse up at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "double_click") + { + // TODO: do we need this ? + } + else + { + mLLCEFLib->mouseMove(x, y); + } + } + else if (message_name == "scroll_event") + { + S32 y = message_in.getValueS32("y"); + const int scaling_factor = 40; + y *= -scaling_factor; + + mLLCEFLib->mouseWheel(y); + } + else if (message_name == "text_event") + { + std::string text = message_in.getValue("text"); + std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + unicodeInput(text, decodeModifiers(modifiers), native_key_data); + } + else if (message_name == "key_event") + { +#if LL_DARWIN + std::string event = message_in.getValue("event"); + S32 key = message_in.getValueS32("key"); + if (event == "down") + { + mLLCEFLib->keyPress(key, true); + } + else if (event == "up") + { + mLLCEFLib->keyPress(key, false); + } + +#elif LL_WINDOWS + + std::string event = message_in.getValue("event"); + S32 key = message_in.getValueS32("key"); + std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + // Treat unknown events as key-up for safety. + EKeyEvent key_event = KE_KEY_UP; + if (event == "down") + { + key_event = KE_KEY_DOWN; + } + else if (event == "repeat") + { + key_event = KE_KEY_REPEAT; + } + + keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); + +#endif + + } + else if (message_name == "enable_media_plugin_debugging") + { + mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if (message_name == "set_page_zoom_factor") + { + F32 factor = (F32)message_in.getValueReal("factor"); + mLLCEFLib->setPageZoom(factor); + } + if (message_name == "browse_stop") + { + mLLCEFLib->stop(); + } + else if (message_name == "browse_reload") + { + bool ignore_cache = true; + mLLCEFLib->reload(ignore_cache); + } + else if (message_name == "browse_forward") + { + mLLCEFLib->goForward(); + } + else if (message_name == "browse_back") + { + mLLCEFLib->goBack(); + } + } + else + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } +} + +EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) +{ + int result = 0; + + if (modifiers.find("shift") != std::string::npos) + result |= KM_MODIFIER_SHIFT; + + if (modifiers.find("alt") != std::string::npos) + result |= KM_MODIFIER_ALT; + + if (modifiers.find("control") != std::string::npos) + result |= KM_MODIFIER_CONTROL; + + if (modifiers.find("meta") != std::string::npos) + result |= KM_MODIFIER_META; + + return (EKeyboardModifier)result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers) +{ + native_scan_code = 0; + native_virtual_key = 0; + native_modifiers = 0; + + if (native_key_data.isMap()) + { +#if LL_DARWIN + native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); + native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); +#elif LL_WINDOWS + native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + // TODO: I don't think we need to do anything with native modifiers here -- please verify +#endif + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +{ +#if LL_DARWIN + std::string utf8_text; + + if (key < 128) + { + utf8_text = (char)key; + } + + switch ((KEY)key) + { + case KEY_BACKSPACE: utf8_text = (char)8; break; + case KEY_TAB: utf8_text = (char)9; break; + case KEY_RETURN: utf8_text = (char)13; break; + case KEY_PAD_RETURN: utf8_text = (char)13; break; + case KEY_ESCAPE: utf8_text = (char)27; break; + + default: + break; + } + + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); + + mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); +#elif LL_WINDOWS + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); +#endif +}; + +void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +{ +#if LL_DARWIN + mLLCEFLib->keyPress(utf8str[0], true); +#elif LL_WINDOWS + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); +#endif +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginCEF::init() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "CEF Plugin"); + sendMessage(message); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) +{ + MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); + *plugin_send_func = MediaPluginCEF::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + -- cgit v1.2.3 From 8e3acf461e3f3536b621a533d6ab15bc9e0a36be Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 17 Jul 2015 16:14:42 -0700 Subject: Changes to implement enable/disable cookies, javascript, plugins --- indra/media_plugins/cef/media_plugin_cef.cpp | 34 +++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 70a8eb5d9b..4bde7e7d49 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -74,6 +74,9 @@ private: bool mEnableMediaPluginDebugging; std::string mHostLanguage; + bool mCookiesEnabled; + bool mPluginsEnabled; + bool mJavascriptEnabled; LLCEFLib* mLLCEFLib; }; @@ -88,7 +91,9 @@ MediaPluginBase(host_send_func, host_user_data) mPixels = 0; mEnableMediaPluginDebugging = true; mHostLanguage = "en"; - + mCookiesEnabled = true; + mPluginsEnabled = false; + mJavascriptEnabled = true; mLLCEFLib = new LLCEFLib(); } @@ -286,14 +291,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) LLCEFLibSettings settings; settings.inital_width = 1024; settings.inital_height = 1024; - settings.javascript_enabled = true; - settings.cookies_enabled = true; + settings.plugins_enabled = mPluginsEnabled; + settings.javascript_enabled = mJavascriptEnabled; + settings.cookies_enabled = mCookiesEnabled; settings.accept_language_list = mHostLanguage; bool result = mLLCEFLib->init(settings); if (!result) { - // TODO - return something to indicate failure - //MessageBoxA(0, "FAIL INIT", 0, 0); + // if this fails, the media system in viewer will put up a message } // Plugin gets to decide the texture parameters to use. @@ -423,7 +428,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } #elif LL_WINDOWS - std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); std::string modifiers = message_in.getValue("modifiers"); @@ -441,9 +445,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); - #endif - } else if (message_name == "enable_media_plugin_debugging") { @@ -474,6 +476,22 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mLLCEFLib->goBack(); } + else if (message_name == "cookies_enabled") + { + mCookiesEnabled = message_in.getValueBoolean("enable"); +std::stringstream str; +str << "@@@@@@@##### cookies_enabled - mCookiesEnabled = " << mCookiesEnabled; +postDebugMessage(str.str()); + + } + else if (message_name == "plugins_enabled") + { + mPluginsEnabled = message_in.getValueBoolean("enable"); + } + else if (message_name == "javascript_enabled") + { + mJavascriptEnabled = message_in.getValueBoolean("enable"); + } } else { -- cgit v1.2.3 From 7cc5db9fdb19d8e798412295280fdf1d86cd0da8 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 24 Jul 2015 23:54:09 +0100 Subject: Include support for http auth. also improve mouse handling with drag select --- indra/media_plugins/cef/media_plugin_cef.cpp | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 4bde7e7d49..56bb4e469b 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -52,6 +52,7 @@ public: /*virtual*/ void receiveMessage(const char* message_string); + private: bool init(); @@ -63,9 +64,10 @@ private: void onLoadStartCallback(); void onLoadEndCallback(int httpStatusCode); void onNavigateURLCallback(std::string url); + bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); void postDebugMessage(const std::string& msg); - + void authResponse(LLPluginMessage &message); EKeyboardModifier decodeModifiers(std::string &modifiers); void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); @@ -77,6 +79,9 @@ private: bool mCookiesEnabled; bool mPluginsEnabled; bool mJavascriptEnabled; + std::string mAuthUsername; + std::string mAuthPassword; + bool mAuthOK; LLCEFLib* mLLCEFLib; }; @@ -94,6 +99,9 @@ MediaPluginBase(host_send_func, host_user_data) mCookiesEnabled = true; mPluginsEnabled = false; mJavascriptEnabled = true; + mAuthUsername = ""; + mAuthPassword = ""; + mAuthOK = false; mLLCEFLib = new LLCEFLib(); } @@ -203,6 +211,39 @@ void MediaPluginCEF::onNavigateURLCallback(std::string url) sendMessage(message); } +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password) +{ + mAuthOK = false; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); + message.setValue("url", host); + message.setValue("realm", realm); + message.setValueBoolean("blocking_request", true); + + // The "blocking_request" key in the message means this sendMessage call will block until a response is received. + sendMessage(message); + + if (mAuthOK) + { + username = mAuthUsername; + password = mAuthPassword; + } + + return mAuthOK; +} + +void MediaPluginCEF::authResponse(LLPluginMessage &message) +{ + mAuthOK = message.getValueBoolean("ok"); + if (mAuthOK) + { + mAuthUsername = message.getValue("username"); + mAuthPassword = message.getValue("password"); + } +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::receiveMessage(const char* message_string) @@ -287,6 +328,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); + mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); LLCEFLibSettings settings; settings.inital_width = 1024; @@ -451,6 +493,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); } + if (message_name == "auth_response") + { + authResponse(message_in); + } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) { -- cgit v1.2.3 From a75a4e2a4f0b8bc65aa45368326fce0e6635c4ac Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 27 Jul 2015 16:09:04 -0700 Subject: Bring in lastest version of LLCEFLIb & set user agent string before browser instance created --- indra/media_plugins/cef/media_plugin_cef.cpp | 1336 +++++++++++++------------- 1 file changed, 674 insertions(+), 662 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 56bb4e469b..fcedc3355d 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -1,664 +1,676 @@ -/** -* @file media_plugin_cef.cpp -* @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system -* -* @cond -* $LicenseInfo:firstyear=2008&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -* -* 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; -* version 2.1 of the License only. -* -* 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 -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -* @endcond -*/ - -#include "linden_common.h" -#include "indra_constants.h" // for indra keyboard codes - -#include "llgl.h" -#include "llsdutil.h" -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#include "boost/function.hpp" -#include "boost/bind.hpp" -#include "llCEFLib.h" - -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginCEF : - public MediaPluginBase -{ -public: - MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginCEF(); - - /*virtual*/ - void receiveMessage(const char* message_string); - - -private: - bool init(); - - void pageChangedCallback(unsigned char* pixels, int width, int height); - void onCustomSchemeURLCallback(std::string url); - void onConsoleMessageCallback(std::string message, std::string source, int line); - void onStatusMessageCallback(std::string value); - void onTitleChangeCallback(std::string title); - void onLoadStartCallback(); - void onLoadEndCallback(int httpStatusCode); - void onNavigateURLCallback(std::string url); - bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); - - void postDebugMessage(const std::string& msg); - void authResponse(LLPluginMessage &message); - - EKeyboardModifier decodeModifiers(std::string &modifiers); - void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); - void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); - void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); - - bool mEnableMediaPluginDebugging; - std::string mHostLanguage; - bool mCookiesEnabled; - bool mPluginsEnabled; - bool mJavascriptEnabled; - std::string mAuthUsername; - std::string mAuthPassword; - bool mAuthOK; - LLCEFLib* mLLCEFLib; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : -MediaPluginBase(host_send_func, host_user_data) -{ - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mEnableMediaPluginDebugging = true; - mHostLanguage = "en"; - mCookiesEnabled = true; - mPluginsEnabled = false; - mJavascriptEnabled = true; - mAuthUsername = ""; - mAuthPassword = ""; - mAuthOK = false; - mLLCEFLib = new LLCEFLib(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginCEF::~MediaPluginCEF() -{ - mLLCEFLib->reset(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::postDebugMessage(const std::string& msg) -{ - if (mEnableMediaPluginDebugging) - { - std::stringstream str; - str << "@Media Msg> " << msg; - - LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); - debug_message.setValue("message_text", str.str()); - debug_message.setValue("message_level", "info"); - sendMessage(debug_message); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::pageChangedCallback(unsigned char* pixels, int width, int height) -{ - if (mPixels && pixels) - { - if (mWidth == width && mHeight == height) - { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); - } - setDirty(0, 0, mWidth, mHeight); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); - message.setValue("uri", url); - message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) -{ - std::stringstream str; - str << "Console message: " << message << " in file(" << source << ") at line " << line; - postDebugMessage(str.str()); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onStatusMessageCallback(std::string value) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); - message.setValue("status", value); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onTitleChangeCallback(std::string title) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", title); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onLoadStartCallback() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueS32("result_code", httpStatusCode); - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onNavigateURLCallback(std::string url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", url); - sendMessage(message); -} - -//////////////////////////////////////////////////////////////////////////////// -// +/** +* @file media_plugin_cef.cpp +* @brief CEF (Chromium Embedding Framework) plugin for LLMedia API plugin system +* +* @cond +* $LicenseInfo:firstyear=2008&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* 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; +* version 2.1 of the License only. +* +* 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 +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +* @endcond +*/ + +#include "linden_common.h" +#include "indra_constants.h" // for indra keyboard codes + +#include "llgl.h" +#include "llsdutil.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include "boost/function.hpp" +#include "boost/bind.hpp" +#include "llCEFLib.h" + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginCEF : + public MediaPluginBase +{ +public: + MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginCEF(); + + /*virtual*/ + void receiveMessage(const char* message_string); + + +private: + bool init(); + + void onPageChangedCallback(unsigned char* pixels, int width, int height); + void onCustomSchemeURLCallback(std::string url); + void onConsoleMessageCallback(std::string message, std::string source, int line); + void onStatusMessageCallback(std::string value); + void onTitleChangeCallback(std::string title); + void onLoadStartCallback(); + void onLoadEndCallback(int httpStatusCode); + void onNavigateURLCallback(std::string url); + bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); + + void postDebugMessage(const std::string& msg); + void authResponse(LLPluginMessage &message); + + EKeyboardModifier decodeModifiers(std::string &modifiers); + void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); + void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); + void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); + + bool mEnableMediaPluginDebugging; + std::string mHostLanguage; + bool mCookiesEnabled; + bool mPluginsEnabled; + bool mJavascriptEnabled; + std::string mUserAgentSubtring; + std::string mAuthUsername; + std::string mAuthPassword; + bool mAuthOK; + LLCEFLib* mLLCEFLib; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : +MediaPluginBase(host_send_func, host_user_data) +{ + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mEnableMediaPluginDebugging = true; + mHostLanguage = "en"; + mCookiesEnabled = true; + mPluginsEnabled = false; + mJavascriptEnabled = true; + mUserAgentSubtring = ""; + mAuthUsername = ""; + mAuthPassword = ""; + mAuthOK = false; + mLLCEFLib = new LLCEFLib(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginCEF::~MediaPluginCEF() +{ + mLLCEFLib->reset(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::postDebugMessage(const std::string& msg) +{ + if (mEnableMediaPluginDebugging) + { + std::stringstream str; + str << "@Media Msg> " << msg; + + LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); + debug_message.setValue("message_text", str.str()); + debug_message.setValue("message_level", "info"); + sendMessage(debug_message); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int width, int height) +{ + if (mPixels && pixels) + { + if (mWidth == width && mHeight == height) + { + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + } + setDirty(0, 0, mWidth, mHeight); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + message.setValue("uri", url); + message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) +{ + std::stringstream str; + str << "Console message: " << message << " in file(" << source << ") at line " << line; + postDebugMessage(str.str()); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onStatusMessageCallback(std::string value) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); + message.setValue("status", value); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onTitleChangeCallback(std::string title) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", title); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadStartCallback() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? + message.setValueS32("result_code", httpStatusCode); + message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onNavigateURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", url); + sendMessage(message); +} + +//////////////////////////////////////////////////////////////////////////////// +// bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password) -{ - mAuthOK = false; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); - message.setValue("url", host); - message.setValue("realm", realm); - message.setValueBoolean("blocking_request", true); - - // The "blocking_request" key in the message means this sendMessage call will block until a response is received. - sendMessage(message); - - if (mAuthOK) - { - username = mAuthUsername; - password = mAuthPassword; - } - - return mAuthOK; -} - -void MediaPluginCEF::authResponse(LLPluginMessage &message) -{ - mAuthOK = message.getValueBoolean("ok"); - if (mAuthOK) - { - mAuthUsername = message.getValue("username"); - mAuthPassword = message.getValue("password"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::receiveMessage(const char* message_string) -{ - // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if (message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if (message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "CEF plugin 1.0.0"; - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if (message_name == "idle") - { - mLLCEFLib->update(); - } - else if (message_name == "cleanup") - { - } - else if (message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if (message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - if (mPixels == iter->second.mAddress) - { - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if (message_name == "init") - { - // event callbacks from LLCefLib - mLLCEFLib->setPageChangedCallback(boost::bind(&MediaPluginCEF::pageChangedCallback, this, _1, _2, _3)); - mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1)); - mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3)); - mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1)); - mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); - mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); - mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); - mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); +{ + mAuthOK = false; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); + message.setValue("url", host); + message.setValue("realm", realm); + message.setValueBoolean("blocking_request", true); + + // The "blocking_request" key in the message means this sendMessage call will block until a response is received. + sendMessage(message); + + if (mAuthOK) + { + username = mAuthUsername; + password = mAuthPassword; + } + + return mAuthOK; +} + +void MediaPluginCEF::authResponse(LLPluginMessage &message) +{ + mAuthOK = message.getValueBoolean("ok"); + if (mAuthOK) + { + mAuthUsername = message.getValue("username"); + mAuthPassword = message.getValue("password"); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::receiveMessage(const char* message_string) +{ + // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if (message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if (message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "CEF plugin 1.0.0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if (message_name == "idle") + { + mLLCEFLib->update(); + } + else if (message_name == "cleanup") + { + } + else if (message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if (message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + if (mPixels == iter->second.mAddress) + { + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if (message_name == "init") + { + // event callbacks from LLCefLib + mLLCEFLib->setOnPageChangedCallback(boost::bind(&MediaPluginCEF::onPageChangedCallback, this, _1, _2, _3)); + mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1)); + mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3)); + mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1)); + mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); + mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); + mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); + mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); - - LLCEFLibSettings settings; - settings.inital_width = 1024; - settings.inital_height = 1024; - settings.plugins_enabled = mPluginsEnabled; - settings.javascript_enabled = mJavascriptEnabled; - settings.cookies_enabled = mCookiesEnabled; - settings.accept_language_list = mHostLanguage; - bool result = mLLCEFLib->init(settings); - if (!result) - { - // if this fails, the media system in viewer will put up a message - } - - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueU32("format", GL_BGRA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", false); - sendMessage(message); - } - else if (message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - if (!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if (iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - }; - }; - - mLLCEFLib->setSize(mWidth, mHeight); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - } - else if (message_name == "set_language_code") - { - mHostLanguage = message_in.getValue("language"); - } - else if (message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - mLLCEFLib->navigate(uri); - } - else if (message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - //std::string modifiers = message_in.getValue("modifiers"); - - S32 button = message_in.getValueS32("button"); - EMouseButton btn = MB_MOUSE_BUTTON_LEFT; - if (button == 0) btn = MB_MOUSE_BUTTON_LEFT; - if (button == 1) btn = MB_MOUSE_BUTTON_RIGHT; - if (button == 2) btn = MB_MOUSE_BUTTON_MIDDLE; - - if (event == "down") - { - mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); - mLLCEFLib->setFocus(true); - - std::stringstream str; - str << "Mouse down at = " << x << ", " << y; - postDebugMessage(str.str()); - } - else if (event == "up") - { - mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); - - std::stringstream str; - str << "Mouse up at = " << x << ", " << y; - postDebugMessage(str.str()); - } - else if (event == "double_click") - { - // TODO: do we need this ? - } - else - { - mLLCEFLib->mouseMove(x, y); - } - } - else if (message_name == "scroll_event") - { - S32 y = message_in.getValueS32("y"); - const int scaling_factor = 40; - y *= -scaling_factor; - - mLLCEFLib->mouseWheel(y); - } - else if (message_name == "text_event") - { - std::string text = message_in.getValue("text"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - unicodeInput(text, decodeModifiers(modifiers), native_key_data); - } - else if (message_name == "key_event") - { -#if LL_DARWIN - std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - if (event == "down") - { - mLLCEFLib->keyPress(key, true); - } - else if (event == "up") - { - mLLCEFLib->keyPress(key, false); - } - -#elif LL_WINDOWS - std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - // Treat unknown events as key-up for safety. - EKeyEvent key_event = KE_KEY_UP; - if (event == "down") - { - key_event = KE_KEY_DOWN; - } - else if (event == "repeat") - { - key_event = KE_KEY_REPEAT; - } - - keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); -#endif - } - else if (message_name == "enable_media_plugin_debugging") - { - mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); - } - if (message_name == "auth_response") - { - authResponse(message_in); - } - } - else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) - { - if (message_name == "set_page_zoom_factor") - { - F32 factor = (F32)message_in.getValueReal("factor"); - mLLCEFLib->setPageZoom(factor); - } - if (message_name == "browse_stop") - { - mLLCEFLib->stop(); - } - else if (message_name == "browse_reload") - { - bool ignore_cache = true; - mLLCEFLib->reload(ignore_cache); - } - else if (message_name == "browse_forward") - { - mLLCEFLib->goForward(); - } - else if (message_name == "browse_back") - { - mLLCEFLib->goBack(); - } - else if (message_name == "cookies_enabled") - { - mCookiesEnabled = message_in.getValueBoolean("enable"); -std::stringstream str; -str << "@@@@@@@##### cookies_enabled - mCookiesEnabled = " << mCookiesEnabled; -postDebugMessage(str.str()); - - } - else if (message_name == "plugins_enabled") - { - mPluginsEnabled = message_in.getValueBoolean("enable"); - } - else if (message_name == "javascript_enabled") - { - mJavascriptEnabled = message_in.getValueBoolean("enable"); - } - } - else - { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } -} - -EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) -{ - int result = 0; - - if (modifiers.find("shift") != std::string::npos) - result |= KM_MODIFIER_SHIFT; - - if (modifiers.find("alt") != std::string::npos) - result |= KM_MODIFIER_ALT; - - if (modifiers.find("control") != std::string::npos) - result |= KM_MODIFIER_CONTROL; - - if (modifiers.find("meta") != std::string::npos) - result |= KM_MODIFIER_META; - - return (EKeyboardModifier)result; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers) -{ - native_scan_code = 0; - native_virtual_key = 0; - native_modifiers = 0; - - if (native_key_data.isMap()) - { -#if LL_DARWIN - native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#elif LL_WINDOWS - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - // TODO: I don't think we need to do anything with native modifiers here -- please verify -#endif - }; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) -{ -#if LL_DARWIN - std::string utf8_text; - - if (key < 128) - { - utf8_text = (char)key; - } - - switch ((KEY)key) - { - case KEY_BACKSPACE: utf8_text = (char)8; break; - case KEY_TAB: utf8_text = (char)9; break; - case KEY_RETURN: utf8_text = (char)13; break; - case KEY_PAD_RETURN: utf8_text = (char)13; break; - case KEY_ESCAPE: utf8_text = (char)27; break; - - default: - break; - } - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); -#elif LL_WINDOWS - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); -#endif -}; - -void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) -{ -#if LL_DARWIN - mLLCEFLib->keyPress(utf8str[0], true); -#elif LL_WINDOWS - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); -#endif -}; - -//////////////////////////////////////////////////////////////////////////////// -// -bool MediaPluginCEF::init() -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", "CEF Plugin"); - sendMessage(message); - - return true; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data) -{ - MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); - *plugin_send_func = MediaPluginCEF::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; -} - + + LLCEFLibSettings settings; + settings.inital_width = 1024; + settings.inital_height = 1024; + settings.plugins_enabled = mPluginsEnabled; + settings.javascript_enabled = mJavascriptEnabled; + settings.cookies_enabled = mCookiesEnabled; + settings.accept_language_list = mHostLanguage; + settings.user_agent_substring = mUserAgentSubtring; + + std::stringstream str; + str << "@@@@@@@@@@ Initializing with = user_agent_substring = " << mUserAgentSubtring; + postDebugMessage(str.str()); + + bool result = mLLCEFLib->init(settings); + if (!result) + { + // if this fails, the media system in viewer will put up a message + } + + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_BGRA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", false); + sendMessage(message); + } + else if (message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if (!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if (iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + mLLCEFLib->setSize(mWidth, mHeight); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if (message_name == "set_language_code") + { + mHostLanguage = message_in.getValue("language"); + } + else if (message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + mLLCEFLib->navigate(uri); + } + else if (message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + //std::string modifiers = message_in.getValue("modifiers"); + + S32 button = message_in.getValueS32("button"); + EMouseButton btn = MB_MOUSE_BUTTON_LEFT; + if (button == 0) btn = MB_MOUSE_BUTTON_LEFT; + if (button == 1) btn = MB_MOUSE_BUTTON_RIGHT; + if (button == 2) btn = MB_MOUSE_BUTTON_MIDDLE; + + if (event == "down") + { + mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); + mLLCEFLib->setFocus(true); + + std::stringstream str; + str << "Mouse down at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "up") + { + mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); + + std::stringstream str; + str << "Mouse up at = " << x << ", " << y; + postDebugMessage(str.str()); + } + else if (event == "double_click") + { + // TODO: do we need this ? + } + else + { + mLLCEFLib->mouseMove(x, y); + } + } + else if (message_name == "scroll_event") + { + S32 y = message_in.getValueS32("y"); + const int scaling_factor = 40; + y *= -scaling_factor; + + mLLCEFLib->mouseWheel(y); + } + else if (message_name == "text_event") + { + std::string text = message_in.getValue("text"); + std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + unicodeInput(text, decodeModifiers(modifiers), native_key_data); + } + else if (message_name == "key_event") + { +#if LL_DARWIN + std::string event = message_in.getValue("event"); + S32 key = message_in.getValueS32("key"); + if (event == "down") + { + mLLCEFLib->keyPress(key, true); + } + else if (event == "up") + { + mLLCEFLib->keyPress(key, false); + } + +#elif LL_WINDOWS + std::string event = message_in.getValue("event"); + S32 key = message_in.getValueS32("key"); + std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + + // Treat unknown events as key-up for safety. + EKeyEvent key_event = KE_KEY_UP; + if (event == "down") + { + key_event = KE_KEY_DOWN; + } + else if (event == "repeat") + { + key_event = KE_KEY_REPEAT; + } + + keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); +#endif + } + else if (message_name == "enable_media_plugin_debugging") + { + mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); + } + if (message_name == "auth_response") + { + authResponse(message_in); + } + } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if (message_name == "set_page_zoom_factor") + { + F32 factor = (F32)message_in.getValueReal("factor"); + mLLCEFLib->setPageZoom(factor); + } + if (message_name == "browse_stop") + { + mLLCEFLib->stop(); + } + else if (message_name == "browse_reload") + { + bool ignore_cache = true; + mLLCEFLib->reload(ignore_cache); + } + else if (message_name == "browse_forward") + { + mLLCEFLib->goForward(); + } + else if (message_name == "browse_back") + { + mLLCEFLib->goBack(); + } + else if (message_name == "cookies_enabled") + { + mCookiesEnabled = message_in.getValueBoolean("enable"); + } + else if (message_name == "set_user_agent") + { + mUserAgentSubtring = message_in.getValue("user_agent"); + + std::stringstream str; + str << "@@@@@@@@@@ setting mUserAgentSubtring = " << mUserAgentSubtring; + postDebugMessage(str.str()); + } + else if (message_name == "plugins_enabled") + { + mPluginsEnabled = message_in.getValueBoolean("enable"); + } + else if (message_name == "javascript_enabled") + { + mJavascriptEnabled = message_in.getValueBoolean("enable"); + } + } + else + { + //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } +} + +EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) +{ + int result = 0; + + if (modifiers.find("shift") != std::string::npos) + result |= KM_MODIFIER_SHIFT; + + if (modifiers.find("alt") != std::string::npos) + result |= KM_MODIFIER_ALT; + + if (modifiers.find("control") != std::string::npos) + result |= KM_MODIFIER_CONTROL; + + if (modifiers.find("meta") != std::string::npos) + result |= KM_MODIFIER_META; + + return (EKeyboardModifier)result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers) +{ + native_scan_code = 0; + native_virtual_key = 0; + native_modifiers = 0; + + if (native_key_data.isMap()) + { +#if LL_DARWIN + native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); + native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); +#elif LL_WINDOWS + native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + // TODO: I don't think we need to do anything with native modifiers here -- please verify +#endif + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +{ +#if LL_DARWIN + std::string utf8_text; + + if (key < 128) + { + utf8_text = (char)key; + } + + switch ((KEY)key) + { + case KEY_BACKSPACE: utf8_text = (char)8; break; + case KEY_TAB: utf8_text = (char)9; break; + case KEY_RETURN: utf8_text = (char)13; break; + case KEY_PAD_RETURN: utf8_text = (char)13; break; + case KEY_ESCAPE: utf8_text = (char)27; break; + + default: + break; + } + + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); + + mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); +#elif LL_WINDOWS + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); +#endif +}; + +void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +{ +#if LL_DARWIN + mLLCEFLib->keyPress(utf8str[0], true); +#elif LL_WINDOWS + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); +#endif +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginCEF::init() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", "CEF Plugin"); + sendMessage(message); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data) +{ + MediaPluginCEF* self = new MediaPluginCEF(host_send_func, host_user_data); + *plugin_send_func = MediaPluginCEF::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + -- cgit v1.2.3 From 7505501aea76e014b205d64accf89a9d30abac3a Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 1 Sep 2015 17:43:30 -0700 Subject: get update llceflib with cookie/cache code and implement cache/cookie folders in viewer --- indra/media_plugins/cef/media_plugin_cef.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index fcedc3355d..a0a80e3a3a 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -83,6 +83,8 @@ private: std::string mAuthUsername; std::string mAuthPassword; bool mAuthOK; + std::string mCachePath; + std::string mCookiePath; LLCEFLib* mLLCEFLib; }; @@ -104,6 +106,8 @@ MediaPluginBase(host_send_func, host_user_data) mAuthUsername = ""; mAuthPassword = ""; mAuthOK = false; + mCachePath = ""; + mCookiePath = ""; mLLCEFLib = new LLCEFLib(); } @@ -338,6 +342,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.plugins_enabled = mPluginsEnabled; settings.javascript_enabled = mJavascriptEnabled; settings.cookies_enabled = mCookiesEnabled; + settings.cache_path = mCachePath; + settings.cookie_store_path = mCookiePath; settings.accept_language_list = mHostLanguage; settings.user_agent_substring = mUserAgentSubtring; @@ -363,6 +369,16 @@ void MediaPluginCEF::receiveMessage(const char* message_string) message.setValueBoolean("coords_opengl", false); sendMessage(message); } + else if (message_name == "set_user_data_path") + { + std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter + mCachePath = user_data_path + "cef_cache"; + mCookiePath = user_data_path + "cef_cookies"; + + std::stringstream str; + str << "@@@@@@@@@@ setting data paths to " << mCachePath << " and " << mCookiePath; + postDebugMessage(str.str()); + } else if (message_name == "size_change") { std::string name = message_in.getValue("name"); -- cgit v1.2.3 From d44eeb48d380215bae0d036976f6daa11082af07 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 1 Sep 2015 17:46:29 -0700 Subject: Remove debugging crud --- indra/media_plugins/cef/media_plugin_cef.cpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index a0a80e3a3a..f49187a897 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -83,7 +83,7 @@ private: std::string mAuthUsername; std::string mAuthPassword; bool mAuthOK; - std::string mCachePath; + std::string mCachePath; std::string mCookiePath; LLCEFLib* mLLCEFLib; }; @@ -106,7 +106,7 @@ MediaPluginBase(host_send_func, host_user_data) mAuthUsername = ""; mAuthPassword = ""; mAuthOK = false; - mCachePath = ""; + mCachePath = ""; mCookiePath = ""; mLLCEFLib = new LLCEFLib(); } @@ -347,10 +347,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.accept_language_list = mHostLanguage; settings.user_agent_substring = mUserAgentSubtring; - std::stringstream str; - str << "@@@@@@@@@@ Initializing with = user_agent_substring = " << mUserAgentSubtring; - postDebugMessage(str.str()); - bool result = mLLCEFLib->init(settings); if (!result) { @@ -369,15 +365,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string) message.setValueBoolean("coords_opengl", false); sendMessage(message); } - else if (message_name == "set_user_data_path") - { - std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter - mCachePath = user_data_path + "cef_cache"; - mCookiePath = user_data_path + "cef_cookies"; - - std::stringstream str; - str << "@@@@@@@@@@ setting data paths to " << mCachePath << " and " << mCookiePath; - postDebugMessage(str.str()); + else if (message_name == "set_user_data_path") + { + std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter + mCachePath = user_data_path + "cef_cache"; + mCookiePath = user_data_path + "cef_cookies"; } else if (message_name == "size_change") { @@ -553,10 +545,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (message_name == "set_user_agent") { mUserAgentSubtring = message_in.getValue("user_agent"); - - std::stringstream str; - str << "@@@@@@@@@@ setting mUserAgentSubtring = " << mUserAgentSubtring; - postDebugMessage(str.str()); } else if (message_name == "plugins_enabled") { -- cgit v1.2.3 From 33da4d9d5dd05bbc9dc232525b59017f7ecbbcdd Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 2 Sep 2015 17:31:40 -0700 Subject: Add support for copy/cut/paste into and out of browser (Note - feature in LLQtWebKit (canPaste, canCut etc.) not present so right click menu always enables options --- indra/media_plugins/cef/media_plugin_cef.cpp | 71 +++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f49187a897..f51a2715bb 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -64,6 +64,7 @@ private: void onLoadStartCallback(); void onLoadEndCallback(int httpStatusCode); void onNavigateURLCallback(std::string url); + void onExternalTargetLinkCallback(std::string url); bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); void postDebugMessage(const std::string& msg); @@ -74,6 +75,8 @@ private: void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); + void checkEditState(); + bool mEnableMediaPluginDebugging; std::string mHostLanguage; bool mCookiesEnabled; @@ -83,6 +86,9 @@ private: std::string mAuthUsername; std::string mAuthPassword; bool mAuthOK; + bool mCanCut; + bool mCanCopy; + bool mCanPaste; std::string mCachePath; std::string mCookiePath; LLCEFLib* mLLCEFLib; @@ -106,6 +112,9 @@ MediaPluginBase(host_send_func, host_user_data) mAuthUsername = ""; mAuthPassword = ""; mAuthOK = false; + mCanCut = false; + mCanCopy = false; + mCanPaste = false; mCachePath = ""; mCookiePath = ""; mLLCEFLib = new LLCEFLib(); @@ -217,6 +226,13 @@ void MediaPluginCEF::onNavigateURLCallback(std::string url) sendMessage(message); } +//////////////////////////////////////////////////////////////////////////////// +// triggered when user clicks link with "external" attribute +void MediaPluginCEF::onExternalTargetLinkCallback(std::string url) +{ + +} + //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password) @@ -279,6 +295,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (message_name == "idle") { mLLCEFLib->update(); + + // this seems bad but unless the state changes (it won't until we figure out + // how to get CEF to tell us if copy/cut/paste is available) then this function + // will return immediately + checkEditState(); } else if (message_name == "cleanup") { @@ -335,6 +356,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); + mLLCEFLib->setOnExternalTargetLinkCallback(boost::bind(&MediaPluginCEF::onExternalTargetLinkCallback, this, _1)); LLCEFLibSettings settings; settings.inital_width = 1024; @@ -342,8 +364,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.plugins_enabled = mPluginsEnabled; settings.javascript_enabled = mJavascriptEnabled; settings.cookies_enabled = mCookiesEnabled; - settings.cache_path = mCachePath; settings.cookie_store_path = mCookiePath; + settings.cache_enabled = true; + settings.cache_path = mCachePath; settings.accept_language_list = mHostLanguage; settings.user_agent_substring = mUserAgentSubtring; @@ -513,6 +536,18 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { authResponse(message_in); } + if (message_name == "edit_cut") + { + mLLCEFLib->editCut(); + } + if (message_name == "edit_copy") + { + mLLCEFLib->editCopy(); + } + if (message_name == "edit_paste") + { + mLLCEFLib->editPaste(); + } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) { @@ -653,6 +688,40 @@ void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier #endif }; +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::checkEditState() +{ + bool can_cut = mLLCEFLib->editCanCut(); + bool can_copy = mLLCEFLib->editCanCopy(); + bool can_paste = mLLCEFLib->editCanPaste(); + + if ((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); + + if (can_cut != mCanCut) + { + mCanCut = can_cut; + message.setValueBoolean("cut", can_cut); + } + + if (can_copy != mCanCopy) + { + mCanCopy = can_copy; + message.setValueBoolean("copy", can_copy); + } + + if (can_paste != mCanPaste) + { + mCanPaste = can_paste; + message.setValueBoolean("paste", can_paste); + } + + sendMessage(message); + } +} + //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::init() -- cgit v1.2.3 From 236b3b9f842c86e1f176068ab70b82f83874e2ab Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 3 Sep 2015 18:16:46 -0700 Subject: support for external links and location_changed messages --- indra/media_plugins/cef/media_plugin_cef.cpp | 37 +++++++++++++++------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f51a2715bb..97364d949a 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -63,8 +63,8 @@ private: void onTitleChangeCallback(std::string title); void onLoadStartCallback(); void onLoadEndCallback(int httpStatusCode); - void onNavigateURLCallback(std::string url); - void onExternalTargetLinkCallback(std::string url); + void onAddressChangeCallback(std::string url); + void onNavigateURLCallback(std::string url, std::string target); bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); void postDebugMessage(const std::string& msg); @@ -157,16 +157,6 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int width, int } } -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); - message.setValue("uri", url); - message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to - sendMessage(message); -} - //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onConsoleMessageCallback(std::string message, std::string source, int line) @@ -219,7 +209,7 @@ void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onNavigateURLCallback(std::string url) +void MediaPluginCEF::onAddressChangeCallback(std::string url) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); message.setValue("uri", url); @@ -227,10 +217,24 @@ void MediaPluginCEF::onNavigateURLCallback(std::string url) } //////////////////////////////////////////////////////////////////////////////// -// triggered when user clicks link with "external" attribute -void MediaPluginCEF::onExternalTargetLinkCallback(std::string url) +// +void MediaPluginCEF::onNavigateURLCallback(std::string url, std::string target) { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); + message.setValue("uri", url); + message.setValue("target", target); + message.setValue("uuid", ""); // not used right now + sendMessage(message); +} +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + message.setValue("uri", url); + message.setValue("nav_type", "clicked"); // TODO: differentiate between click and navigate to + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// @@ -354,9 +358,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); - mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1)); + mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1, _2)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); - mLLCEFLib->setOnExternalTargetLinkCallback(boost::bind(&MediaPluginCEF::onExternalTargetLinkCallback, this, _1)); LLCEFLibSettings settings; settings.inital_width = 1024; -- cgit v1.2.3 From 83f26facbf717504b0ab4677cb6dd64534f6b844 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 3 Sep 2015 19:59:57 -0700 Subject: point to new version of llceflib with fixed support for secondlife:// URLs --- indra/media_plugins/cef/media_plugin_cef.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 97364d949a..f45ab5575c 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -52,7 +52,6 @@ public: /*virtual*/ void receiveMessage(const char* message_string); - private: bool init(); -- cgit v1.2.3 From 52e56af35eed8ffff522e13e028206243e1302f6 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 10 Sep 2015 15:11:28 -0700 Subject: Pull in LLCefLib with inverted output switched on and change viewer to uninvert things --- indra/media_plugins/cef/media_plugin_cef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f45ab5575c..e812341f8c 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -387,7 +387,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) message.setValueU32("internalformat", GL_RGB); message.setValueU32("format", GL_BGRA); message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", false); + message.setValueBoolean("coords_opengl", true); sendMessage(message); } else if (message_name == "set_user_data_path") -- cgit v1.2.3 From 6a119e327d7b7196e03581561545fb8501c79067 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 16 Sep 2015 22:14:55 -0700 Subject: tmp chckin - still needs latest llceflib to build --- indra/media_plugins/cef/media_plugin_cef.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index e812341f8c..c668076d93 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -503,11 +503,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) S32 key = message_in.getValueS32("key"); if (event == "down") { - mLLCEFLib->keyPress(key, true); + //mLLCEFLib->keyPress(key, true); + mLLCEFLib->keyboardEvent(KE_KEY_DOWN, (uint32_t)key, 0, KM_MODIFIER_NONE, 0, 0, 0); + } else if (event == "up") { - mLLCEFLib->keyPress(key, false); + //mLLCEFLib->keyPress(key, false); + mLLCEFLib->keyboardEvent(KE_KEY_UP, (uint32_t)key, 0, KM_MODIFIER_NONE, 0, 0, 0); } #elif LL_WINDOWS @@ -681,7 +684,8 @@ void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier mo void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN - mLLCEFLib->keyPress(utf8str[0], true); + //mLLCEFLib->keyPress(utf8str[0], true); + mLLCEFLib->keyboardEvent(KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, KM_MODIFIER_NONE, 0, 0, 0); #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); -- cgit v1.2.3 From 3e20770f350652b91fd4b4a5bbef9b5f03561310 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Sat, 26 Sep 2015 18:53:17 -0700 Subject: Point to new third party llcef package and fix typo in interface --- indra/media_plugins/cef/media_plugin_cef.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index c668076d93..ca7339669b 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -361,8 +361,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); LLCEFLibSettings settings; - settings.inital_width = 1024; - settings.inital_height = 1024; + settings.initial_width = 1024; + settings.initial_height = 1024; settings.plugins_enabled = mPluginsEnabled; settings.javascript_enabled = mJavascriptEnabled; settings.cookies_enabled = mCookiesEnabled; -- cgit v1.2.3 From a0c0bc6b4033acf8d395708b5515215699905acc Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 30 Sep 2015 16:34:49 -0700 Subject: Update CEF media plugin to reflect changes in LLCEFLib --- indra/media_plugins/cef/media_plugin_cef.cpp | 76 ++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 21 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index ca7339669b..da39cd353b 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -65,14 +65,15 @@ private: void onAddressChangeCallback(std::string url); void onNavigateURLCallback(std::string url, std::string target); bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); + void onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle); void postDebugMessage(const std::string& msg); void authResponse(LLPluginMessage &message); - EKeyboardModifier decodeModifiers(std::string &modifiers); + LLCEFLib::EKeyboardModifier decodeModifiers(std::string &modifiers); void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); - void keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data); - void unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data); + void keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data); + void unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data); void checkEditState(); @@ -259,6 +260,38 @@ bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::strin return mAuthOK; } +void MediaPluginCEF::onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle) +{ + std::string name = ""; + + switch (type) + { + case LLCEFLib::CT_POINTER: + name = "arrow"; + break; + case LLCEFLib::CT_IBEAM: + name = "ibeam"; + break; + case LLCEFLib::CT_NORTHSOUTHRESIZE: + name = "splitv"; + break; + case LLCEFLib::CT_EASTWESTRESIZE: + name = "splith"; + break; + case LLCEFLib::CT_HAND: + name = "hand"; + break; + + default: + LL_WARNS() << "Unknown cursor ID: " << (int)type << LL_ENDL; + break; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed"); + message.setValue("name", name); + sendMessage(message); +} + void MediaPluginCEF::authResponse(LLPluginMessage &message) { mAuthOK = message.getValueBoolean("ok"); @@ -359,8 +392,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1, _2)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); + mLLCEFLib->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2)); - LLCEFLibSettings settings; + LLCEFLib::LLCEFLibSettings settings; settings.initial_width = 1024; settings.initial_height = 1024; settings.plugins_enabled = mPluginsEnabled; @@ -449,14 +483,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) //std::string modifiers = message_in.getValue("modifiers"); S32 button = message_in.getValueS32("button"); - EMouseButton btn = MB_MOUSE_BUTTON_LEFT; - if (button == 0) btn = MB_MOUSE_BUTTON_LEFT; - if (button == 1) btn = MB_MOUSE_BUTTON_RIGHT; - if (button == 2) btn = MB_MOUSE_BUTTON_MIDDLE; + LLCEFLib::EMouseButton btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; + if (button == 0) btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; + if (button == 1) btn = LLCEFLib::MB_MOUSE_BUTTON_RIGHT; + if (button == 2) btn = LLCEFLib::MB_MOUSE_BUTTON_MIDDLE; if (event == "down") { - mLLCEFLib->mouseButton(btn, ME_MOUSE_DOWN, x, y); + mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y); mLLCEFLib->setFocus(true); std::stringstream str; @@ -465,7 +499,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (event == "up") { - mLLCEFLib->mouseButton(btn, ME_MOUSE_UP, x, y); + mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y); std::stringstream str; str << "Mouse up at = " << x << ", " << y; @@ -520,14 +554,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) LLSD native_key_data = message_in.getValueLLSD("native_key_data"); // Treat unknown events as key-up for safety. - EKeyEvent key_event = KE_KEY_UP; + LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP; if (event == "down") { - key_event = KE_KEY_DOWN; + key_event = LLCEFLib::KE_KEY_DOWN; } else if (event == "repeat") { - key_event = KE_KEY_REPEAT; + key_event = LLCEFLib::KE_KEY_REPEAT; } keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); @@ -602,23 +636,23 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } } -EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) +LLCEFLib::EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) { int result = 0; if (modifiers.find("shift") != std::string::npos) - result |= KM_MODIFIER_SHIFT; + result |= LLCEFLib::KM_MODIFIER_SHIFT; if (modifiers.find("alt") != std::string::npos) - result |= KM_MODIFIER_ALT; + result |= LLCEFLib::KM_MODIFIER_ALT; if (modifiers.find("control") != std::string::npos) - result |= KM_MODIFIER_CONTROL; + result |= LLCEFLib::KM_MODIFIER_CONTROL; if (modifiers.find("meta") != std::string::npos) - result |= KM_MODIFIER_META; + result |= LLCEFLib::KM_MODIFIER_META; - return (EKeyboardModifier)result; + return (LLCEFLib::EKeyboardModifier)result; } //////////////////////////////////////////////////////////////////////////////// @@ -645,7 +679,7 @@ void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& nat //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN std::string utf8_text; @@ -681,7 +715,7 @@ void MediaPluginCEF::keyEvent(EKeyEvent key_event, int key, EKeyboardModifier mo #endif }; -void MediaPluginCEF::unicodeInput(const std::string &utf8str, EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN //mLLCEFLib->keyPress(utf8str[0], true); -- cgit v1.2.3 From ca871f25e921dd2fd3ea7c7b7b8a8c53bd4f7eb1 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 1 Oct 2015 09:57:53 -0700 Subject: Fix OS X missing scope qualifiers --- indra/media_plugins/cef/media_plugin_cef.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index da39cd353b..9b87eca726 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -538,13 +538,13 @@ void MediaPluginCEF::receiveMessage(const char* message_string) if (event == "down") { //mLLCEFLib->keyPress(key, true); - mLLCEFLib->keyboardEvent(KE_KEY_DOWN, (uint32_t)key, 0, KM_MODIFIER_NONE, 0, 0, 0); + mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); } else if (event == "up") { //mLLCEFLib->keyPress(key, false); - mLLCEFLib->keyboardEvent(KE_KEY_UP, (uint32_t)key, 0, KM_MODIFIER_NONE, 0, 0, 0); + mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_UP, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); } #elif LL_WINDOWS @@ -719,7 +719,7 @@ void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboar { #if LL_DARWIN //mLLCEFLib->keyPress(utf8str[0], true); - mLLCEFLib->keyboardEvent(KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, KM_MODIFIER_NONE, 0, 0, 0); + mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); -- cgit v1.2.3 From cb7f84a470d7afeb1501cf5514333c6ee15d96df Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 2 Oct 2015 11:14:28 -0700 Subject: MAINT-5687: Remove old webkit from the make files and the repo. Ensure that it is no longer meaningfully referenced. --- indra/media_plugins/webkit/CMakeLists.txt | 132 -- .../media_plugins/webkit/dummy_volume_catcher.cpp | 58 - .../media_plugins/webkit/linux_volume_catcher.cpp | 468 ------- .../webkit/linux_volume_catcher_pa_syms.inc | 21 - .../webkit/linux_volume_catcher_paglib_syms.inc | 6 - indra/media_plugins/webkit/mac_volume_catcher.cpp | 275 ---- indra/media_plugins/webkit/media_plugin_webkit.cpp | 1481 -------------------- indra/media_plugins/webkit/volume_catcher.h | 54 - .../webkit/windows_volume_catcher.cpp | 147 -- indra/media_plugins/winmmshim/CMakeLists.txt | 3 - 10 files changed, 2645 deletions(-) delete mode 100755 indra/media_plugins/webkit/CMakeLists.txt delete mode 100755 indra/media_plugins/webkit/dummy_volume_catcher.cpp delete mode 100755 indra/media_plugins/webkit/linux_volume_catcher.cpp delete mode 100755 indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc delete mode 100755 indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc delete mode 100755 indra/media_plugins/webkit/mac_volume_catcher.cpp delete mode 100755 indra/media_plugins/webkit/media_plugin_webkit.cpp delete mode 100755 indra/media_plugins/webkit/volume_catcher.h delete mode 100755 indra/media_plugins/webkit/windows_volume_catcher.cpp (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt deleted file mode 100755 index 5a8fe90bdd..0000000000 --- a/indra/media_plugins/webkit/CMakeLists.txt +++ /dev/null @@ -1,132 +0,0 @@ -# -*- cmake -*- - -project(media_plugin_webkit) - -include(00-Common) -include(LLCommon) -include(LLImage) -include(LLPlugin) -include(LLMath) -include(LLRender) -include(LLWindow) -include(UI) -include(Linking) -include(PluginAPI) -include(MediaPluginBase) -include(OpenGL) -include(PulseAudio) - -include(WebKitLibPlugin) - -include_directories( - ${PULSEAUDIO_INCLUDE_DIRS} - ${LLPLUGIN_INCLUDE_DIRS} - ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} - ${LLCOMMON_INCLUDE_DIRS} - ${LLMATH_INCLUDE_DIRS} - ${LLIMAGE_INCLUDE_DIRS} - ${LLRENDER_INCLUDE_DIRS} - ${LLWINDOW_INCLUDE_DIRS} - ${LLQTWEBKIT_INCLUDE_DIR} -) -include_directories(SYSTEM - ${LLCOMMON_SYSTEM_INCLUDE_DIRS} - ) - - -### media_plugin_webkit - -if(NOT WORD_SIZE EQUAL 32) - if(WINDOWS) - add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT WORD_SIZE EQUAL 32) - -set(media_plugin_webkit_SOURCE_FILES - media_plugin_webkit.cpp - ) - -set(media_plugin_webkit_HEADER_FILES - volume_catcher.h - ) - -set(media_plugin_webkit_LINK_LIBRARIES - ${LLPLUGIN_LIBRARIES} - ${MEDIA_PLUGIN_BASE_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ${WEBKIT_PLUGIN_LIBRARIES} - ${PLUGIN_API_WINDOWS_LIBRARIES} - ${PULSEAUDIO_LIBRARIES} -) - -# Select which VolumeCatcher implementation to use -if (LINUX) - if (PULSEAUDIO_FOUND) - list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp) - else (PULSEAUDIO_FOUND) - list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp) - endif (PULSEAUDIO_FOUND) - list(APPEND media_plugin_webkit_LINK_LIBRARIES - ${UI_LIBRARIES} # for glib/GTK - ) -elseif (DARWIN) - list(APPEND media_plugin_webkit_SOURCE_FILES mac_volume_catcher.cpp) - find_library(CORESERVICES_LIBRARY CoreServices) - find_library(AUDIOUNIT_LIBRARY AudioUnit) - list(APPEND media_plugin_webkit_LINK_LIBRARIES - ${CORESERVICES_LIBRARY} # for Component Manager calls - ${AUDIOUNIT_LIBRARY} # for AudioUnit calls - ) -elseif (WINDOWS) - list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp) -endif (LINUX) - -set_source_files_properties(${media_plugin_webkit_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND media_plugin_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES}) - -add_library(media_plugin_webkit - SHARED - ${media_plugin_webkit_SOURCE_FILES} -) - -target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES}) - -add_dependencies(media_plugin_webkit - ${LLPLUGIN_LIBRARIES} - ${MEDIA_PLUGIN_BASE_LIBRARIES} - ${LLCOMMON_LIBRARIES} -) - -if (WINDOWS) - set_target_properties( - media_plugin_webkit - PROPERTIES - LINK_FLAGS "/MANIFEST:NO" - ) -endif (WINDOWS) - -if (DARWIN) - # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name - set_target_properties( - media_plugin_webkit - PROPERTIES - PREFIX "" - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path" - LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" - ) - - # copy the webkit dylib to the build directory -# add_custom_command( -# TARGET media_plugin_webkit POST_BUILD -# # OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libllqtwebkit.dylib -# COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ -# DEPENDS media_plugin_webkit ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib -# ) - -endif (DARWIN) - diff --git a/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/indra/media_plugins/webkit/dummy_volume_catcher.cpp deleted file mode 100755 index d54b31b2ae..0000000000 --- a/indra/media_plugins/webkit/dummy_volume_catcher.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file dummy_volume_catcher.cpp - * @brief A null implementation of the "VolumeCatcher" class for platforms where it's not implemented yet. - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "volume_catcher.h" - - -class VolumeCatcherImpl -{ -}; - -///////////////////////////////////////////////////// - -VolumeCatcher::VolumeCatcher() -{ - pimpl = NULL; -} - -VolumeCatcher::~VolumeCatcher() -{ -} - -void VolumeCatcher::setVolume(F32 volume) -{ -} - -void VolumeCatcher::setPan(F32 pan) -{ -} - -void VolumeCatcher::pump() -{ -} - diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp deleted file mode 100755 index 91be3a89e9..0000000000 --- a/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/** - * @file linux_volume_catcher.cpp - * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -/* - The high-level design is as follows: - 1) Connect to the PulseAudio daemon - 2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins) - 3) Examine any new audio player's PID to see if it belongs to our own process - 4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance) - 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call - */ - -#include "linden_common.h" - -#include "volume_catcher.h" - - -extern "C" { -#include -#include - -#include -#include -#include -#include // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. - -#include "apr_pools.h" -#include "apr_dso.h" -} - -//////////////////////////////////////////////////// - -#define DEBUGMSG(...) do {} while(0) -#define INFOMSG(...) do {} while(0) -#define WARNMSG(...) do {} while(0) - -#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) RTN (*ll##PASYM)(__VA_ARGS__) = NULL -#include "linux_volume_catcher_pa_syms.inc" -#include "linux_volume_catcher_paglib_syms.inc" -#undef LL_PA_SYM - -static bool sSymsGrabbed = false; -static apr_pool_t *sSymPADSOMemoryPool = NULL; -static apr_dso_handle_t *sSymPADSOHandleG = NULL; - -bool grab_pa_syms(std::string pulse_dso_name) -{ - if (sSymsGrabbed) - { - // already have grabbed good syms - return true; - } - - bool sym_error = false; - bool rtn = false; - apr_status_t rv; - apr_dso_handle_t *sSymPADSOHandle = NULL; - -#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0) - - //attempt to load the shared library - apr_pool_create(&sSymPADSOMemoryPool, NULL); - - if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle, - pulse_dso_name.c_str(), - sSymPADSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", pulse_dso_name.c_str()); - -#include "linux_volume_catcher_pa_syms.inc" -#include "linux_volume_catcher_paglib_syms.inc" - - if ( sSymPADSOHandle ) - { - sSymPADSOHandleG = sSymPADSOHandle; - sSymPADSOHandle = NULL; - } - - rtn = !sym_error; - } - else - { - INFOMSG("Couldn't load DSO: %s", pulse_dso_name.c_str()); - rtn = false; // failure - } - - if (sym_error) - { - WARNMSG("Failed to find necessary symbols in PulseAudio libraries."); - } -#undef LL_PA_SYM - - sSymsGrabbed = rtn; - return rtn; -} - - -void ungrab_pa_syms() -{ - // should be safe to call regardless of whether we've - // actually grabbed syms. - - if ( sSymPADSOHandleG ) - { - apr_dso_unload(sSymPADSOHandleG); - sSymPADSOHandleG = NULL; - } - - if ( sSymPADSOMemoryPool ) - { - apr_pool_destroy(sSymPADSOMemoryPool); - sSymPADSOMemoryPool = NULL; - } - - // NULL-out all of the symbols we'd grabbed -#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0) -#include "linux_volume_catcher_pa_syms.inc" -#include "linux_volume_catcher_paglib_syms.inc" -#undef LL_PA_SYM - - sSymsGrabbed = false; -} -//////////////////////////////////////////////////// - -// PulseAudio requires a chain of callbacks with C linkage -extern "C" { - void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata); - void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata); - void callback_context_state(pa_context *context, void *userdata); -} - - -class VolumeCatcherImpl -{ -public: - VolumeCatcherImpl(); - ~VolumeCatcherImpl(); - - void setVolume(F32 volume); - void pump(void); - - // for internal use - can't be private because used from our C callbacks - - bool loadsyms(std::string pulse_dso_name); - void init(); - void cleanup(); - - void update_all_volumes(F32 volume); - void update_index_volume(U32 index, F32 volume); - void connected_okay(); - - std::set mSinkInputIndices; - std::map mSinkInputNumChannels; - F32 mDesiredVolume; - pa_glib_mainloop *mMainloop; - pa_context *mPAContext; - bool mConnected; - bool mGotSyms; -}; - -VolumeCatcherImpl::VolumeCatcherImpl() - : mDesiredVolume(0.0f), - mMainloop(NULL), - mPAContext(NULL), - mConnected(false), - mGotSyms(false) -{ - init(); -} - -VolumeCatcherImpl::~VolumeCatcherImpl() -{ - cleanup(); -} - -bool VolumeCatcherImpl::loadsyms(std::string pulse_dso_name) -{ - return grab_pa_syms(pulse_dso_name); -} - -void VolumeCatcherImpl::init() -{ - // try to be as defensive as possible because PA's interface is a - // bit fragile and (for our purposes) we'd rather simply not function - // than crash - - // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in - // libpulse.so.0 - this isn't a great assumption, and the two DSOs should - // probably be loaded separately. Our Linux DSO framework needs refactoring, - // we do this sort of thing a lot with practically identical logic... - mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); - if (!mGotSyms) return; - - // better make double-sure glib itself is initialized properly. - if (!g_thread_supported ()) g_thread_init (NULL); - g_type_init(); - - mMainloop = llpa_glib_mainloop_new(g_main_context_default()); - if (mMainloop) - { - pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop); - if (api) - { - pa_proplist *proplist = llpa_proplist_new(); - if (proplist) - { - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust"); - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster"); - llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1"); - - // plain old pa_context_new() is broken! - mPAContext = llpa_context_new_with_proplist(api, NULL, proplist); - llpa_proplist_free(proplist); - } - } - } - - // Now we've set up a PA context and mainloop, try connecting the - // PA context to a PA daemon. - if (mPAContext) - { - llpa_context_set_state_callback(mPAContext, callback_context_state, this); - pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN? - if (llpa_context_connect(mPAContext, NULL, cflags, NULL) >= 0) - { - // Okay! We haven't definitely connected, but we - // haven't definitely failed yet. - } - else - { - // Failed to connect to PA manager... we'll leave - // things like that. Perhaps we should try again later. - } - } -} - -void VolumeCatcherImpl::cleanup() -{ - mConnected = false; - - if (mGotSyms && mPAContext) - { - llpa_context_disconnect(mPAContext); - llpa_context_unref(mPAContext); - } - mPAContext = NULL; - - if (mGotSyms && mMainloop) - { - llpa_glib_mainloop_free(mMainloop); - } - mMainloop = NULL; -} - -void VolumeCatcherImpl::setVolume(F32 volume) -{ - mDesiredVolume = volume; - - if (!mGotSyms) return; - - if (mConnected && mPAContext) - { - update_all_volumes(mDesiredVolume); - } - - pump(); -} - -void VolumeCatcherImpl::pump() -{ - gboolean may_block = FALSE; - g_main_context_iteration(g_main_context_default(), may_block); -} - -void VolumeCatcherImpl::connected_okay() -{ - pa_operation *op; - - // fetch global list of existing sinkinputs - if ((op = llpa_context_get_sink_input_info_list(mPAContext, - callback_discovered_sinkinput, - this))) - { - llpa_operation_unref(op); - } - - // subscribe to future global sinkinput changes - llpa_context_set_subscribe_callback(mPAContext, - callback_subscription_alert, - this); - if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK_INPUT), - NULL, NULL))) - { - llpa_operation_unref(op); - } -} - -void VolumeCatcherImpl::update_all_volumes(F32 volume) -{ - for (std::set::iterator it = mSinkInputIndices.begin(); - it != mSinkInputIndices.end(); ++it) - { - update_index_volume(*it, volume); - } -} - -void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume) -{ - static pa_cvolume cvol; - llpa_cvolume_set(&cvol, mSinkInputNumChannels[index], - llpa_sw_volume_from_linear(volume)); - - pa_context *c = mPAContext; - uint32_t idx = index; - const pa_cvolume *cvolumep = &cvol; - pa_context_success_cb_t cb = NULL; // okay as null - void *userdata = NULL; // okay as null - - pa_operation *op; - if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata))) - { - llpa_operation_unref(op); - } -} - - -void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata) -{ - VolumeCatcherImpl *impl = dynamic_cast((VolumeCatcherImpl*)userdata); - llassert(impl); - - if (0 == eol) - { - pa_proplist *proplist = sii->proplist; - pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID)); - - if (sinkpid == getpid()) // does the discovered sinkinput belong to this process? - { - bool is_new = (impl->mSinkInputIndices.find(sii->index) == - impl->mSinkInputIndices.end()); - - impl->mSinkInputIndices.insert(sii->index); - impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels; - - if (is_new) - { - // new! - impl->update_index_volume(sii->index, impl->mDesiredVolume); - } - else - { - // seen it already, do nothing. - } - } - } -} - -void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) -{ - VolumeCatcherImpl *impl = dynamic_cast((VolumeCatcherImpl*)userdata); - llassert(impl); - - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == - PA_SUBSCRIPTION_EVENT_REMOVE) - { - // forget this sinkinput, if we were caring about it - impl->mSinkInputIndices.erase(index); - impl->mSinkInputNumChannels.erase(index); - } - else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == - PA_SUBSCRIPTION_EVENT_NEW) - { - // ask for more info about this new sinkinput - pa_operation *op; - if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) - { - llpa_operation_unref(op); - } - } - else - { - // property change on this sinkinput - we don't care. - } - break; - - default:; - } -} - -void callback_context_state(pa_context *context, void *userdata) -{ - VolumeCatcherImpl *impl = dynamic_cast((VolumeCatcherImpl*)userdata); - llassert(impl); - - switch (llpa_context_get_state(context)) - { - case PA_CONTEXT_READY: - impl->mConnected = true; - impl->connected_okay(); - break; - case PA_CONTEXT_TERMINATED: - impl->mConnected = false; - break; - case PA_CONTEXT_FAILED: - impl->mConnected = false; - break; - default:; - } -} - -///////////////////////////////////////////////////// - -VolumeCatcher::VolumeCatcher() -{ - pimpl = new VolumeCatcherImpl(); -} - -VolumeCatcher::~VolumeCatcher() -{ - delete pimpl; - pimpl = NULL; -} - -void VolumeCatcher::setVolume(F32 volume) -{ - llassert(pimpl); - pimpl->setVolume(volume); -} - -void VolumeCatcher::setPan(F32 pan) -{ - // TODO: implement this (if possible) -} - -void VolumeCatcher::pump() -{ - llassert(pimpl); - pimpl->pump(); -} diff --git a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc deleted file mode 100755 index d806b48428..0000000000 --- a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc +++ /dev/null @@ -1,21 +0,0 @@ -// required symbols to grab -LL_PA_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api); -LL_PA_SYM(true, pa_context_disconnect, void, pa_context *c); -LL_PA_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata); -LL_PA_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata); -LL_PA_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c); -LL_PA_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist); -LL_PA_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); -LL_PA_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata); -LL_PA_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata); -LL_PA_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata); -LL_PA_SYM(true, pa_context_unref, void, pa_context *c); -LL_PA_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v); -LL_PA_SYM(true, pa_operation_unref, void, pa_operation *o); -LL_PA_SYM(true, pa_proplist_free, void, pa_proplist* p); -LL_PA_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key); -LL_PA_SYM(true, pa_proplist_new, pa_proplist*, void); -LL_PA_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value); -LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v); - -// optional symbols to grab diff --git a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc deleted file mode 100755 index abf628c96c..0000000000 --- a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc +++ /dev/null @@ -1,6 +0,0 @@ -// required symbols to grab -LL_PA_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g); -LL_PA_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g); -LL_PA_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c); - -// optional symbols to grab diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp deleted file mode 100755 index 73e5bf3da3..0000000000 --- a/indra/media_plugins/webkit/mac_volume_catcher.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/** - * @file mac_volume_catcher.cpp - * @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process. - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -/************************************************************************************************************** - This code works by using CaptureComponent to capture the "Default Output" audio component - (kAudioUnitType_Output/kAudioUnitSubType_DefaultOutput) and delegating all calls to the original component. - It does this just to keep track of all instances of the default output component, so that it can set the - kHALOutputParam_Volume parameter on all of them to adjust the output volume. -**************************************************************************************************************/ - -#include "volume_catcher.h" - -#include -#include -#include - -#if LL_DARWIN -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - -struct VolumeCatcherStorage; - -class VolumeCatcherImpl -{ -public: - - void setVolume(F32 volume); - void setPan(F32 pan); - - void setInstanceVolume(VolumeCatcherStorage *instance); - - std::list mComponentInstances; - Component mOriginalDefaultOutput; - Component mVolumeAdjuster; - - static VolumeCatcherImpl *getInstance(); -private: - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - VolumeCatcherImpl(); - static VolumeCatcherImpl *sInstance; - - // The singlar instance of this class is expected to last until the process exits. - // To ensure this, we declare the destructor here but never define it, so any code which attempts to destroy the instance will not link. - ~VolumeCatcherImpl(); - - F32 mVolume; - F32 mPan; -}; - -VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL;; - -struct VolumeCatcherStorage -{ - ComponentInstance self; - ComponentInstance delegate; -}; - -static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage); -static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self); -static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self); - -VolumeCatcherImpl *VolumeCatcherImpl::getInstance() -{ - if(!sInstance) - { - sInstance = new VolumeCatcherImpl; - } - - return sInstance; -} - -VolumeCatcherImpl::VolumeCatcherImpl() -{ - mVolume = 1.0; // default to full volume - mPan = 0.0; // and center pan - - ComponentDescription desc; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - // Find the original default output component - mOriginalDefaultOutput = FindNextComponent(NULL, &desc); - - // Register our own output component with the same parameters - mVolumeAdjuster = RegisterComponent(&desc, NewComponentRoutineUPP(volume_catcher_component_entry), 0, NULL, NULL, NULL); - - // Capture the original component, so we always get found instead. - CaptureComponent(mOriginalDefaultOutput, mVolumeAdjuster); - -} - -static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage) -{ - ComponentResult result = badComponentSelector; - VolumeCatcherStorage *storage = (VolumeCatcherStorage*)componentStorage; - - switch(cp->what) - { - case kComponentOpenSelect: -// std::cerr << "kComponentOpenSelect" << std::endl; - result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_open, uppCallComponentOpenProcInfo); - break; - - case kComponentCloseSelect: -// std::cerr << "kComponentCloseSelect" << std::endl; - result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_close, uppCallComponentCloseProcInfo); - // CallComponentFunctionWithStorageProcInfo - break; - - default: -// std::cerr << "Delegating selector: " << cp->what << " to component instance " << storage->delegate << std::endl; - result = DelegateComponentCall(cp, storage->delegate); - break; - } - - return result; -} - -static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self) -{ - ComponentResult result = noErr; - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - - storage = new VolumeCatcherStorage; - - storage->self = self; - storage->delegate = NULL; - - result = OpenAComponent(impl->mOriginalDefaultOutput, &(storage->delegate)); - - if(result != noErr) - { -// std::cerr << "OpenAComponent result = " << result << ", component ref = " << storage->delegate << std::endl; - - // If we failed to open the delagate component, our open is going to fail. Clean things up. - delete storage; - } - else - { - // Success -- set up this component's storage - SetComponentInstanceStorage(self, (Handle)storage); - - // add this instance to the global list - impl->mComponentInstances.push_back(storage); - - // and set up the initial volume - impl->setInstanceVolume(storage); - } - - return result; -} - -static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self) -{ - ComponentResult result = noErr; - - if(storage) - { - if(storage->delegate) - { - CloseComponent(storage->delegate); - storage->delegate = NULL; - } - - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - impl->mComponentInstances.remove(storage); - delete[] storage; - } - - return result; -} - -void VolumeCatcherImpl::setVolume(F32 volume) -{ - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - impl->mVolume = volume; - - // Iterate through all known instances, setting the volume on each. - for(std::list::iterator iter = mComponentInstances.begin(); iter != mComponentInstances.end(); ++iter) - { - impl->setInstanceVolume(*iter); - } -} - -void VolumeCatcherImpl::setPan(F32 pan) -{ - VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); - impl->mPan = pan; - - // TODO: implement this. - // This will probably require adding a "panner" audio unit to the chain somehow. - // There's also a "3d mixer" component that we might be able to use... -} - -void VolumeCatcherImpl::setInstanceVolume(VolumeCatcherStorage *instance) -{ -// std::cerr << "Setting volume on component instance: " << (instance->delegate) << " to " << mVolume << std::endl; - - OSStatus err = noErr; - - if(instance && instance->delegate) - { - err = AudioUnitSetParameter( - instance->delegate, - kHALOutputParam_Volume, - kAudioUnitScope_Global, - 0, - mVolume, - 0); - } - - if(err) - { -// std::cerr << " AudioUnitSetParameter returned " << err << std::endl; - } -} - -///////////////////////////////////////////////////// - -VolumeCatcher::VolumeCatcher() -{ - pimpl = VolumeCatcherImpl::getInstance(); -} - -VolumeCatcher::~VolumeCatcher() -{ - // Let the instance persist until exit. -} - -void VolumeCatcher::setVolume(F32 volume) -{ - pimpl->setVolume(volume); -} - -void VolumeCatcher::setPan(F32 pan) -{ - pimpl->setPan(pan); -} - -void VolumeCatcher::pump() -{ - // No periodic tasks are necessary for this implementation. -} - -#if LL_DARWIN -#pragma GCC diagnostic warning "-Wdeprecated-declarations" -#endif diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp deleted file mode 100755 index 3edeef51e3..0000000000 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ /dev/null @@ -1,1481 +0,0 @@ -/** - * @file media_plugin_webkit.cpp - * @brief Webkit plugin for LLMedia API plugin system - * - * @cond - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ -#include "llqtwebkit.h" -#include "linden_common.h" -#include "indra_constants.h" // for indra keyboard codes - -#include "lltimer.h" -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified -#if LL_LINUX -# define LL_QTWEBKIT_USES_PIXMAPS 0 -extern "C" { -# include -# include -} -#else -# define LL_QTWEBKIT_USES_PIXMAPS 0 -#endif // LL_LINUX - -# include "volume_catcher.h" - -#if LL_WINDOWS -# include -#else -# include -# include -#endif - -#if LL_WINDOWS - // *NOTE:Mani - This captures the module handle for the dll. This is used below - // to get the path to this dll for webkit initialization. - // I don't know how/if this can be done with apr... - namespace { HMODULE gModuleHandle;}; - BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) - { - gModuleHandle = (HMODULE) hinstDLL; - return TRUE; - } -#endif - -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginWebKit : - public MediaPluginBase, - public LLEmbeddedBrowserWindowObserver -{ -public: - MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginWebKit(); - - /*virtual*/ void receiveMessage(const char *message_string); - -private: - - std::string mProfileDir; - std::string mHostLanguage; - std::string mUserAgent; - bool mCookiesEnabled; - bool mJavascriptEnabled; - bool mPluginsEnabled; - bool mEnableMediaPluginDebugging; - - enum - { - INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet - INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet. - INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued - INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed - INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws - INIT_STATE_WAIT_COMPLETE, // Waiting for first real navigate complete event - INIT_STATE_RUNNING // All initialization gymnastics are complete. - }; - int mBrowserWindowId; - int mInitState; - std::string mInitialNavigateURL; - bool mNeedsUpdate; - - bool mCanCut; - bool mCanCopy; - bool mCanPaste; - int mLastMouseX; - int mLastMouseY; - bool mFirstFocus; - F32 mBackgroundR; - F32 mBackgroundG; - F32 mBackgroundB; - std::string mTarget; - LLTimer mElapsedTime; - - VolumeCatcher mVolumeCatcher; - - void postDebugMessage( const std::string& msg ) - { - if ( mEnableMediaPluginDebugging ) - { - std::stringstream str; - str << "@Media Msg> " << "[" << (double)mElapsedTime.getElapsedTimeF32() << "] -- " << msg; - - LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); - debug_message.setValue("message_text", str.str()); - debug_message.setValue("message_level", "info"); - sendMessage(debug_message); - } - } - - void setInitState(int state) - { -// std::cerr << "changing init state to " << state << std::endl; - mInitState = state; - } - - //////////////////////////////////////////////////////////////////////////////// - // - void update(int milliseconds) - { -#if LL_QTLINUX_DOESNT_HAVE_GLIB - // pump glib generously, as Linux browser plugins are on the - // glib main loop, even if the browser itself isn't - ugh - // This is NOT NEEDED if Qt itself was built with glib - // mainloop integration. - GMainContext *mainc = g_main_context_default(); - while(g_main_context_iteration(mainc, FALSE)); -#endif // LL_QTLINUX_DOESNT_HAVE_GLIB - - // pump qt - LLQtWebKit::getInstance()->pump( milliseconds ); - - mVolumeCatcher.pump(); - - checkEditState(); - - if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) - { - if(!mInitialNavigateURL.empty()) - { - // We already have the initial navigate URL -- kick off the navigate. - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL ); - mInitialNavigateURL.clear(); - } - } - - if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate ) - { - const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); - - unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ); - unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); -#if !LL_QTWEBKIT_USES_PIXMAPS - unsigned int buffer_size = rowspan * height; -#endif // !LL_QTWEBKIT_USES_PIXMAPS - -// std::cerr << "webkit plugin: updating" << std::endl; - - // TODO: should get rid of this memcpy if possible - if ( mPixels && browser_pixels ) - { -// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl; - -#if LL_QTWEBKIT_USES_PIXMAPS - // copy the pixel data upside-down because of the co-ord system - for (int y=0; y 0 && mHeight > 0 ) - { -// std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl; - setDirty( 0, 0, mWidth, mHeight ); - } - - mNeedsUpdate = false; - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - bool initBrowser() - { - // already initialized - if ( mInitState > INIT_STATE_UNINITIALIZED ) - return true; - - // set up directories - char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use - if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) - { - LL_WARNS() << "Couldn't get cwd - probably too long - failing to init." << LL_ENDL; - return false; - } - std::string application_dir = std::string( cwd ); - -#if LL_LINUX - // take care to initialize glib properly, because some - // versions of Qt don't, and we indirectly need it for (some - // versions of) Flash to not crash the browser. - if (!g_thread_supported ()) g_thread_init (NULL); - g_type_init(); -#endif - -#if LL_DARWIN - // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. - // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. - // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it - // which gets hit when the plugin is probed by webkit. - // Unsetting the environment variable here works around this issue. - unsetenv("USERBREAK"); -#endif - -#if LL_WINDOWS - //*NOTE:Mani - On windows, at least, the component path is the - // location of this dll's image file. - std::string component_dir; - char dll_path[_MAX_PATH]; - DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH); - while(len && dll_path[ len ] != ('\\') ) - { - len--; - } - if(len >= 0) - { - dll_path[len] = 0; - component_dir = dll_path; - } - else - { - // *NOTE:Mani - This case should be an rare exception. - // GetModuleFileNameA should always give you a full path, no? - component_dir = application_dir; - } -#else - std::string component_dir = application_dir; -#endif - - // debug spam sent to viewer and displayed in the log as usual - postDebugMessage( "Component dir set to: " + component_dir ); - - // window handle - needed on Windows and must be app window. -#if LL_WINDOWS - char window_title[ MAX_PATH ]; - GetConsoleTitleA( window_title, MAX_PATH ); - void* native_window_handle = (void*)FindWindowA( NULL, window_title ); -#else - void* native_window_handle = 0; -#endif - - // main browser initialization - bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle ); - if ( result ) - { - mInitState = INIT_STATE_INITIALIZED; - - // debug spam sent to viewer and displayed in the log as usual - postDebugMessage( "browser initialized okay" ); - - return true; - }; - - // debug spam sent to viewer and displayed in the log as usual - postDebugMessage( "browser nOT initialized." ); - - return false; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - bool initBrowserWindow() - { - // already initialized - if ( mInitState > INIT_STATE_INITIALIZED ) - return true; - - // not enough information to initialize the browser yet. - if ( mWidth < 0 || mHeight < 0 || mDepth < 0 || - mTextureWidth < 0 || mTextureHeight < 0 ) - { - return false; - }; - - // Set up host language before creating browser window - if(!mHostLanguage.empty()) - { - LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage); - postDebugMessage( "Setting language to " + mHostLanguage ); - } - - // turn on/off cookies based on what host app tells us - LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); - - // turn on/off plugins based on what host app tells us - LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); - - // turn on/off Javascript based on what host app tells us -#if LLQTWEBKIT_API_VERSION >= 11 - LLQtWebKit::getInstance()->enableJavaScript( mJavascriptEnabled ); -#else - LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); -#endif - - std::stringstream str; - str << "Cookies enabled = " << mCookiesEnabled << ", plugins enabled = " << mPluginsEnabled << ", Javascript enabled = " << mJavascriptEnabled; - postDebugMessage( str.str() ); - - // create single browser window - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight, mTarget); - - str.str(""); - str.clear(); - str << "Setting browser window size to " << mWidth << " x " << mHeight; - postDebugMessage( str.str() ); - - // tell LLQtWebKit about the size of the browser window - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); - - // observer events that LLQtWebKit emits - LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); - - // append details to agent string - LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); - postDebugMessage( "Updating user agent with " + mUserAgent ); - -#if !LL_QTWEBKIT_USES_PIXMAPS - // don't flip bitmap - LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); -#endif // !LL_QTWEBKIT_USES_PIXMAPS - - // set background color - // convert background color channels from [0.0, 1.0] to [0, 255]; - LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) ); - - // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. - setInitState(INIT_STATE_NAVIGATING); - - // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. - // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially - // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. - // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E" - // where RRGGBB is the background color in HTML style - std::stringstream url; - - url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#"; - // convert background color channels from [0.0, 1.0] to [0, 255]; - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f); - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f); - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); - url << "%22%3E%3C/body%3E%3C/html%3E"; - - //LL_DEBUGS() << "data url is: " << url.str() << LL_ENDL; - - // always display loading overlay now -#if LLQTWEBKIT_API_VERSION >= 16 - LLQtWebKit::getInstance()->enableLoadingOverlay(mBrowserWindowId, true); -#else - LL_WARNS() << "Ignoring enableLoadingOverlay() call (llqtwebkit version is too old)." << LL_ENDL; -#endif - str.clear(); - str << "Loading overlay enabled = " << mEnableMediaPluginDebugging << " for mBrowserWindowId = " << mBrowserWindowId; - postDebugMessage( str.str() ); - - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); -// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); - - return true; - } - - void setVolume(F32 vol); - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onCursorChanged(const EventType& event) - { - LLQtWebKit::ECursor llqt_cursor = (LLQtWebKit::ECursor)event.getIntValue(); - std::string name; - - switch(llqt_cursor) - { - case LLQtWebKit::C_ARROW: - name = "arrow"; - break; - case LLQtWebKit::C_IBEAM: - name = "ibeam"; - break; - case LLQtWebKit::C_SPLITV: - name = "splitv"; - break; - case LLQtWebKit::C_SPLITH: - name = "splith"; - break; - case LLQtWebKit::C_POINTINGHAND: - name = "hand"; - break; - - default: - LL_WARNS() << "Unknown cursor ID: " << (int)llqt_cursor << LL_ENDL; - break; - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed"); - message.setValue("name", name); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onPageChanged( const EventType& event ) - { - if(mInitState == INIT_STATE_WAIT_REDRAW) - { - setInitState(INIT_STATE_WAIT_COMPLETE); - } - - // flag that an update is required - mNeedsUpdate = true; - }; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateBegin(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - message.setValue("uri", event.getEventUri()); - message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); - message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); - sendMessage(message); - - // debug spam sent to viewer and displayed in the log as usual - postDebugMessage( "Navigate begin event at: " + event.getEventUri() ); - - setStatus(STATUS_LOADING); - } - - if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) - { - // Skip the WAIT_REDRAW state now -- with the right background color set, it should no longer be necessary. -// setInitState(INIT_STATE_WAIT_REDRAW); - setInitState(INIT_STATE_WAIT_COMPLETE); - } - - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateComplete(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - if(mInitState < INIT_STATE_RUNNING) - { - setInitState(INIT_STATE_RUNNING); - - // Clear the history, so the "back" button doesn't take you back to "about:blank". - LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); - } - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - message.setValue("uri", event.getEventUri()); - message.setValueS32("result_code", event.getIntValue()); - message.setValue("result_string", event.getStringValue()); - message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); - message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); - sendMessage(message); - - setStatus(STATUS_LOADED); - } - else if(mInitState == INIT_STATE_NAVIGATING) - { - setInitState(INIT_STATE_NAVIGATE_COMPLETE); - } - - // debug spam sent to viewer and displayed in the log as usual - postDebugMessage( "Navigate complete event at: " + event.getEventUri() ); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onUpdateProgress(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "progress"); - message.setValueS32("percent", event.getIntValue()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onStatusTextChange(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); - message.setValue("status", event.getStringValue()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onTitleChange(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", event.getStringValue()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onNavigateErrorPage(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_error_page"); - message.setValueS32("status_code", event.getIntValue()); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onLocationChange(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); - message.setValue("uri", event.getEventUri()); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onClickLinkHref(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); - message.setValue("uri", event.getEventUri()); - message.setValue("target", event.getStringValue()); - message.setValue("uuid", event.getStringValue2()); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onClickLinkNoFollow(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); - message.setValue("uri", event.getEventUri()); -#if LLQTWEBKIT_API_VERSION >= 7 - message.setValue("nav_type", event.getNavigationType()); -#else - message.setValue("nav_type", "clicked"); -#endif - sendMessage(message); - } - - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onCookieChanged(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookie_set"); - message.setValue("cookie", event.getStringValue()); - // These could be passed through as well, but aren't really needed. -// message.setValue("uri", event.getEventUri()); -// message.setValueBoolean("dead", (event.getIntValue() != 0)) - - // debug spam - postDebugMessage( "Sending cookie_set message from plugin: " + event.getStringValue() ); - - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onWindowCloseRequested(const EventType& event) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "close_request"); - message.setValue("uuid", event.getStringValue()); - sendMessage(message); - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onWindowGeometryChangeRequested(const EventType& event) - { - int x, y, width, height; - event.getRectValue(x, y, width, height); - - // This sometimes gets called with a zero-size request. Don't pass these along. - if(width > 0 && height > 0) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "geometry_change"); - message.setValue("uuid", event.getStringValue()); - message.setValueS32("x", x); - message.setValueS32("y", y); - message.setValueS32("width", width); - message.setValueS32("height", height); - sendMessage(message); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - std::string onRequestFilePicker( const EventType& eventIn ) - { - return blockingPickFile(); - } - - std::string mAuthUsername; - std::string mAuthPassword; - bool mAuthOK; - - //////////////////////////////////////////////////////////////////////////////// - // virtual - bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password) - { - mAuthOK = false; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); - message.setValue("url", in_url); - message.setValue("realm", in_realm); - message.setValueBoolean("blocking_request", true); - - // The "blocking_request" key in the message means this sendMessage call will block until a response is received. - sendMessage(message); - - if(mAuthOK) - { - out_username = mAuthUsername; - out_password = mAuthPassword; - } - - return mAuthOK; - } - - void authResponse(LLPluginMessage &message) - { - mAuthOK = message.getValueBoolean("ok"); - if(mAuthOK) - { - mAuthUsername = message.getValue("username"); - mAuthPassword = message.getValue("password"); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // virtual - void onLinkHovered(const EventType& event) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "link_hovered"); - message.setValue("link", event.getEventUri()); - message.setValue("title", event.getStringValue()); - message.setValue("text", event.getStringValue2()); - sendMessage(message); - } - } - - LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) - { - int result = 0; - - if(modifiers.find("shift") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_SHIFT; - - if(modifiers.find("alt") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_ALT; - - if(modifiers.find("control") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_CONTROL; - - if(modifiers.find("meta") != std::string::npos) - result |= LLQtWebKit::KM_MODIFIER_META; - - return (LLQtWebKit::EKeyboardModifier)result; - } - - //////////////////////////////////////////////////////////////////////////////// - // - void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers ) - { - native_scan_code = 0; - native_virtual_key = 0; - native_modifiers = 0; - - if( native_key_data.isMap() ) - { -#if LL_DARWIN - native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#elif LL_WINDOWS - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - // TODO: I don't think we need to do anything with native modifiers here -- please verify -#elif LL_LINUX - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#else - // Add other platforms here as needed -#endif - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) - { - // The incoming values for 'key' will be the ones from indra_constants.h - std::string utf8_text; - - if(key < KEY_SPECIAL) - { - // Low-ascii characters need to get passed through. - utf8_text = (char)key; - } - - // Any special-case handling we want to do for particular keys... - switch((KEY)key) - { - // ASCII codes for some standard keys - case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break; - case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break; - case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break; - case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break; - case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break; - - default: - break; - } - -// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl; - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); - - LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - - checkEditState(); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) - { - uint32_t key = LLQtWebKit::KEY_NONE; - -// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl; - - if(utf8str.size() == 1) - { - // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character. - // In this case, use it as the key value. - key = utf8str[0]; - } - - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); - - LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); - - checkEditState(); - }; - - void checkEditState(void) - { - bool can_cut = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT); - bool can_copy = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY); - bool can_paste = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE); - - if((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); - - if(can_cut != mCanCut) - { - mCanCut = can_cut; - message.setValueBoolean("cut", can_cut); - } - - if(can_copy != mCanCopy) - { - mCanCopy = can_copy; - message.setValueBoolean("copy", can_copy); - } - - if(can_paste != mCanPaste) - { - mCanPaste = can_paste; - message.setValueBoolean("paste", can_paste); - } - - sendMessage(message); - - } - } - - std::string mPickedFile; - - std::string blockingPickFile(void) - { - mPickedFile.clear(); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); - message.setValueBoolean("blocking_request", true); - - // The "blocking_request" key in the message means this sendMessage call will block until a response is received. - sendMessage(message); - - return mPickedFile; - } - - void onPickFileResponse(const std::string &file) - { - mPickedFile = file; - } - -}; - -MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : - MediaPluginBase(host_send_func, host_user_data) -{ -// std::cerr << "MediaPluginWebKit constructor" << std::endl; - - mBrowserWindowId = 0; - mInitState = INIT_STATE_UNINITIALIZED; - mNeedsUpdate = true; - mCanCut = false; - mCanCopy = false; - mCanPaste = false; - mLastMouseX = 0; - mLastMouseY = 0; - mFirstFocus = true; - mBackgroundR = 0.0f; - mBackgroundG = 0.0f; - mBackgroundB = 0.0f; - - mHostLanguage = "en"; // default to english - mJavascriptEnabled = true; // default to on - mPluginsEnabled = true; // default to on - mEnableMediaPluginDebugging = false; - mUserAgent = "LLPluginMedia Web Browser"; - - mElapsedTime.reset(); -} - -MediaPluginWebKit::~MediaPluginWebKit() -{ - // unhook observer - LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); - - // clean up - LLQtWebKit::getInstance()->reset(); - -// std::cerr << "MediaPluginWebKit destructor" << std::endl; -} - -void MediaPluginWebKit::receiveMessage(const char *message_string) -{ -// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "Webkit media plugin, Webkit version "; - plugin_version += LLQtWebKit::getInstance()->getVersion(); - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - F64 time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - // DTOR most likely won't be called but the recent change to the way this process - // is (not) killed means we see this message and can do what we need to here. - // Note: this cleanup is ultimately what writes cookies to the disk - LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); - LLQtWebKit::getInstance()->reset(); - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - -// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name -// << ", size: " << info.mSize -// << ", address: " << info.mAddress -// << std::endl; - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - -// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl; - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if(message_name == "set_volume") - { - F32 volume = (F32)message_in.getValueReal("volume"); - setVolume(volume); - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - mTarget = message_in.getValue("target"); - - // This is the media init message -- all necessary data for initialization should have been received. - if(initBrowser()) - { - - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGBA); - #if LL_QTWEBKIT_USES_PIXMAPS - message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck. - #else - message.setValueU32("format", GL_RGBA); - #endif // LL_QTWEBKIT_USES_PIXMAPS - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); - } - else - { - // if initialization failed, we're done. - mDeleteMe = true; - } - - } - else if(message_name == "set_user_data_path") - { - std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter - mProfileDir = user_data_path + "browser_profile"; - - // FIXME: Should we do anything with this if it comes in after the browser has been initialized? - } - else if(message_name == "set_language_code") - { - mHostLanguage = message_in.getValue("language"); - - // FIXME: Should we do anything with this if it comes in after the browser has been initialized? - } - else if(message_name == "plugins_enabled") - { - mPluginsEnabled = message_in.getValueBoolean("enable"); - } - else if(message_name == "javascript_enabled") - { - mJavascriptEnabled = message_in.getValueBoolean("enable"); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - mBackgroundR = (F32)message_in.getValueReal("background_r"); - mBackgroundG = (F32)message_in.getValueReal("background_g"); - mBackgroundB = (F32)message_in.getValueReal("background_b"); -// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - mPixels = (unsigned char*)iter->second.mAddress; - mWidth = width; - mHeight = height; - - if(initBrowserWindow()) - { - - // size changed so tell the browser - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); - - // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight - // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl; - - S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId); - - // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response. - if(real_width <= texture_width) - { - texture_width = real_width; - } - else - { - // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. - // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl; - mDeleteMe = true; - return; - } - } - else - { - // Setting up the browser window failed. This is a fatal error. - mDeleteMe = true; - } - - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - - }; - }; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - } - else if(message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - -// std::cout << "loading URI: " << uri << std::endl; - - if(!uri.empty()) - { - if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) - { - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri ); - } - else - { - mInitialNavigateURL = uri; - } - } - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - S32 button = message_in.getValueS32("button"); - mLastMouseX = message_in.getValueS32("x"); - mLastMouseY = message_in.getValueS32("y"); - std::string modifiers = message_in.getValue("modifiers"); - - // Treat unknown mouse events as mouse-moves. - LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE; - if(event == "down") - { - mouse_event = LLQtWebKit::ME_MOUSE_DOWN; - } - else if(event == "up") - { - mouse_event = LLQtWebKit::ME_MOUSE_UP; - } - else if(event == "double_click") - { - mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK; - } - - LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers)); - checkEditState(); - } - else if(message_name == "scroll_event") - { - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - std::string modifiers = message_in.getValue("modifiers"); - - // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit. - // Qt expects 1 detent to be 120 units. - // It also seems that our y scroll direction is inverted vs. what Qt expects. - - x *= 120; - y *= -120; - - LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers)); - } - else if(message_name == "key_event") - { - std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - // Treat unknown events as key-up for safety. - LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP; - if(event == "down") - { - key_event = LLQtWebKit::KE_KEY_DOWN; - } - else if(event == "repeat") - { - key_event = LLQtWebKit::KE_KEY_REPEAT; - } - - keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); - } - else if(message_name == "text_event") - { - std::string text = message_in.getValue("text"); - std::string modifiers = message_in.getValue("modifiers"); - LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - unicodeInput(text, decodeModifiers(modifiers), native_key_data); - } - if(message_name == "edit_cut") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT ); - checkEditState(); - } - if(message_name == "edit_copy") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY ); - checkEditState(); - } - if(message_name == "edit_paste") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE ); - checkEditState(); - } - if(message_name == "pick_file_response") - { - onPickFileResponse(message_in.getValue("file")); - } - if(message_name == "auth_response") - { - authResponse(message_in); - } - else - if(message_name == "enable_media_plugin_debugging") - { - mEnableMediaPluginDebugging = message_in.getValueBoolean( "enable" ); - } - else - if(message_name == "js_enable_object") - { -#if LLQTWEBKIT_API_VERSION >= 9 - bool enable = message_in.getValueBoolean( "enable" ); - LLQtWebKit::getInstance()->setSLObjectEnabled( enable ); -#endif - } - else - if(message_name == "js_agent_location") - { -#if LLQTWEBKIT_API_VERSION >= 9 - F32 x = (F32)message_in.getValueReal("x"); - F32 y = (F32)message_in.getValueReal("y"); - F32 z = (F32)message_in.getValueReal("z"); - LLQtWebKit::getInstance()->setAgentLocation( x, y, z ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_global_location") - { -#if LLQTWEBKIT_API_VERSION >= 9 - F32 x = (F32)message_in.getValueReal("x"); - F32 y = (F32)message_in.getValueReal("y"); - F32 z = (F32)message_in.getValueReal("z"); - LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_orientation") - { -#if LLQTWEBKIT_API_VERSION >= 9 - F32 angle = (F32)message_in.getValueReal("angle"); - LLQtWebKit::getInstance()->setAgentOrientation( angle ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_region") - { -#if LLQTWEBKIT_API_VERSION >= 9 - const std::string& region = message_in.getValue("region"); - LLQtWebKit::getInstance()->setAgentRegion( region ); - LLQtWebKit::getInstance()->emitLocation(); -#endif - } - else - if(message_name == "js_agent_maturity") - { -#if LLQTWEBKIT_API_VERSION >= 9 - const std::string& maturity = message_in.getValue("maturity"); - LLQtWebKit::getInstance()->setAgentMaturity( maturity ); - LLQtWebKit::getInstance()->emitMaturity(); -#endif - } - else - if(message_name == "js_agent_language") - { -#if LLQTWEBKIT_API_VERSION >= 9 - const std::string& language = message_in.getValue("language"); - LLQtWebKit::getInstance()->setAgentLanguage( language ); - LLQtWebKit::getInstance()->emitLanguage(); -#endif - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) - { - if(message_name == "focus") - { - bool val = message_in.getValueBoolean("focused"); - LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val ); - - if(mFirstFocus && val) - { - // On the first focus, post a tab key event. This fixes a problem with initial focus. - std::string empty; - keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty)); - keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty)); - mFirstFocus = false; - } - } - else if(message_name == "set_page_zoom_factor") - { -#if LLQTWEBKIT_API_VERSION >= 15 - F32 factor = (F32)message_in.getValueReal("factor"); - LLQtWebKit::getInstance()->setPageZoomFactor(factor); -#else - LL_WARNS() << "Ignoring setPageZoomFactor message (llqtwebkit version is too old)." << LL_ENDL; -#endif - } - else if(message_name == "clear_cache") - { - LLQtWebKit::getInstance()->clearCache(); - } - else if(message_name == "clear_cookies") - { - LLQtWebKit::getInstance()->clearAllCookies(); - } - else if(message_name == "enable_cookies") - { - mCookiesEnabled = message_in.getValueBoolean("enable"); - LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); - } - else if(message_name == "enable_plugins") - { - mPluginsEnabled = message_in.getValueBoolean("enable"); - LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); - } - else if(message_name == "enable_javascript") - { - mJavascriptEnabled = message_in.getValueBoolean("enable"); - //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); - } - else if(message_name == "set_cookies") - { - LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies")); - - // debug spam - postDebugMessage( "Plugin setting cookie: " + message_in.getValue("cookies") ); - } - else if(message_name == "proxy_setup") - { - bool val = message_in.getValueBoolean("enable"); - std::string host = message_in.getValue("host"); - int port = message_in.getValueS32("port"); - LLQtWebKit::getInstance()->enableProxy( val, host, port ); - } - else if(message_name == "browse_stop") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP ); - } - else if(message_name == "browse_reload") - { - // foo = message_in.getValueBoolean("ignore_cache"); - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD ); - } - else if(message_name == "browse_forward") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD ); - } - else if(message_name == "browse_back") - { - LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK ); - } - else if(message_name == "set_status_redirect") - { - int code = message_in.getValueS32("code"); - std::string url = message_in.getValue("url"); - if ( 404 == code ) // browser lib only supports 404 right now - { -#if LLQTWEBKIT_API_VERSION < 8 - LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url ); -#endif - }; - } - else if(message_name == "set_user_agent") - { - mUserAgent = message_in.getValue("user_agent"); - LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); - } - else if(message_name == "show_web_inspector") - { -#if LLQTWEBKIT_API_VERSION >= 10 - bool val = message_in.getValueBoolean("show"); - LLQtWebKit::getInstance()->showWebInspector( val ); -#else - LL_WARNS() << "Ignoring showWebInspector message (llqtwebkit version is too old)." << LL_ENDL; -#endif - } - else if(message_name == "ignore_ssl_cert_errors") - { -#if LLQTWEBKIT_API_VERSION >= 3 - LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( message_in.getValueBoolean("ignore") ); -#else - LL_WARNS() << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << LL_ENDL; -#endif - } - else if(message_name == "add_certificate_file_path") - { -#if LLQTWEBKIT_API_VERSION >= 6 - LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") ); -#else - LL_WARNS() << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << LL_ENDL; -#endif - } - else if(message_name == "init_history") - { - // Initialize browser history - LLSD history = message_in.getValueLLSD("history"); - // First, clear the URL history - LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); - // Then, add the history items in order - LLSD::array_iterator iter_history = history.beginArray(); - LLSD::array_iterator end_history = history.endArray(); - for(; iter_history != end_history; ++iter_history) - { - std::string url = (*iter_history).asString(); - if(! url.empty()) { - LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url); - } - } - } - else if(message_name == "proxy_window_opened") - { - std::string target = message_in.getValue("target"); - std::string uuid = message_in.getValue("uuid"); - LLQtWebKit::getInstance()->proxyWindowOpened(mBrowserWindowId, target, uuid); - } - else if(message_name == "proxy_window_closed") - { - std::string uuid = message_in.getValue("uuid"); - LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl; - }; - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } -} - -void MediaPluginWebKit::setVolume(F32 volume) -{ - mVolumeCatcher.setVolume(volume); -} - -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data); - *plugin_send_func = MediaPluginWebKit::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; -} - - diff --git a/indra/media_plugins/webkit/volume_catcher.h b/indra/media_plugins/webkit/volume_catcher.h deleted file mode 100755 index 337f2913d3..0000000000 --- a/indra/media_plugins/webkit/volume_catcher.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file volume_catcher.h - * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process. - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#ifndef VOLUME_CATCHER_H -#define VOLUME_CATCHER_H - -#include "linden_common.h" - -class VolumeCatcherImpl; - -class VolumeCatcher -{ - public: - VolumeCatcher(); - ~VolumeCatcher(); - - void setVolume(F32 volume); // 0.0 - 1.0 - - // Set the left-right pan of audio sources - // where -1.0 = left, 0 = center, and 1.0 = right - void setPan(F32 pan); - - void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume - - private: - VolumeCatcherImpl *pimpl; -}; - -#endif // VOLUME_CATCHER_H diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp deleted file mode 100755 index 0cfb810906..0000000000 --- a/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @file windows_volume_catcher.cpp - * @brief A Windows implementation of volume level control of all audio channels opened by a process. - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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; - * version 2.1 of the License only. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "volume_catcher.h" -#include -#include "llsingleton.h" -class VolumeCatcherImpl : public LLSingleton -{ -friend LLSingleton; -public: - - void setVolume(F32 volume); - void setPan(F32 pan); - -private: - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - VolumeCatcherImpl(); - ~VolumeCatcherImpl(); - - typedef void (WINAPI *set_volume_func_t)(F32); - typedef void (WINAPI *set_mute_func_t)(bool); - - set_volume_func_t mSetVolumeFunc; - set_mute_func_t mSetMuteFunc; - - // tests if running on Vista, 7, 8 + once in CTOR - bool isWindowsVistaOrHigher(); - - F32 mVolume; - F32 mPan; - bool mSystemIsVistaOrHigher; -}; - -bool VolumeCatcherImpl::isWindowsVistaOrHigher() -{ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - return osvi.dwMajorVersion >= 6; -} - -VolumeCatcherImpl::VolumeCatcherImpl() -: mVolume(1.0f), // default volume is max - mPan(0.f) // default pan is centered -{ - mSystemIsVistaOrHigher = isWindowsVistaOrHigher(); - - if ( ! mSystemIsVistaOrHigher ) - { - HMODULE handle = ::LoadLibrary(L"winmm.dll"); - if(handle) - { - mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); - mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); - } - } -} - -VolumeCatcherImpl::~VolumeCatcherImpl() -{ -} - -void VolumeCatcherImpl::setVolume(F32 volume) -{ - mVolume = volume; - - if ( mSystemIsVistaOrHigher ) - { - // set both left/right to same volume - // TODO: use pan value to set independently - DWORD left_channel = (DWORD)(mVolume * 65535.0f); - DWORD right_channel = (DWORD)(mVolume * 65535.0f); - DWORD hw_volume = left_channel << 16 | right_channel; - ::waveOutSetVolume(NULL, hw_volume); - } - else - { - if (mSetMuteFunc) - { - mSetMuteFunc(volume == 0.f); - } - if (mSetVolumeFunc) - { - mSetVolumeFunc(mVolume); - } - } -} - -void VolumeCatcherImpl::setPan(F32 pan) -{ // remember pan for calculating individual channel levels later - mPan = pan; -} - -///////////////////////////////////////////////////// - -VolumeCatcher::VolumeCatcher() -{ - pimpl = VolumeCatcherImpl::getInstance(); -} - -VolumeCatcher::~VolumeCatcher() -{ - // Let the instance persist until exit. -} - -void VolumeCatcher::setVolume(F32 volume) -{ - pimpl->setVolume(volume); -} - -void VolumeCatcher::setPan(F32 pan) -{ - pimpl->setPan(pan); -} - -void VolumeCatcher::pump() -{ - // No periodic tasks are necessary for this implementation. -} - - diff --git a/indra/media_plugins/winmmshim/CMakeLists.txt b/indra/media_plugins/winmmshim/CMakeLists.txt index bf74f81809..6890589892 100755 --- a/indra/media_plugins/winmmshim/CMakeLists.txt +++ b/indra/media_plugins/winmmshim/CMakeLists.txt @@ -22,9 +22,6 @@ set(winmm_shim_HEADER_FILES list(APPEND winmm_shim_SOURCE_FILES ${winmm_shim_HEADER_FILES}) -set_source_files_properties(${media_plugin_webkit_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - add_library(winmm_shim SHARED ${winmm_shim_SOURCE_FILES} -- cgit v1.2.3 From ebcee8d7e7cb6ead01e1061fd1cf1720ee7e1a45 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 6 Oct 2015 15:24:57 -0700 Subject: MAINT-5703 fix - add observer to media plugin so MEDIA_LOCATION_CHANGED events get propagated throughout system --- indra/media_plugins/cef/media_plugin_cef.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 9b87eca726..5b9ff6cac8 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -390,6 +390,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnTitleChangeCallback(boost::bind(&MediaPluginCEF::onTitleChangeCallback, this, _1)); mLLCEFLib->setOnLoadStartCallback(boost::bind(&MediaPluginCEF::onLoadStartCallback, this)); mLLCEFLib->setOnLoadEndCallback(boost::bind(&MediaPluginCEF::onLoadEndCallback, this, _1)); + mLLCEFLib->setOnAddressChangeCallback(boost::bind(&MediaPluginCEF::onAddressChangeCallback, this, _1)); mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1, _2)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); mLLCEFLib->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2)); -- cgit v1.2.3 From 295d392b1c1ed6182eb2dce528fd396eab2ed2b2 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 9 Oct 2015 10:09:18 -0700 Subject: MAINT-5715, MAINT-5717, MAINT-5718: Replace the the volume catcher that was removed with the QT viewer. Addresses panning and fading issues, teleport and viewer mute controls. --- indra/media_plugins/cef/CMakeLists.txt | 34 ++- indra/media_plugins/cef/mac_volume_catcher.cpp | 275 +++++++++++++++++++++ indra/media_plugins/cef/media_plugin_cef.cpp | 20 +- indra/media_plugins/cef/volume_catcher.h | 54 ++++ indra/media_plugins/cef/windows_volume_catcher.cpp | 147 +++++++++++ 5 files changed, 525 insertions(+), 5 deletions(-) create mode 100644 indra/media_plugins/cef/mac_volume_catcher.cpp create mode 100644 indra/media_plugins/cef/volume_catcher.h create mode 100644 indra/media_plugins/cef/windows_volume_catcher.cpp (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index 7465fe727a..9bd6dbc5e9 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -45,23 +45,49 @@ set(media_plugin_cef_SOURCE_FILES media_plugin_cef.cpp ) +set(media_plugin_webkit_HEADER_FILES + volume_catcher.h + ) + +# Select which VolumeCatcher implementation to use +if (LINUX) + message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n" + " Please create a volume_catcher implementation for this platform.") + +elseif (DARWIN) + list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher.cpp) + find_library(CORESERVICES_LIBRARY CoreServices) + find_library(AUDIOUNIT_LIBRARY AudioUnit) + list(APPEND media_plugin_cef_SOURCE_FILES + ${CORESERVICES_LIBRARY} # for Component Manager calls + ${AUDIOUNIT_LIBRARY} # for AudioUnit calls + ) +elseif (WINDOWS) + list(APPEND media_plugin_cef_SOURCE_FILES windows_volume_catcher.cpp) +endif (LINUX) + +set_source_files_properties(${media_plugin_webkit_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND media_plugin_cef_SOURCE_FILES ${media_plugin_cef_HEADER_FILES}) + add_library(media_plugin_cef SHARED ${media_plugin_cef_SOURCE_FILES} ) -target_link_libraries(media_plugin_cef +add_dependencies(media_plugin_cef ${LLPLUGIN_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES} ${LLCOMMON_LIBRARIES} - ${CEF_PLUGIN_LIBRARIES} - ${PLUGIN_API_WINDOWS_LIBRARIES} ) -add_dependencies(media_plugin_cef +target_link_libraries(media_plugin_cef ${LLPLUGIN_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES} ${LLCOMMON_LIBRARIES} + ${CEF_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} ) if (WINDOWS) diff --git a/indra/media_plugins/cef/mac_volume_catcher.cpp b/indra/media_plugins/cef/mac_volume_catcher.cpp new file mode 100644 index 0000000000..73e5bf3da3 --- /dev/null +++ b/indra/media_plugins/cef/mac_volume_catcher.cpp @@ -0,0 +1,275 @@ +/** + * @file mac_volume_catcher.cpp + * @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * 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; + * version 2.1 of the License only. + * + * 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 + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +/************************************************************************************************************** + This code works by using CaptureComponent to capture the "Default Output" audio component + (kAudioUnitType_Output/kAudioUnitSubType_DefaultOutput) and delegating all calls to the original component. + It does this just to keep track of all instances of the default output component, so that it can set the + kHALOutputParam_Volume parameter on all of them to adjust the output volume. +**************************************************************************************************************/ + +#include "volume_catcher.h" + +#include +#include +#include + +#if LL_DARWIN +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +struct VolumeCatcherStorage; + +class VolumeCatcherImpl +{ +public: + + void setVolume(F32 volume); + void setPan(F32 pan); + + void setInstanceVolume(VolumeCatcherStorage *instance); + + std::list mComponentInstances; + Component mOriginalDefaultOutput; + Component mVolumeAdjuster; + + static VolumeCatcherImpl *getInstance(); +private: + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + VolumeCatcherImpl(); + static VolumeCatcherImpl *sInstance; + + // The singlar instance of this class is expected to last until the process exits. + // To ensure this, we declare the destructor here but never define it, so any code which attempts to destroy the instance will not link. + ~VolumeCatcherImpl(); + + F32 mVolume; + F32 mPan; +}; + +VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL;; + +struct VolumeCatcherStorage +{ + ComponentInstance self; + ComponentInstance delegate; +}; + +static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage); +static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self); +static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self); + +VolumeCatcherImpl *VolumeCatcherImpl::getInstance() +{ + if(!sInstance) + { + sInstance = new VolumeCatcherImpl; + } + + return sInstance; +} + +VolumeCatcherImpl::VolumeCatcherImpl() +{ + mVolume = 1.0; // default to full volume + mPan = 0.0; // and center pan + + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + // Find the original default output component + mOriginalDefaultOutput = FindNextComponent(NULL, &desc); + + // Register our own output component with the same parameters + mVolumeAdjuster = RegisterComponent(&desc, NewComponentRoutineUPP(volume_catcher_component_entry), 0, NULL, NULL, NULL); + + // Capture the original component, so we always get found instead. + CaptureComponent(mOriginalDefaultOutput, mVolumeAdjuster); + +} + +static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage) +{ + ComponentResult result = badComponentSelector; + VolumeCatcherStorage *storage = (VolumeCatcherStorage*)componentStorage; + + switch(cp->what) + { + case kComponentOpenSelect: +// std::cerr << "kComponentOpenSelect" << std::endl; + result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_open, uppCallComponentOpenProcInfo); + break; + + case kComponentCloseSelect: +// std::cerr << "kComponentCloseSelect" << std::endl; + result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_close, uppCallComponentCloseProcInfo); + // CallComponentFunctionWithStorageProcInfo + break; + + default: +// std::cerr << "Delegating selector: " << cp->what << " to component instance " << storage->delegate << std::endl; + result = DelegateComponentCall(cp, storage->delegate); + break; + } + + return result; +} + +static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self) +{ + ComponentResult result = noErr; + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + + storage = new VolumeCatcherStorage; + + storage->self = self; + storage->delegate = NULL; + + result = OpenAComponent(impl->mOriginalDefaultOutput, &(storage->delegate)); + + if(result != noErr) + { +// std::cerr << "OpenAComponent result = " << result << ", component ref = " << storage->delegate << std::endl; + + // If we failed to open the delagate component, our open is going to fail. Clean things up. + delete storage; + } + else + { + // Success -- set up this component's storage + SetComponentInstanceStorage(self, (Handle)storage); + + // add this instance to the global list + impl->mComponentInstances.push_back(storage); + + // and set up the initial volume + impl->setInstanceVolume(storage); + } + + return result; +} + +static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self) +{ + ComponentResult result = noErr; + + if(storage) + { + if(storage->delegate) + { + CloseComponent(storage->delegate); + storage->delegate = NULL; + } + + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mComponentInstances.remove(storage); + delete[] storage; + } + + return result; +} + +void VolumeCatcherImpl::setVolume(F32 volume) +{ + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mVolume = volume; + + // Iterate through all known instances, setting the volume on each. + for(std::list::iterator iter = mComponentInstances.begin(); iter != mComponentInstances.end(); ++iter) + { + impl->setInstanceVolume(*iter); + } +} + +void VolumeCatcherImpl::setPan(F32 pan) +{ + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mPan = pan; + + // TODO: implement this. + // This will probably require adding a "panner" audio unit to the chain somehow. + // There's also a "3d mixer" component that we might be able to use... +} + +void VolumeCatcherImpl::setInstanceVolume(VolumeCatcherStorage *instance) +{ +// std::cerr << "Setting volume on component instance: " << (instance->delegate) << " to " << mVolume << std::endl; + + OSStatus err = noErr; + + if(instance && instance->delegate) + { + err = AudioUnitSetParameter( + instance->delegate, + kHALOutputParam_Volume, + kAudioUnitScope_Global, + 0, + mVolume, + 0); + } + + if(err) + { +// std::cerr << " AudioUnitSetParameter returned " << err << std::endl; + } +} + +///////////////////////////////////////////////////// + +VolumeCatcher::VolumeCatcher() +{ + pimpl = VolumeCatcherImpl::getInstance(); +} + +VolumeCatcher::~VolumeCatcher() +{ + // Let the instance persist until exit. +} + +void VolumeCatcher::setVolume(F32 volume) +{ + pimpl->setVolume(volume); +} + +void VolumeCatcher::setPan(F32 pan) +{ + pimpl->setPan(pan); +} + +void VolumeCatcher::pump() +{ + // No periodic tasks are necessary for this implementation. +} + +#if LL_DARWIN +#pragma GCC diagnostic warning "-Wdeprecated-declarations" +#endif diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 5b9ff6cac8..3f3d9dc657 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -39,6 +39,7 @@ #include "boost/function.hpp" #include "boost/bind.hpp" #include "llCEFLib.h" +#include "volume_catcher.h" //////////////////////////////////////////////////////////////////////////////// // @@ -76,6 +77,7 @@ private: void unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data); void checkEditState(); + void setVolume(F32 vol); bool mEnableMediaPluginDebugging; std::string mHostLanguage; @@ -92,6 +94,8 @@ private: std::string mCachePath; std::string mCookiePath; LLCEFLib* mLLCEFLib; + + VolumeCatcher mVolumeCatcher; }; //////////////////////////////////////////////////////////////////////////////// @@ -332,6 +336,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mLLCEFLib->update(); + mVolumeCatcher.pump(); // this seems bad but unless the state changes (it won't until we figure out // how to get CEF to tell us if copy/cut/paste is available) then this function // will return immediately @@ -630,7 +635,15 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mJavascriptEnabled = message_in.getValueBoolean("enable"); } } - else + else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if (message_name == "set_volume") + { + F32 volume = (F32)message_in.getValueReal("volume"); + setVolume(volume); + } + } + else { //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; }; @@ -763,6 +776,11 @@ void MediaPluginCEF::checkEditState() } } +void MediaPluginCEF::setVolume(F32 vol) +{ + mVolumeCatcher.setVolume(vol); +} + //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginCEF::init() diff --git a/indra/media_plugins/cef/volume_catcher.h b/indra/media_plugins/cef/volume_catcher.h new file mode 100644 index 0000000000..337f2913d3 --- /dev/null +++ b/indra/media_plugins/cef/volume_catcher.h @@ -0,0 +1,54 @@ +/** + * @file volume_catcher.h + * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * 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; + * version 2.1 of the License only. + * + * 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 + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#ifndef VOLUME_CATCHER_H +#define VOLUME_CATCHER_H + +#include "linden_common.h" + +class VolumeCatcherImpl; + +class VolumeCatcher +{ + public: + VolumeCatcher(); + ~VolumeCatcher(); + + void setVolume(F32 volume); // 0.0 - 1.0 + + // Set the left-right pan of audio sources + // where -1.0 = left, 0 = center, and 1.0 = right + void setPan(F32 pan); + + void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume + + private: + VolumeCatcherImpl *pimpl; +}; + +#endif // VOLUME_CATCHER_H diff --git a/indra/media_plugins/cef/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp new file mode 100644 index 0000000000..0cfb810906 --- /dev/null +++ b/indra/media_plugins/cef/windows_volume_catcher.cpp @@ -0,0 +1,147 @@ +/** + * @file windows_volume_catcher.cpp + * @brief A Windows implementation of volume level control of all audio channels opened by a process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * 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; + * version 2.1 of the License only. + * + * 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 + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#include "volume_catcher.h" +#include +#include "llsingleton.h" +class VolumeCatcherImpl : public LLSingleton +{ +friend LLSingleton; +public: + + void setVolume(F32 volume); + void setPan(F32 pan); + +private: + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + VolumeCatcherImpl(); + ~VolumeCatcherImpl(); + + typedef void (WINAPI *set_volume_func_t)(F32); + typedef void (WINAPI *set_mute_func_t)(bool); + + set_volume_func_t mSetVolumeFunc; + set_mute_func_t mSetMuteFunc; + + // tests if running on Vista, 7, 8 + once in CTOR + bool isWindowsVistaOrHigher(); + + F32 mVolume; + F32 mPan; + bool mSystemIsVistaOrHigher; +}; + +bool VolumeCatcherImpl::isWindowsVistaOrHigher() +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + return osvi.dwMajorVersion >= 6; +} + +VolumeCatcherImpl::VolumeCatcherImpl() +: mVolume(1.0f), // default volume is max + mPan(0.f) // default pan is centered +{ + mSystemIsVistaOrHigher = isWindowsVistaOrHigher(); + + if ( ! mSystemIsVistaOrHigher ) + { + HMODULE handle = ::LoadLibrary(L"winmm.dll"); + if(handle) + { + mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); + mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + } + } +} + +VolumeCatcherImpl::~VolumeCatcherImpl() +{ +} + +void VolumeCatcherImpl::setVolume(F32 volume) +{ + mVolume = volume; + + if ( mSystemIsVistaOrHigher ) + { + // set both left/right to same volume + // TODO: use pan value to set independently + DWORD left_channel = (DWORD)(mVolume * 65535.0f); + DWORD right_channel = (DWORD)(mVolume * 65535.0f); + DWORD hw_volume = left_channel << 16 | right_channel; + ::waveOutSetVolume(NULL, hw_volume); + } + else + { + if (mSetMuteFunc) + { + mSetMuteFunc(volume == 0.f); + } + if (mSetVolumeFunc) + { + mSetVolumeFunc(mVolume); + } + } +} + +void VolumeCatcherImpl::setPan(F32 pan) +{ // remember pan for calculating individual channel levels later + mPan = pan; +} + +///////////////////////////////////////////////////// + +VolumeCatcher::VolumeCatcher() +{ + pimpl = VolumeCatcherImpl::getInstance(); +} + +VolumeCatcher::~VolumeCatcher() +{ + // Let the instance persist until exit. +} + +void VolumeCatcher::setVolume(F32 volume) +{ + pimpl->setVolume(volume); +} + +void VolumeCatcher::setPan(F32 pan) +{ + pimpl->setPan(pan); +} + +void VolumeCatcher::pump() +{ + // No periodic tasks are necessary for this implementation. +} + + -- cgit v1.2.3 From 506e7271a7b69cc08a9096a6642a0b3f1b0ce04a Mon Sep 17 00:00:00 2001 From: rider Date: Fri, 9 Oct 2015 11:51:10 -0700 Subject: CMake fixes for mac build. --- indra/media_plugins/cef/CMakeLists.txt | 22 +++++++++++++--------- indra/media_plugins/cef/mac_volume_catcher.cpp | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index 9bd6dbc5e9..16015be672 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -45,20 +45,28 @@ set(media_plugin_cef_SOURCE_FILES media_plugin_cef.cpp ) -set(media_plugin_webkit_HEADER_FILES +set(media_plugin_cef_HEADER_FILES volume_catcher.h ) +set (media_plugin_cef_LINK_LIBRARIES + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${CEF_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES}) + + # Select which VolumeCatcher implementation to use if (LINUX) - message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n" + message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n" " Please create a volume_catcher implementation for this platform.") elseif (DARWIN) list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher.cpp) find_library(CORESERVICES_LIBRARY CoreServices) find_library(AUDIOUNIT_LIBRARY AudioUnit) - list(APPEND media_plugin_cef_SOURCE_FILES + list(APPEND media_plugin_cef_LINK_LIBRARIES ${CORESERVICES_LIBRARY} # for Component Manager calls ${AUDIOUNIT_LIBRARY} # for AudioUnit calls ) @@ -66,7 +74,7 @@ elseif (WINDOWS) list(APPEND media_plugin_cef_SOURCE_FILES windows_volume_catcher.cpp) endif (LINUX) -set_source_files_properties(${media_plugin_webkit_HEADER_FILES} +set_source_files_properties(${media_plugin_cef_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) list(APPEND media_plugin_cef_SOURCE_FILES ${media_plugin_cef_HEADER_FILES}) @@ -83,11 +91,7 @@ add_dependencies(media_plugin_cef ) target_link_libraries(media_plugin_cef - ${LLPLUGIN_LIBRARIES} - ${MEDIA_PLUGIN_BASE_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ${CEF_PLUGIN_LIBRARIES} - ${PLUGIN_API_WINDOWS_LIBRARIES} + ${media_plugin_cef_LINK_LIBRARIES} ) if (WINDOWS) diff --git a/indra/media_plugins/cef/mac_volume_catcher.cpp b/indra/media_plugins/cef/mac_volume_catcher.cpp index 73e5bf3da3..dddb9c2077 100644 --- a/indra/media_plugins/cef/mac_volume_catcher.cpp +++ b/indra/media_plugins/cef/mac_volume_catcher.cpp @@ -6,7 +6,7 @@ * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * 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; -- cgit v1.2.3 From 2a899b49dd5d0a4ff4b4ab2e36bda48ff1473f0a Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 19 Oct 2015 18:43:48 -0700 Subject: MAINT-5711 FIX profiles and marketplace are asking for a login each session --- indra/media_plugins/cef/media_plugin_cef.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 3f3d9dc657..7f538e16d8 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -479,6 +479,15 @@ void MediaPluginCEF::receiveMessage(const char* message_string) std::string uri = message_in.getValue("uri"); mLLCEFLib->navigate(uri); } + else if (message_name == "set_cookie") + { + std::string uri = message_in.getValue("uri"); + std::string name = message_in.getValue("name"); + std::string value = message_in.getValue("value"); + std::string domain = message_in.getValue("domain"); + std::string path = message_in.getValue("path"); + mLLCEFLib->setCookie(uri, name, value, domain, path); + } else if (message_name == "mouse_event") { std::string event = message_in.getValue("event"); -- cgit v1.2.3 From 8c74ed2a58f5443b931374489b04ba80fb11a590 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 21 Oct 2015 09:05:19 -0700 Subject: Fix windows line endings --- indra/media_plugins/cef/media_plugin_cef.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 7f538e16d8..5b08807619 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -479,14 +479,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) std::string uri = message_in.getValue("uri"); mLLCEFLib->navigate(uri); } - else if (message_name == "set_cookie") - { - std::string uri = message_in.getValue("uri"); - std::string name = message_in.getValue("name"); - std::string value = message_in.getValue("value"); - std::string domain = message_in.getValue("domain"); - std::string path = message_in.getValue("path"); - mLLCEFLib->setCookie(uri, name, value, domain, path); + else if (message_name == "set_cookie") + { + std::string uri = message_in.getValue("uri"); + std::string name = message_in.getValue("name"); + std::string value = message_in.getValue("value"); + std::string domain = message_in.getValue("domain"); + std::string path = message_in.getValue("path"); + mLLCEFLib->setCookie(uri, name, value, domain, path); } else if (message_name == "mouse_event") { @@ -814,4 +814,3 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, return 0; } - -- cgit v1.2.3 From 16cd296e30e95fbacefff4e291fbdd6fbf0c2c43 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 22 Oct 2015 13:24:43 -0700 Subject: MAINT-5775 FIX Split out cookies and cache directories into separate folders and move cache to same place as viewer cache --- indra/media_plugins/cef/media_plugin_cef.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 5b08807619..bb2270181e 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -432,9 +432,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "set_user_data_path") { - std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter - mCachePath = user_data_path + "cef_cache"; - mCookiePath = user_data_path + "cef_cookies"; + std::string user_data_path_cache = message_in.getValue("cache_path"); + std::string user_data_path_cookies = message_in.getValue("cookies_path"); + mCachePath = user_data_path_cache + "cef_cache"; + mCookiePath = user_data_path_cookies + "cef_cookies"; } else if (message_name == "size_change") { -- cgit v1.2.3 From bd817f6f422991c2653493436c7845e75ea9d855 Mon Sep 17 00:00:00 2001 From: rider Date: Fri, 6 Nov 2015 14:12:30 -0800 Subject: MAINT-5754: Basic keyboard functionality on the Mac. Still incomplete --- indra/media_plugins/cef/media_plugin_cef.cpp | 41 +++++++++++++++++++++------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index bb2270181e..d653aaace9 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -551,6 +551,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string) #if LL_DARWIN std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); + +#if 0 if (event == "down") { //mLLCEFLib->keyPress(key, true); @@ -562,7 +565,21 @@ void MediaPluginCEF::receiveMessage(const char* message_string) //mLLCEFLib->keyPress(key, false); mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_UP, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); } - +#else + // Treat unknown events as key-up for safety. + LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP; + if (event == "down") + { + key_event = LLCEFLib::KE_KEY_DOWN; + } + else if (event == "repeat") + { + key_event = LLCEFLib::KE_KEY_REPEAT; + } + + keyEvent(key_event, key, LLCEFLib::KM_MODIFIER_NONE, native_key_data); + +#endif #elif LL_WINDOWS std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); @@ -708,12 +725,20 @@ void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib:: #if LL_DARWIN std::string utf8_text; + uint32_t native_char_code = native_key_data["char_code"].asInteger(); + uint32_t native_scan_code = native_key_data["scan_code"].asInteger(); + uint32_t native_virtual_key = native_key_data["key_code"].asInteger(); + uint32_t native_modifiers = native_key_data["modifiers"].asInteger(); + + + if (key < 128) { - utf8_text = (char)key; + utf8_text = (char)native_virtual_key; } - + switch ((KEY)key) + { case KEY_BACKSPACE: utf8_text = (char)8; break; case KEY_TAB: utf8_text = (char)9; break; @@ -725,16 +750,12 @@ void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib:: break; } - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - mLLCEFLib->keyboardEvent(key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + mLLCEFLib->keyboardEvent(key_event, native_char_code, utf8_text.c_str(), native_modifiers, native_scan_code, native_virtual_key, native_modifiers); #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); #endif }; @@ -743,7 +764,7 @@ void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboar { #if LL_DARWIN //mLLCEFLib->keyPress(utf8str[0], true); - mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); + //mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); -- cgit v1.2.3 From 5449ae73b337c026afa93e99a47b670c28c8eb80 Mon Sep 17 00:00:00 2001 From: rider Date: Sat, 7 Nov 2015 12:09:08 -0800 Subject: MAINT-5754: Finish key modifier experiment. Still not working. --- indra/media_plugins/cef/media_plugin_cef.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index d653aaace9..7d60c1a5ed 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -720,7 +720,7 @@ void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& nat //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) +void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers_x, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN std::string utf8_text; @@ -729,14 +729,23 @@ void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib:: uint32_t native_scan_code = native_key_data["scan_code"].asInteger(); uint32_t native_virtual_key = native_key_data["key_code"].asInteger(); uint32_t native_modifiers = native_key_data["modifiers"].asInteger(); - - if (key < 128) { utf8_text = (char)native_virtual_key; } + unsigned int modifers = LLCEFLib::KM_MODIFIER_NONE; + + if (native_modifiers & (MASK_CONTROL | MASK_MAC_CONTROL)) + modifers |= LLCEFLib::KM_MODIFIER_CONTROL; + if (native_modifiers & MASK_SHIFT) + modifers |= LLCEFLib::KM_MODIFIER_SHIFT; + if (native_modifiers & MASK_ALT) + modifers |= LLCEFLib::KM_MODIFIER_ALT; + + //modifers |= LLCEFLib::KM_MODIFIER_META; + switch ((KEY)key) { @@ -750,7 +759,10 @@ void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib:: break; } - mLLCEFLib->keyboardEvent(key_event, native_char_code, utf8_text.c_str(), native_modifiers, native_scan_code, native_virtual_key, native_modifiers); + mLLCEFLib->keyboardEvent(key_event, native_char_code, utf8_text.c_str(), + static_cast(modifers), + native_scan_code, native_virtual_key, native_modifiers); + #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); -- cgit v1.2.3 From 66848f7a94438f2fe9edd4fad9c12ea44ad285b2 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 9 Nov 2015 11:53:09 -0800 Subject: Undo the clobbering that the PR did :) --- indra/media_plugins/cef/media_plugin_cef.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 7d60c1a5ed..ea451ed5b6 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -128,7 +128,7 @@ MediaPluginBase(host_send_func, host_user_data) // MediaPluginCEF::~MediaPluginCEF() { - mLLCEFLib->reset(); + mLLCEFLib->requestExit(); } //////////////////////////////////////////////////////////////////////////////// @@ -532,11 +532,12 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "scroll_event") { + S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); const int scaling_factor = 40; y *= -scaling_factor; - mLLCEFLib->mouseWheel(y); + mLLCEFLib->mouseWheel(x, y); } else if (message_name == "text_event") { -- cgit v1.2.3 From 148de7ceeb1acd6fe76f0986812e32d2488202b7 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 10 Nov 2015 14:26:47 -0800 Subject: Have the media_cef plugin post goodbye back to the plugin. --- indra/media_plugins/cef/media_plugin_cef.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index ea451ed5b6..86157bf852 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -344,6 +344,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "cleanup") { + LLPluginMessage message("base", "goodbye"); + sendMessage(message); } else if (message_name == "shm_added") { -- cgit v1.2.3 From a9a3cafa9194794850f97bec15e1d176389dd7eb Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 11 Nov 2015 08:55:18 -0800 Subject: Adding plugin goodbye response to quicktime plugin. --- indra/media_plugins/quicktime/media_plugin_quicktime.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index ff1ed8bfbc..7ef5a0fe44 100755 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -837,7 +837,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) else if(message_name == "cleanup") { // TODO: clean up here - } + LLPluginMessage message("base", "goodbye"); + sendMessage(message); + } else if(message_name == "shm_added") { SharedSegmentInfo info; -- cgit v1.2.3 From f563ef61004c70c05c2ca78a8fbdd85ed1dbf1a6 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 11 Nov 2015 09:53:51 -0800 Subject: Add callback for when CEF asks to shutdown --- indra/media_plugins/cef/media_plugin_cef.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 86157bf852..d14254d3d7 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -62,6 +62,7 @@ private: void onStatusMessageCallback(std::string value); void onTitleChangeCallback(std::string title); void onLoadStartCallback(); + void onRequestExitCallback(); void onLoadEndCallback(int httpStatusCode); void onAddressChangeCallback(std::string url); void onNavigateURLCallback(std::string url, std::string target); @@ -128,7 +129,6 @@ MediaPluginBase(host_send_func, host_user_data) // MediaPluginCEF::~MediaPluginCEF() { - mLLCEFLib->requestExit(); } //////////////////////////////////////////////////////////////////////////////// @@ -199,6 +199,16 @@ void MediaPluginCEF::onLoadStartCallback() sendMessage(message); } +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onRequestExitCallback() +{ + mLLCEFLib->shutdown(); + + LLPluginMessage message("base", "goodbye"); + sendMessage(message); +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) @@ -344,8 +354,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "cleanup") { - LLPluginMessage message("base", "goodbye"); - sendMessage(message); + mLLCEFLib->requestExit(); } else if (message_name == "shm_added") { @@ -401,6 +410,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1, _2)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); mLLCEFLib->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2)); + mLLCEFLib->setOnRequestExitCallback(boost::bind(&MediaPluginCEF::onRequestExitCallback, this)); LLCEFLib::LLCEFLibSettings settings; settings.initial_width = 1024; -- cgit v1.2.3 From f8050dbac2861d76adfe8630abe09ca5fb2666f7 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 11 Nov 2015 16:28:11 -0800 Subject: Fix MAINT-5832 Add /LTCG flag to linker for media_plugin_cef.dll to avoid linker restarts --- indra/media_plugins/cef/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index 16015be672..1f6163e41e 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -61,7 +61,7 @@ set (media_plugin_cef_LINK_LIBRARIES if (LINUX) message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n" " Please create a volume_catcher implementation for this platform.") - + elseif (DARWIN) list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher.cpp) find_library(CORESERVICES_LIBRARY CoreServices) @@ -98,7 +98,7 @@ if (WINDOWS) set_target_properties( media_plugin_cef PROPERTIES - LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT" + LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT" LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD" ) endif (WINDOWS) -- cgit v1.2.3 From c2ad041c23b0097aec30acc7447a42f96d515d3b Mon Sep 17 00:00:00 2001 From: rider Date: Fri, 13 Nov 2015 16:22:34 -0800 Subject: Encode keyboard event for reconstruction in the plugin. --- indra/media_plugins/cef/media_plugin_cef.cpp | 46 ++++++---------------------- 1 file changed, 9 insertions(+), 37 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 86157bf852..9e7c390eb2 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -726,46 +726,18 @@ void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& nat void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers_x, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN - std::string utf8_text; - uint32_t native_char_code = native_key_data["char_code"].asInteger(); - uint32_t native_scan_code = native_key_data["scan_code"].asInteger(); - uint32_t native_virtual_key = native_key_data["key_code"].asInteger(); - uint32_t native_modifiers = native_key_data["modifiers"].asInteger(); - - if (key < 128) - { - utf8_text = (char)native_virtual_key; - } - - unsigned int modifers = LLCEFLib::KM_MODIFIER_NONE; - - if (native_modifiers & (MASK_CONTROL | MASK_MAC_CONTROL)) - modifers |= LLCEFLib::KM_MODIFIER_CONTROL; - if (native_modifiers & MASK_SHIFT) - modifers |= LLCEFLib::KM_MODIFIER_SHIFT; - if (native_modifiers & MASK_ALT) - modifers |= LLCEFLib::KM_MODIFIER_ALT; - - //modifers |= LLCEFLib::KM_MODIFIER_META; - - switch ((KEY)key) - - { - case KEY_BACKSPACE: utf8_text = (char)8; break; - case KEY_TAB: utf8_text = (char)9; break; - case KEY_RETURN: utf8_text = (char)13; break; - case KEY_PAD_RETURN: utf8_text = (char)13; break; - case KEY_ESCAPE: utf8_text = (char)27; break; - - default: - break; - } + uint32_t eventType = native_key_data["event_type"].asInteger(); + uint32_t eventModifiers = native_key_data["event_modifiers"].asInteger(); + uint32_t eventKeycode = native_key_data["event_keycode"].asInteger(); + char eventChars = static_cast(native_key_data["event_chars"].isUndefined() ? 0 : native_key_data["event_chars"].asInteger()); + char eventUChars = static_cast(native_key_data["event_umodchars"].isUndefined() ? 0 : native_key_data["event_umodchars"].asInteger()); + bool eventIsRepeat = native_key_data["event_isrepeat"].asBoolean(); - mLLCEFLib->keyboardEvent(key_event, native_char_code, utf8_text.c_str(), - static_cast(modifers), - native_scan_code, native_virtual_key, native_modifiers); + mLLCEFLib->keyboardEventOSX(eventType, eventModifiers, (eventChars) ? &eventChars : NULL, + (eventUChars) ? &eventUChars : NULL, eventIsRepeat, eventKeycode); + #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); -- cgit v1.2.3 From df29aab81ba962d29b541fb84ffe0a682abcfaf5 Mon Sep 17 00:00:00 2001 From: rider Date: Fri, 13 Nov 2015 16:38:35 -0800 Subject: Throw away any incomplete llsd messages that may have get sent on CR --- indra/media_plugins/cef/media_plugin_cef.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 9e7c390eb2..be69858d47 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -727,6 +727,12 @@ void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib:: { #if LL_DARWIN + if (!native_key_data.has("event_type") || + !native_key_data.has("event_modifiers") || + !native_key_data.has("event_keycode") || + !native_key_data.has("event_isrepeat")) + return; + uint32_t eventType = native_key_data["event_type"].asInteger(); uint32_t eventModifiers = native_key_data["event_modifiers"].asInteger(); uint32_t eventKeycode = native_key_data["event_keycode"].asInteger(); -- cgit v1.2.3 From 311b376ab50bacf2bf113616af2a5bbedfcd5ee5 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 16 Nov 2015 16:09:40 -0800 Subject: Update SetCookie code for new LLCEFLib API and add support for shoing/hising developer console (Inspector) --- indra/media_plugins/cef/media_plugin_cef.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 60f6264db4..a53b453b3e 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -499,7 +499,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string) std::string value = message_in.getValue("value"); std::string domain = message_in.getValue("domain"); std::string path = message_in.getValue("path"); - mLLCEFLib->setCookie(uri, name, value, domain, path); + bool httponly = message_in.getValueBoolean("httponly"); + bool secure = message_in.getValueBoolean("secure"); + mLLCEFLib->setCookie(uri, name, value, domain, path, httponly, secure); } else if (message_name == "mouse_event") { @@ -666,6 +668,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mUserAgentSubtring = message_in.getValue("user_agent"); } + else if (message_name == "show_web_inspector") + { + mLLCEFLib->showDevTools(true); + } else if (message_name == "plugins_enabled") { mPluginsEnabled = message_in.getValueBoolean("enable"); -- cgit v1.2.3 From 32691c441664821fcb29824461ed85277ae418c8 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 18 Nov 2015 18:17:50 -0800 Subject: initial support for dropdown menus/select widgits --- indra/media_plugins/cef/media_plugin_cef.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index a53b453b3e..ec3518100b 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -56,7 +56,7 @@ public: private: bool init(); - void onPageChangedCallback(unsigned char* pixels, int width, int height); + void onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup); void onCustomSchemeURLCallback(std::string url); void onConsoleMessageCallback(std::string message, std::string source, int line); void onStatusMessageCallback(std::string value); @@ -149,13 +149,31 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg) //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int width, int height) +void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup) { if (mPixels && pixels) { - if (mWidth == width && mHeight == height) + if (is_popup) { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + for (int line = 0; line < height; ++line) + { + int inverted_y = mHeight - y - height; + int src = line * width * mDepth; + int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth; + + if (dst + width * mDepth < mWidth * mHeight * mDepth) + { + memcpy(mPixels + dst, pixels + src, width * mDepth); + } + } + } + else + { + if (mWidth == width && mHeight == height) + { + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); + } + } setDirty(0, 0, mWidth, mHeight); } @@ -399,7 +417,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) if (message_name == "init") { // event callbacks from LLCefLib - mLLCEFLib->setOnPageChangedCallback(boost::bind(&MediaPluginCEF::onPageChangedCallback, this, _1, _2, _3)); + mLLCEFLib->setOnPageChangedCallback(boost::bind(&MediaPluginCEF::onPageChangedCallback, this, _1, _2, _3, _4, _5, _6)); mLLCEFLib->setOnCustomSchemeURLCallback(boost::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, _1)); mLLCEFLib->setOnConsoleMessageCallback(boost::bind(&MediaPluginCEF::onConsoleMessageCallback, this, _1, _2, _3)); mLLCEFLib->setOnStatusMessageCallback(boost::bind(&MediaPluginCEF::onStatusMessageCallback, this, _1)); -- cgit v1.2.3 From f2a6e0f89c45e06742204efd92acc494bb14d9bd Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 19 Nov 2015 16:39:40 -0800 Subject: Fix javascript_enabled && plugins_enabled (wrong media class) and pull in new LLCEFLib --- indra/media_plugins/cef/media_plugin_cef.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index ec3518100b..182b7f2546 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -338,7 +338,7 @@ void MediaPluginCEF::authResponse(LLPluginMessage &message) // void MediaPluginCEF::receiveMessage(const char* message_string) { - // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + // std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl; LLPluginMessage message_in; if (message_in.parse(message_string) >= 0) @@ -356,7 +356,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; message.setValueLLSD("versions", versions); - std::string plugin_version = "CEF plugin 1.0.0"; + std::string plugin_version = "CEF plugin 1.1.3"; message.setValue("plugin_version", plugin_version); sendMessage(message); } @@ -400,7 +400,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; } LLPluginMessage message("base", "shm_remove_response"); @@ -409,7 +408,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) @@ -709,7 +707,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else { - //std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; }; } } -- cgit v1.2.3 From 94ea5dce50e97aa6ee7bd36790a995c9ae4dbeba Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 20 Nov 2015 17:34:46 -0800 Subject: pull in llceflib changes for user agent, flash plugins and pdf --- indra/media_plugins/cef/media_plugin_cef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 182b7f2546..c8a52ff5fe 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -438,7 +438,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.cache_enabled = true; settings.cache_path = mCachePath; settings.accept_language_list = mHostLanguage; - settings.user_agent_substring = mUserAgentSubtring; + settings.user_agent_substring = mLLCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); bool result = mLLCEFLib->init(settings); if (!result) -- cgit v1.2.3 From cc0faa34243047303c5cc066525e93c49bc5920d Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Mon, 23 Nov 2015 12:01:32 -0800 Subject: Refrain from sending right mouse button events - crashes OS X - and we don't need them --- indra/media_plugins/cef/media_plugin_cef.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index c8a52ff5fe..77e6d35b11 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -526,15 +526,13 @@ void MediaPluginCEF::receiveMessage(const char* message_string) S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); - //std::string modifiers = message_in.getValue("modifiers"); - + // only even send left mouse button events to LLCEFLib + // (partially prompted by crash in OS X CEF when sending right button events) + // we catch the right click in viewer and display our own context menu anyway S32 button = message_in.getValueS32("button"); LLCEFLib::EMouseButton btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; - if (button == 0) btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; - if (button == 1) btn = LLCEFLib::MB_MOUSE_BUTTON_RIGHT; - if (button == 2) btn = LLCEFLib::MB_MOUSE_BUTTON_MIDDLE; - if (event == "down") + if (event == "down" && button == 0) { mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y); mLLCEFLib->setFocus(true); @@ -543,7 +541,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) str << "Mouse down at = " << x << ", " << y; postDebugMessage(str.str()); } - else if (event == "up") + else if (event == "up" && button == 0) { mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y); -- cgit v1.2.3 From eb484d5051c48e3bd35a2f06915eb75cf5c8c1fc Mon Sep 17 00:00:00 2001 From: rider Date: Thu, 3 Dec 2015 13:32:06 -0800 Subject: MAINT-5909: Enable unicode text input on mac and feed that directly into the viewer. Windows fixes still required. --- indra/media_plugins/cef/media_plugin_cef.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 77e6d35b11..919d83bc09 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -763,16 +763,17 @@ void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib:: return; uint32_t eventType = native_key_data["event_type"].asInteger(); + if (!eventType) + return; uint32_t eventModifiers = native_key_data["event_modifiers"].asInteger(); uint32_t eventKeycode = native_key_data["event_keycode"].asInteger(); char eventChars = static_cast(native_key_data["event_chars"].isUndefined() ? 0 : native_key_data["event_chars"].asInteger()); char eventUChars = static_cast(native_key_data["event_umodchars"].isUndefined() ? 0 : native_key_data["event_umodchars"].asInteger()); bool eventIsRepeat = native_key_data["event_isrepeat"].asBoolean(); - mLLCEFLib->keyboardEventOSX(eventType, eventModifiers, (eventChars) ? &eventChars : NULL, (eventUChars) ? &eventUChars : NULL, eventIsRepeat, eventKeycode); - + #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); @@ -787,6 +788,16 @@ void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboar #if LL_DARWIN //mLLCEFLib->keyPress(utf8str[0], true); //mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); + if (!native_key_data.has("event_chars") || !native_key_data.has("event_umodchars") || + !native_key_data.has("event_keycode") || !native_key_data.has("event_modifiers")) + return; + uint32_t unicodeChar = native_key_data["event_chars"].asInteger(); + uint32_t unmodifiedChar = native_key_data["event_umodchars"].asInteger(); + uint32_t keyCode = native_key_data["event_keycode"].asInteger(); + uint32_t rawmodifiers = native_key_data["event_modifiers"].asInteger(); + + mLLCEFLib->injectUnicodeText(unicodeChar, unmodifiedChar, keyCode, rawmodifiers); + #elif LL_WINDOWS U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); -- cgit v1.2.3 From 5f1fe20e9ec530b1e4c4384474011e913180671c Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 11 Dec 2015 16:15:34 -0800 Subject: Missed a commit for MAINT-5948 - enable double click --- indra/media_plugins/cef/media_plugin_cef.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 919d83bc09..19df1fa640 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -245,7 +245,7 @@ void MediaPluginCEF::onAddressChangeCallback(std::string url) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); message.setValue("uri", url); - sendMessage(message); + sendMessage(message); } //////////////////////////////////////////////////////////////////////////////// @@ -551,7 +551,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (event == "double_click") { - // TODO: do we need this ? + mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOUBLE_CLICK, x, y); } else { -- cgit v1.2.3 From 3bf8929d932a6253177be55766cd2a80bb6e224d Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 15 Dec 2015 15:24:41 -0800 Subject: MAINT-5966 - file download failures need feedback --- indra/media_plugins/cef/media_plugin_cef.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'indra/media_plugins') diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 19df1fa640..a2479cc946 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -68,6 +68,7 @@ private: void onNavigateURLCallback(std::string url, std::string target); bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); void onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle); + void onFileDownloadCallback(std::string filename); void postDebugMessage(const std::string& msg); void authResponse(LLPluginMessage &message); @@ -292,6 +293,18 @@ bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::strin return mAuthOK; } +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onFileDownloadCallback(const std::string filename) +{ + mAuthOK = false; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download"); + message.setValue("filename", filename); + + sendMessage(message); +} + void MediaPluginCEF::onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle) { std::string name = ""; @@ -425,6 +438,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mLLCEFLib->setOnAddressChangeCallback(boost::bind(&MediaPluginCEF::onAddressChangeCallback, this, _1)); mLLCEFLib->setOnNavigateURLCallback(boost::bind(&MediaPluginCEF::onNavigateURLCallback, this, _1, _2)); mLLCEFLib->setOnHTTPAuthCallback(boost::bind(&MediaPluginCEF::onHTTPAuthCallback, this, _1, _2, _3, _4)); + mLLCEFLib->setOnFileDownloadCallback(boost::bind(&MediaPluginCEF::onFileDownloadCallback, this, _1)); mLLCEFLib->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2)); mLLCEFLib->setOnRequestExitCallback(boost::bind(&MediaPluginCEF::onRequestExitCallback, this)); -- cgit v1.2.3