master
Brad Payne (Vir Linden) 2015-12-18 13:55:41 -05:00
commit 3f81bb15b3
84 changed files with 2733 additions and 9156 deletions

View File

@ -510,3 +510,4 @@ d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release
27e3cf444c4cc645884960a61325a9ee0e9a2d0f 3.8.4-release
e821ef17c6edea4a59997719d8ba416d8c16e143 3.8.5-release
5a5bd148943bfb46cf2ff2ccf376c42dee93d19b 3.8.6-release
ae3297cdd03ab14f19f3811acbc4acd3eb600336 4.0.0-release

View File

@ -70,12 +70,15 @@ additional_packages = ""
# the viewer_channel_suffix is prefixed by a blank and then appended to the viewer_channel
# for the package in a setting that overrides the compiled-in value
################################################################
additional_packages = "EDU"
## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
## additional_packages = "EDU"
# The EDU package allows us to create a separate release channel whose expirations
# are synchronized as much as possible with the academic year
EDU_sourceid = ""
EDU_viewer_channel_suffix = "edu"
## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
## EDU_sourceid = ""
## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
## EDU_viewer_channel_suffix = "edu"
# Notifications - to configure email notices, add a setting like this:
# <username>_<reponame>.email = <email-address>

View File

@ -1517,6 +1517,52 @@
<key>version</key>
<string>0.0.1</string>
</map>
<key>llceflib</key>
<map>
<key>copyright</key>
<string>Copyright (c) 2014, Linden Research, Inc.</string>
<key>description</key>
<string>LLCefLib implements a headless web browser, rendering modern web content to a memory buffer and providing an API for injecting mouse and keyboard events. It uses the Chromium Embedded Framework (https://bitbucket.org/chromiumembedded/cef)</string>
<key>license</key>
<string>LGPL</string>
<key>license_file</key>
<string>LICENSES/LICENSE-source.txt</string>
<key>name</key>
<string>llceflib</string>
<key>platforms</key>
<map>
<key>darwin</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>5a0f74f8e736d91d2c2c6cbc71db90bd</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/309177/arch/Darwin/installer/llceflib-1.5.1.309177-darwin-309177.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>5ed007e503cd768681ba282fd6d7aa76</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/309177/arch/CYGWIN/installer/llceflib-1.5.1.309177-windows-309177.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>1.5.1.309177</string>
</map>
<key>llphysicsextensions_source</key>
<map>
<key>copyright</key>
@ -1625,66 +1671,6 @@
<key>version</key>
<string>1.0.298370</string>
</map>
<key>llqtwebkit</key>
<map>
<key>copyright</key>
<string>Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).</string>
<key>description</key>
<string>QT cross-platform application and UI framework.</string>
<key>license</key>
<string>LGPL</string>
<key>license_file</key>
<string>LICENSES/llqtwebkit.txt</string>
<key>name</key>
<string>llqtwebkit</string>
<key>platforms</key>
<map>
<key>darwin</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>3c2b6be4c78b2479c3fae612e1053d37</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/canonical_3p-llqtwebkit2/rev/295522/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20141015.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>d31358176b9ba8c676458cc061767c0b</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/canonical_3p-llqtwebkit2/rev/295522/arch/Linux/installer/llqtwebkit-4.7.1-linux-20141015.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>bb4e8c8006c8a7aef6d3e3c36a8cebbf</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/canonical_3p-llqtwebkit2/rev/295522/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20141015.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>4.7.1</string>
</map>
<key>mesa</key>
<map>
<key>license</key>
@ -2052,9 +2038,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>3f8b52280cb1eff2d1acd0214bce1b16</string>
<string>78650a79bda6435e623a940ad425a593</string>
<key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/quicktime_3p-update-quicktime/rev/296445/arch/CYGWIN/installer/quicktime-7.3-windows-296445.tar.bz2</string>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/quicktime_3p-update-quicktime/rev/300073/arch/CYGWIN/installer/quicktime-7.3-windows-300073.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -2063,62 +2049,6 @@
<key>version</key>
<string>7.3</string>
</map>
<key>slplugins</key>
<map>
<key>copyright</key>
<string>Second Life Viewer Source Code - Copyright (C) 2010, Linden Research, Inc.</string>
<key>description</key>
<string>Second Life Viewer Plugins and launcher</string>
<key>license</key>
<string>LGPL</string>
<key>license_file</key>
<string>LICENSES/slplugins-license.txt</string>
<key>name</key>
<string>slplugins</string>
<key>platforms</key>
<map>
<key>darwin</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>f6bfb026572f03a4c8ac6b2b7d7eb0ae</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/slplugins_3p-update-slplugins/rev/298079/arch/Darwin/installer/slplugins-3.7.24.297623.298079-darwin-298079.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>64b8a3bac95b5888a7ede3d7661a18b8</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/slplugins_3p-update-slplugins/rev/298079/arch/Linux/installer/slplugins-3.7.24.297623.298079-linux-298079.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>3a1ea3385303b78b0327c8cea929ef27</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/slplugins_3p-update-slplugins/rev/298079/arch/CYGWIN/installer/slplugins-3.7.24.297623.298079-windows-298079.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>3.7.24.297623.298079</string>
</map>
<key>slvoice</key>
<map>
<key>copyright</key>

View File

@ -57,12 +57,6 @@ add_subdirectory(${VIEWER_PREFIX}test)
if (ENABLE_MEDIA_PLUGINS)
# viewer media plugins
add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
# llplugin testbed code (is this the right way to include it?)
if (LL_TESTS AND NOT LINUX)
add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
add_subdirectory(${VIEWER_PREFIX}test_apps/llfbconnecttest)
endif (LL_TESTS AND NOT LINUX)
endif (ENABLE_MEDIA_PLUGINS)
if (LINUX)

View File

@ -166,6 +166,9 @@ if (LINUX)
-pthread
)
# force this platform to accept TOS via external browser
add_definitions(-DEXTERNAL_TOS)
add_definitions(-DAPPID=secondlife)
add_definitions(-fvisibility=hidden)
# don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.

View File

@ -0,0 +1,40 @@
# -*- cmake -*-
include(Linking)
include(Prebuilt)
if (USESYSTEMLIBS)
set(CEFPLUGIN OFF CACHE BOOL
"CEFPLUGIN support for the llplugin/llmedia test apps.")
else (USESYSTEMLIBS)
use_prebuilt_binary(llceflib)
set(CEFPLUGIN ON CACHE BOOL
"CEFPLUGIN support for the llplugin/llmedia test apps.")
set(CEF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/cef)
endif (USESYSTEMLIBS)
if (WINDOWS)
set(CEF_PLUGIN_LIBRARIES
libcef.lib
libcef_dll_wrapper.lib
llceflib.lib
)
elseif (DARWIN)
FIND_LIBRARY(APPKIT_LIBRARY AppKit)
if (NOT APPKIT_LIBRARY)
message(FATAL_ERROR "AppKit not found")
endif()
FIND_LIBRARY(CEF_LIBRARY "Chromium Embedded Framework" ${ARCH_PREBUILT_DIRS_RELEASE})
if (NOT CEF_LIBRARY)
message(FATAL_ERROR "CEF not found")
endif()
set(CEF_PLUGIN_LIBRARIES
${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
${ARCH_PREBUILT_DIRS_RELEASE}/libLLCefLib.a
${APPKIT_LIBRARY}
${CEF_LIBRARY}
)
elseif (LINUX)
endif (WINDOWS)

View File

@ -14,6 +14,7 @@ set(cmake_SOURCE_FILES
Boost.cmake
BuildVersion.cmake
CARes.cmake
CEFPlugin.cmake
CMakeCopyIfDifferent.cmake
ConfigurePkgConfig.cmake
CURL.cmake
@ -82,18 +83,18 @@ set(cmake_SOURCE_FILES
LLXML.cmake
LScript.cmake
Linking.cmake
## MediaPluginBase.cmake
MediaPluginBase.cmake
NDOF.cmake
OPENAL.cmake
OpenGL.cmake
OpenJPEG.cmake
OpenSSL.cmake
PNG.cmake
## PluginAPI.cmake
PluginAPI.cmake
Prebuilt.cmake
PulseAudio.cmake
Python.cmake
## QuickTimePlugin.cmake
QuickTimePlugin.cmake
TemplateCheck.cmake
Tut.cmake
UI.cmake
@ -102,7 +103,6 @@ set(cmake_SOURCE_FILES
Variables.cmake
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
## WebKitLibPlugin.cmake
XmlRpcEpi.cmake
ZLIB.cmake
)

View File

@ -6,7 +6,7 @@ set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
include(Variables)
set(ARCH_PREBUILT_DIRS ${AUTOBUILD_INSTALL_DIR}/lib)
##set(ARCH_PREBUILT_DIRS_PLUGINS ${AUTOBUILD_INSTALL_DIR}/plugins)
set(ARCH_PREBUILT_DIRS_PLUGINS ${AUTOBUILD_INSTALL_DIR}/plugins)
set(ARCH_PREBUILT_DIRS_RELEASE ${AUTOBUILD_INSTALL_DIR}/lib/release)
set(ARCH_PREBUILT_DIRS_DEBUG ${AUTOBUILD_INSTALL_DIR}/lib/debug)
if (WINDOWS)

View File

@ -26,7 +26,7 @@ set(VIEWER_PREFIX)
set(INTEGRATION_TESTS_PREFIX)
set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)")
set(ENABLE_MEDIA_PLUGINS OFF CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")
set(ENABLE_MEDIA_PLUGINS ON CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")
if(LIBS_CLOSED_DIR)
file(TO_CMAKE_PATH "${LIBS_CLOSED_DIR}" LIBS_CLOSED_DIR)

View File

@ -1,93 +0,0 @@
# -*- cmake -*-
include(Linking)
include(Prebuilt)
include(OpenSSL)
if (USESYSTEMLIBS)
# The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny.
find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED)
include(${QT_USE_FILE})
set(QTDIR $ENV{QTDIR})
if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; "
"Qt is found by looking for qmake in your PATH. "
"Please set your PATH such that 'qmake' is found in \$QTDIR/bin, "
"or unset QTDIR if the found Qt is correct.")
endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
find_package(LLQtWebkit REQUIRED QUIET)
# Add the plugins.
set(QT_PLUGIN_LIBRARIES)
foreach(qlibname qgif qjpeg)
find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH)
if (QT_PLUGIN_${qlibname})
list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}})
else (QT_PLUGIN_${qtlibname})
message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!")
endif (QT_PLUGIN_${qlibname})
endforeach(qlibname)
# qjpeg depends on libjpeg
list(APPEND QT_PLUGIN_LIBRARIES jpeg)
set(WEBKITLIBPLUGIN OFF CACHE BOOL
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
else (USESYSTEMLIBS)
use_prebuilt_binary(llqtwebkit)
set(WEBKITLIBPLUGIN ON CACHE BOOL
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
endif (USESYSTEMLIBS)
if (WINDOWS)
set(WEBKIT_PLUGIN_LIBRARIES
debug llqtwebkitd
debug QtWebKitd4
debug QtOpenGLd4
debug QtNetworkd4
debug QtGuid4
debug QtCored4
debug qtmaind
optimized llqtwebkit
optimized QtWebKit4
optimized QtOpenGL4
optimized QtNetwork4
optimized QtGui4
optimized QtCore4
optimized qtmain
)
elseif (DARWIN)
set(WEBKIT_PLUGIN_LIBRARIES
${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.a
${ARCH_PREBUILT_DIRS_RELEASE}/libQtWebKit.4.dylib
${ARCH_PREBUILT_DIRS_RELEASE}/libQtOpenGL.4.dylib
${ARCH_PREBUILT_DIRS_RELEASE}/libQtNetwork.4.dylib
${ARCH_PREBUILT_DIRS_RELEASE}/libQtGui.4.dylib
${ARCH_PREBUILT_DIRS_RELEASE}/libQtCore.4.dylib
)
elseif (LINUX)
# *HUH: What does this do?
set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES})
set(WEBKIT_PLUGIN_LIBRARIES
llqtwebkit
# qico
# qpng
# qtiff
# qsvg
# QtSvg
QtWebKit
QtOpenGL
QtNetwork
${OPENSSL_LIBRARIES}
QtGui
QtCore
# jscore
# qgif
# qjpeg
# jpeg
fontconfig
X11
Xrender
GL
# sqlite3
# Xi
# SM
)
endif (WINDOWS)

View File

@ -512,11 +512,7 @@ class LLManifest(object):
# ensure that destination path exists
self.cmakedirs(os.path.dirname(dst))
self.created_paths.append(dst)
if not os.path.isdir(src):
self.ccopy(src,dst)
else:
# src is a dir
self.ccopytree(src,dst)
self.ccopymumble(src, dst)
else:
print "Doesn't exist:", src
@ -595,28 +591,38 @@ class LLManifest(object):
else:
os.remove(path)
def ccopy(self, src, dst):
""" Copy a single file or symlink. Uses filecmp to skip copying for existing files."""
def ccopymumble(self, src, dst):
"""Copy a single symlink, file or directory."""
if os.path.islink(src):
linkto = os.readlink(src)
if os.path.islink(dst) or os.path.exists(dst):
if os.path.islink(dst) or os.path.isfile(dst):
os.remove(dst) # because symlinking over an existing link fails
elif os.path.isdir(dst):
shutil.rmtree(dst)
os.symlink(linkto, dst)
elif os.path.isdir(src):
self.ccopytree(src, dst)
else:
# Don't recopy file if it's up-to-date.
# If we seem to be not not overwriting files that have been
# updated, set the last arg to False, but it will take longer.
if os.path.exists(dst) and filecmp.cmp(src, dst, True):
return
# only copy if it's not excluded
if self.includes(src, dst):
try:
os.unlink(dst)
except OSError, err:
if err.errno != errno.ENOENT:
raise
self.ccopyfile(src, dst)
# XXX What about devices, sockets etc.?
# YYY would we put such things into a viewer package?!
shutil.copy2(src, dst)
def ccopyfile(self, src, dst):
""" Copy a single file. Uses filecmp to skip copying for existing files."""
# Don't recopy file if it's up-to-date.
# If we seem to be not not overwriting files that have been
# updated, set the last arg to False, but it will take longer.
if os.path.exists(dst) and filecmp.cmp(src, dst, True):
return
# only copy if it's not excluded
if self.includes(src, dst):
try:
os.unlink(dst)
except OSError, err:
if err.errno != errno.ENOENT:
raise
shutil.copy2(src, dst)
def ccopytree(self, src, dst):
"""Direct copy of shutil.copytree with the additional
@ -632,11 +638,7 @@ class LLManifest(object):
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if os.path.isdir(srcname):
self.ccopytree(srcname, dstname)
else:
self.ccopy(srcname, dstname)
# XXX What about devices, sockets etc.?
self.ccopymumble(srcname, dstname)
except (IOError, os.error), why:
errors.append((srcname, dstname, why))
if errors:

View File

@ -178,6 +178,11 @@ void LLCurl::Responder::setURL(const std::string& url)
mURL = url;
}
const std::string& LLCurl::Responder::getURL()
{
return mURL;
}
void LLCurl::Responder::successResult(const LLSD& content)
{
setResult(HTTP_OK, "", content);

View File

@ -147,6 +147,7 @@ public:
public:
void setHTTPMethod(EHTTPMethod method);
void setURL(const std::string& url);
const std::string& getURL();
void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
void setResponseHeader(const std::string& header, const std::string& value);

View File

@ -20,7 +20,6 @@ include_directories(
${LLRENDER_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${LLQTWEBKIT_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@ -68,7 +67,7 @@ list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES})
add_library (llplugin ${llplugin_SOURCE_FILES})
##add_subdirectory(slplugin)
add_subdirectory(slplugin)
# Add tests
if (LL_TESTS)

View File

@ -1,4 +1,4 @@
/**
/**
* @file llpluginclassmedia.cpp
* @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
*
@ -6,21 +6,21 @@
* $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
@ -41,14 +41,13 @@ static int nextPowerOf2( int value )
{
next_power_of_2 <<= 1;
}
return next_power_of_2;
}
LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
{
mOwner = owner;
mPlugin = NULL;
reset();
//debug use
@ -63,19 +62,19 @@ LLPluginClassMedia::~LLPluginClassMedia()
}
bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
{
{
LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
mPlugin = new LLPluginProcessParent(this);
mPlugin = LLPluginProcessParent::create(this);
mPlugin->setSleepTime(mSleepTime);
// Queue up the media init message -- it will be sent after all the currently queued messages.
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
message.setValue("target", mTarget);
sendMessage(message);
mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
return true;
@ -84,10 +83,10 @@ bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::s
void LLPluginClassMedia::reset()
{
if(mPlugin != NULL)
if(mPlugin)
{
delete mPlugin;
mPlugin = NULL;
mPlugin->requestShutdown();
mPlugin.reset();
}
mTextureParamsReceived = false;
@ -115,7 +114,7 @@ void LLPluginClassMedia::reset()
mTextureHeight = 0;
mMediaWidth = 0;
mMediaHeight = 0;
mDirtyRect = LLRect::null;
mDirtyRect = LLRect::null;
mAutoScaleMedia = false;
mRequestedVolume = 1.0f;
mPriority = PRIORITY_NORMAL;
@ -132,7 +131,7 @@ void LLPluginClassMedia::reset()
mMediaName.clear();
mMediaDescription.clear();
mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
// media_browser class
mNavigateURI.clear();
mNavigateResultCode = -1;
@ -140,7 +139,7 @@ void LLPluginClassMedia::reset()
mHistoryBackAvailable = false;
mHistoryForwardAvailable = false;
mStatusText.clear();
mProgressPercent = 0;
mProgressPercent = 0;
mClickURL.clear();
mClickNavType.clear();
mClickTarget.clear();
@ -148,7 +147,7 @@ void LLPluginClassMedia::reset()
mStatusCode = 0;
mClickEnforceTarget = false;
// media_time class
mCurrentTime = 0.0f;
mDuration = 0.0f;
@ -162,7 +161,7 @@ void LLPluginClassMedia::idle(void)
{
mPlugin->idle();
}
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
{
// Can't process a size change at this time
@ -179,7 +178,7 @@ void LLPluginClassMedia::idle(void)
else
{
mRequestedTextureWidth = mRequestedMediaWidth;
if(mPadding > 1)
{
// Pad up to a multiple of the specified number of bytes per row
@ -189,7 +188,7 @@ void LLPluginClassMedia::idle(void)
{
rowbytes += mPadding - pad;
}
if(rowbytes % mRequestedTextureDepth == 0)
{
mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
@ -201,7 +200,7 @@ void LLPluginClassMedia::idle(void)
}
}
// Size change has been requested but not initiated yet.
size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
@ -216,22 +215,22 @@ void LLPluginClassMedia::idle(void)
mPlugin->removeSharedMemory(mTextureSharedMemoryName);
mTextureSharedMemoryName.clear();
}
mTextureSharedMemorySize = newsize;
mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
if(!mTextureSharedMemoryName.empty())
{
void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
// clear texture memory to avoid random screen visual fuzz from uninitialized texture data
memset( addr, 0x00, newsize );
// We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
// so it may not be worthwhile.
// mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
}
}
// This is our local indicator that a change is in progress.
mTextureWidth = -1;
mTextureHeight = -1;
@ -240,7 +239,7 @@ void LLPluginClassMedia::idle(void)
// This invalidates any existing dirty rect.
resetDirty();
// Send a size change message to the plugin
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
@ -254,11 +253,11 @@ void LLPluginClassMedia::idle(void)
message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
message.setValueReal("background_a", mBackgroundColor.mV[VW]);
mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
}
}
if(mPlugin && mPlugin->isRunning())
{
// Send queued messages
@ -324,11 +323,11 @@ void LLPluginClassMedia::setSizeInternal(void)
mRequestedMediaWidth = mDefaultMediaWidth;
mRequestedMediaHeight = mDefaultMediaHeight;
}
// Save these for size/interest calculations
mFullMediaWidth = mRequestedMediaWidth;
mFullMediaHeight = mRequestedMediaHeight;
if(mAllowDownsample)
{
switch(mPriority)
@ -342,19 +341,19 @@ void LLPluginClassMedia::setSizeInternal(void)
mRequestedMediaHeight /= 2;
}
break;
default:
// Don't adjust texture size
break;
}
}
if(mAutoScaleMedia)
{
mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
}
if(mRequestedMediaWidth > 2048)
mRequestedMediaWidth = 2048;
@ -382,9 +381,9 @@ bool LLPluginClassMedia::textureValid(void)
mRequestedMediaWidth != mMediaWidth ||
mRequestedMediaHeight != mMediaHeight ||
getBitsData() == NULL
)
)
return false;
return true;
}
@ -408,8 +407,8 @@ void LLPluginClassMedia::resetDirty(void)
std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
{
std::string result;
if(modifiers & MASK_CONTROL)
{
result += "control|";
@ -432,7 +431,7 @@ std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
{
result += "meta|";
}
*/
*/
return result;
}
@ -540,11 +539,11 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
// Don't spam unnecessary mouse move events.
return;
}
mLastMouseX = x;
mLastMouseY = y;
}
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
std::string temp;
switch(type)
@ -559,7 +558,7 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
message.setValueS32("button", button);
message.setValueS32("x", x);
// Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
if(!mRequestedTextureCoordsOpenGL)
{
@ -569,42 +568,42 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
message.setValueS32("y", y);
message.setValue("modifiers", translateModifiers(modifiers));
sendMessage(message);
}
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
{
bool result = true;
// FIXME:
// HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
// For now, return false for the ones the webkit plugin won't handle properly.
switch(key_code)
{
case KEY_BACKSPACE:
case KEY_TAB:
case KEY_RETURN:
case KEY_PAD_RETURN:
case KEY_SHIFT:
case KEY_CONTROL:
case KEY_ALT:
case KEY_CAPSLOCK:
case KEY_ESCAPE:
case KEY_PAGE_UP:
case KEY_PAGE_DOWN:
case KEY_END:
case KEY_HOME:
case KEY_LEFT:
case KEY_UP:
case KEY_RIGHT:
case KEY_DOWN:
case KEY_INSERT:
case KEY_BACKSPACE:
case KEY_TAB:
case KEY_RETURN:
case KEY_PAD_RETURN:
case KEY_SHIFT:
case KEY_CONTROL:
case KEY_ALT:
case KEY_CAPSLOCK:
case KEY_ESCAPE:
case KEY_PAGE_UP:
case KEY_PAGE_DOWN:
case KEY_END:
case KEY_HOME:
case KEY_LEFT:
case KEY_UP:
case KEY_RIGHT:
case KEY_DOWN:
case KEY_INSERT:
case KEY_DELETE:
// These will be handled
// These will be handled
break;
default:
// regular ASCII characters will also be handled
if(key_code >= KEY_SPECIAL)
@ -615,7 +614,7 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
break;
}
#if LL_DARWIN
#if LL_DARWIN
if(modifiers & MASK_ALT)
{
// Option-key modified characters should be handled by the unicode input path instead of this one.
@ -634,15 +633,15 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
case KEY_EVENT_REPEAT: temp = "repeat"; break;
}
message.setValue("event", temp);
message.setValueS32("key", key_code);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
sendMessage(message);
}
return result;
}
@ -653,10 +652,10 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
message.setValueS32("x", x);
message.setValueS32("y", y);
message.setValue("modifiers", translateModifiers(modifiers));
sendMessage(message);
}
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
@ -664,18 +663,33 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD
message.setValue("text", text);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
sendMessage(message);
return true;
}
void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
message.setValue("uri", uri);
message.setValue("name", name);
message.setValue("value", value);
message.setValue("domain", domain);
message.setValue("path", path);
message.setValueBoolean("httponly", httponly);
message.setValueBoolean("secure", secure);
sendMessage(message);
}
void LLPluginClassMedia::loadURI(const std::string &uri)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
message.setValue("uri", uri);
sendMessage(message);
}
@ -692,7 +706,7 @@ const char* LLPluginClassMedia::priorityToString(EPriority priority)
case PRIORITY_NORMAL: result = "normal"; break;
case PRIORITY_HIGH: result = "high"; break;
}
return result;
}
@ -703,44 +717,44 @@ void LLPluginClassMedia::setPriority(EPriority priority)
mPriority = priority;
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
std::string priority_string = priorityToString(priority);
switch(priority)
{
case PRIORITY_UNLOADED:
case PRIORITY_UNLOADED:
mSleepTime = 1.0f;
break;
case PRIORITY_STOPPED:
case PRIORITY_STOPPED:
mSleepTime = 1.0f;
break;
case PRIORITY_HIDDEN:
case PRIORITY_HIDDEN:
mSleepTime = 1.0f;
break;
case PRIORITY_SLIDESHOW:
mSleepTime = 1.0f;
break;
case PRIORITY_LOW:
case PRIORITY_LOW:
mSleepTime = 1.0f / 25.0f;
break;
case PRIORITY_NORMAL:
case PRIORITY_NORMAL:
mSleepTime = 1.0f / 50.0f;
break;
case PRIORITY_HIGH:
case PRIORITY_HIGH:
mSleepTime = 1.0f / 100.0f;
break;
}
message.setValue("priority", priority_string);
sendMessage(message);
if(mPlugin)
{
mPlugin->setSleepTime(mSleepTime);
}
LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
// This may affect the calculated size, so recalculate it here.
setSizeInternal();
}
@ -761,12 +775,12 @@ void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
F64 LLPluginClassMedia::getCPUUsage()
{
F64 result = 0.0f;
if(mPlugin)
{
result = mPlugin->getCPUUsage();
}
return result;
}
@ -814,10 +828,11 @@ void LLPluginClassMedia::paste()
sendMessage(message);
}
void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
message.setValue("path", user_data_path);
message.setValue("cache_path", user_data_path_cache);
message.setValue("cookies_path", user_data_path_cookies);
sendMessage(message);
}
@ -830,14 +845,14 @@ void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "plugins_enabled");
message.setValueBoolean("enable", enabled);
sendMessage(message);
}
void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "javascript_enabled");
message.setValueBoolean("enable", enabled);
sendMessage(message);
}
@ -855,11 +870,11 @@ void LLPluginClassMedia::setTarget(const std::string &target)
mTarget = target;
}
/* virtual */
/* virtual */
void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
std::string message_class = message.getClass();
if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
{
std::string message_name = message.getName();
@ -870,21 +885,21 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mRequestedTextureFormat = message.getValueU32("format");
mRequestedTextureType = message.getValueU32("type");
mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
// These two are optional, and will default to 0 if they're not specified.
mDefaultMediaWidth = message.getValueS32("default_width");
mDefaultMediaHeight = message.getValueS32("default_height");
mAllowDownsample = message.getValueBoolean("allow_downsample");
mPadding = message.getValueS32("padding");
setSizeInternal();
mTextureParamsReceived = true;
}
else if(message_name == "updated")
{
{
if(message.hasValue("left"))
{
LLRect newDirtyRect;
@ -892,7 +907,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
newDirtyRect.mTop = message.getValueS32("top");
newDirtyRect.mRight = message.getValueS32("right");
newDirtyRect.mBottom = message.getValueS32("bottom");
// The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
// If they're backwards, swap them.
if(newDirtyRect.mTop < newDirtyRect.mBottom)
@ -901,7 +916,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
newDirtyRect.mTop = newDirtyRect.mBottom;
newDirtyRect.mBottom = temp;
}
if(mDirtyRect.isEmpty())
{
mDirtyRect = newDirtyRect;
@ -911,7 +926,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mDirtyRect.unionWith(newDirtyRect);
}
LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
<< newDirtyRect.mLeft << ", "
<< newDirtyRect.mTop << ", "
<< newDirtyRect.mRight << ", "
@ -921,10 +936,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
<< mDirtyRect.mRight << ", "
<< mDirtyRect.mBottom << ")"
<< LL_ENDL;
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
}
}
bool time_duration_updated = false;
int previous_percent = mProgressPercent;
@ -944,7 +959,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mCurrentRate = message.getValueReal("current_rate");
}
if(message.hasValue("loaded_duration"))
{
mLoadedDuration = message.getValueReal("loaded_duration");
@ -955,7 +970,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// If the message doesn't contain a loaded_duration param, assume it's equal to duration
mLoadedDuration = mDuration;
}
// Calculate a percentage based on the loaded duration and total duration.
if(mDuration != 0.0f) // Don't divide by zero.
{
@ -966,7 +981,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
}
if(previous_percent != mProgressPercent)
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
@ -975,9 +990,9 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
else if(message_name == "media_status")
{
std::string status = message.getValue("status");
LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
if(status == "loading")
{
mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
@ -1017,24 +1032,24 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// TODO: check that name matches?
mNaturalMediaWidth = width;
mNaturalMediaHeight = height;
setSizeInternal();
}
else if(message_name == "size_change_response")
{
std::string name = message.getValue("name");
// TODO: check that name matches?
mTextureWidth = message.getValueS32("texture_width");
mTextureHeight = message.getValueS32("texture_height");
mMediaWidth = message.getValueS32("width");
mMediaHeight = message.getValueS32("height");
// This invalidates any existing dirty rect.
resetDirty();
// TODO: should we verify that the plugin sent back the right values?
// TODO: should we verify that the plugin sent back the right values?
// Two size changes in a row may cause them to not match, due to queueing, etc.
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
@ -1075,6 +1090,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mAuthRealm = message.getValue("realm");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
}
else if (message_name == "file_download")
{
mFileDownloadFilename = message.getValue("filename");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_FILE_DOWNLOAD);
}
else if(message_name == "debug_message")
{
mDebugMessageText = message.getValue("message_text");
@ -1101,7 +1121,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mNavigateResultString = message.getValue("result_string");
mHistoryBackAvailable = message.getValueBoolean("history_back_available");
mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
}
else if(message_name == "progress")
@ -1156,7 +1176,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mGeometryY = message.getValueS32("y");
mGeometryWidth = message.getValueS32("width");
mGeometryHeight = message.getValueS32("height");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
}
else if(message_name == "link_hovered")
@ -1165,7 +1185,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mHoverLink = message.getValue("link");
mHoverText = message.getValue("title");
// message.getValue("text");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
}
else
@ -1181,7 +1201,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// if(message_name == "message_name")
// {
// }
// else
// else
{
LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
}
@ -1189,13 +1209,13 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
}
/* virtual */
/* virtual */
void LLPluginClassMedia::pluginLaunchFailed()
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
}
/* virtual */
/* virtual */
void LLPluginClassMedia::pluginDied()
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
@ -1235,7 +1255,7 @@ void LLPluginClassMedia::focus(bool focused)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
message.setValueBoolean("focused", focused);
sendMessage(message);
}
@ -1262,7 +1282,7 @@ void LLPluginClassMedia::clear_cookies()
void LLPluginClassMedia::set_cookies(const std::string &cookies)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
message.setValue("cookies", cookies);
message.setValue("cookies", cookies);
sendMessage(message);
}
@ -1295,7 +1315,7 @@ void LLPluginClassMedia::browse_reload(bool ignore_cache)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
message.setValueBoolean("ignore_cache", ignore_cache);
sendMessage(message);
}
@ -1415,7 +1435,7 @@ void LLPluginClassMedia::seek(float time)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
message.setValueReal("time", time);
sendMessage(message);
}
@ -1433,11 +1453,11 @@ void LLPluginClassMedia::setVolume(float volume)
if(volume != mRequestedVolume)
{
mRequestedVolume = volume;
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
message.setValueReal("volume", volume);
sendMessage(message);
}
}
@ -1456,4 +1476,3 @@ void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
}

View File

@ -133,6 +133,8 @@ public:
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure);
void loadURI(const std::string &uri);
// "Loading" means uninitialized or any state prior to fully running (processing commands)
@ -191,7 +193,7 @@ public:
bool canPaste() const { return mCanPaste; };
// These can be called before init(), and they will be queued and sent before the media init message.
void setUserDataPath(const std::string &user_data_path);
void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies);
void setLanguageCode(const std::string &language_code);
void setPluginsEnabled(const bool enabled);
void setJavascriptEnabled(const bool enabled);
@ -277,6 +279,10 @@ public:
std::string getHoverText() const { return mHoverText; };
std::string getHoverLink() const { return mHoverLink; };
// these are valid during MEDIA_EVENT_LINK_HOVERED
std::string getFileDownloadFilename() const { return mFileDownloadFilename; }
const std::string& getMediaName() const { return mMediaName; };
std::string getMediaDescription() const { return mMediaDescription; };
@ -372,7 +378,7 @@ protected:
int mPadding;
LLPluginProcessParent *mPlugin;
LLPluginProcessParent::ptr_t mPlugin;
LLRect mDirtyRect;
@ -424,6 +430,7 @@ protected:
std::string mAuthRealm;
std::string mHoverText;
std::string mHoverLink;
std::string mFileDownloadFilename;
/////////////////////////////////////////
// media_time class

View File

@ -64,6 +64,8 @@ public:
MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog
MEDIA_EVENT_FILE_DOWNLOAD, // the plugin wants to download a file
MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process
MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin

View File

@ -33,6 +33,7 @@
#include "llpluginmessagepipe.h"
#include "llpluginmessageclasses.h"
static const F32 GOODBYE_SECONDS = 20.0f;
static const F32 HEARTBEAT_SECONDS = 1.0f;
static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will give the plugin this much time.
@ -194,33 +195,43 @@ void LLPluginProcessChild::idle(void)
}
}
// receivePluginMessage will transition to STATE_UNLOADING
break;
break;
case STATE_SHUTDOWNREQ:
if (mInstance != NULL)
{
sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
delete mInstance;
mInstance = NULL;
}
setState(STATE_UNLOADING);
mWaitGoodbye.setTimerExpirySec(GOODBYE_SECONDS);
break;
case STATE_UNLOADING:
if(mInstance != NULL)
{
sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
delete mInstance;
mInstance = NULL;
}
setState(STATE_UNLOADED);
break;
// waiting for goodbye from plugin.
if (mWaitGoodbye.hasExpired())
{
LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL;
setState(STATE_UNLOADED);
}
break;
case STATE_UNLOADED:
killSockets();
setState(STATE_DONE);
break;
break;
case STATE_ERROR:
// Close the socket to the launcher
killSockets();
// TODO: Where do we go from here? Just exit()?
setState(STATE_DONE);
break;
break;
case STATE_DONE:
// just sit here.
break;
break;
}
} while (idle_again);
@ -350,6 +361,10 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
mPluginFile = parsed.getValue("file");
mPluginDir = parsed.getValue("dir");
}
else if (message_name == "shutdown_plugin")
{
setState(STATE_SHUTDOWNREQ);
}
else if(message_name == "shm_add")
{
std::string name = parsed.getValue("name");
@ -495,6 +510,10 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)
// Let the parent know it's loaded and initialized.
sendMessageToParent(new_message);
}
else if (message_name == "goodbye")
{
setState(STATE_UNLOADED);
}
else if(message_name == "shm_remove_response")
{
// Don't pass this message up to the parent

View File

@ -80,6 +80,7 @@ private:
STATE_PLUGIN_LOADED, // plugin library has been loaded
STATE_PLUGIN_INITIALIZING, // plugin is processing init message
STATE_RUNNING, // steady state (processing messages)
STATE_SHUTDOWNREQ, // Parent has requested a shutdown.
STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded
STATE_UNLOADED, // plugin has been unloaded
STATE_ERROR, // generic bailout state
@ -101,12 +102,12 @@ private:
sharedMemoryRegionsType mSharedMemoryRegions;
LLTimer mHeartbeat;
F64 mSleepTime;
F64 mCPUElapsed;
F64 mSleepTime;
F64 mCPUElapsed;
bool mBlockingRequest;
bool mBlockingResponseReceived;
std::queue<std::string> mMessageQueue;
LLTimer mWaitGoodbye;
void deliverQueuedMessages();
};

View File

@ -46,7 +46,7 @@ bool LLPluginProcessParent::sUseReadThread = false;
apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
LLMutex *LLPluginProcessParent::sInstancesMutex;
std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
LLPluginProcessParent::mapInstances_t LLPluginProcessParent::sInstances;
LLThread *LLPluginProcessParent::sReadThread = NULL;
@ -104,27 +104,12 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
// Don't start the timer here -- start it when we actually launch the plugin process.
mHeartbeat.stop();
// Don't add to the global list until fully constructed.
{
LLMutexLock lock(sInstancesMutex);
sInstances.push_back(this);
}
}
LLPluginProcessParent::~LLPluginProcessParent()
{
LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
// Remove from the global list before beginning destruction.
{
// Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll()
LLMutexLock lock(sInstancesMutex);
{
LLMutexLock lock2(&mIncomingQueueMutex);
sInstances.remove(this);
}
}
// Destroy any remaining shared memory regions
sharedMemoryRegionsType::iterator iter;
while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end())
@ -139,9 +124,109 @@ LLPluginProcessParent::~LLPluginProcessParent()
}
LLProcess::kill(mProcess);
killSockets();
if (!LLApp::isQuitting())
{ // If we are quitting, the network sockets will already have been destroyed.
killSockets();
}
}
/*static*/
LLPluginProcessParent::ptr_t LLPluginProcessParent::create(LLPluginProcessParentOwner *owner)
{
ptr_t that(new LLPluginProcessParent(owner));
// Don't add to the global list until fully constructed.
{
LLMutexLock lock(sInstancesMutex);
sInstances.insert(mapInstances_t::value_type(that.get(), that));
}
return that;
}
/*static*/
void LLPluginProcessParent::shutdown()
{
LLMutexLock lock(sInstancesMutex);
mapInstances_t::iterator it;
for (it = sInstances.begin(); it != sInstances.end(); ++it)
{
(*it).second->setState(STATE_GOODBYE);
(*it).second->idle();
}
sInstances.clear();
}
void LLPluginProcessParent::requestShutdown()
{
setState(STATE_GOODBYE);
mOwner = NULL;
if (LLApp::isQuitting())
{ // if we're quitting, run the idle once more
idle();
removeFromProcessing();
return;
}
static uint32_t count = 0;
std::stringstream namestream;
namestream << "LLPluginProcessParentListener" << ++count;
//*HACK!*//
// After requestShutdown has been called our previous owner will no longer call
// our idle() method. Tie into the event loop here to do that until we are good
// and finished.
LL_DEBUGS("LLPluginProcessParent") << "listening on \"mainloop\"" << LL_ENDL;
mPolling = LLEventPumps::instance().obtain("mainloop")
.listen(namestream.str(), boost::bind(&LLPluginProcessParent::pollTick, this));
}
bool LLPluginProcessParent::pollTick()
{
if (isDone())
{
ptr_t that;
{
// this grabs a copy of the smart pointer to ourselves to ensure that we do not
// get destroyed until after this method returns.
LLMutexLock lock(sInstancesMutex);
mapInstances_t::iterator it = sInstances.find(this);
if (it != sInstances.end())
that = (*it).second;
}
removeFromProcessing();
return true;
}
idle();
return false;
}
void LLPluginProcessParent::removeFromProcessing()
{
// Remove from the global list before beginning destruction.
{
// Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll()
LLMutexLock lock(sInstancesMutex);
{
LLMutexLock lock2(&mIncomingQueueMutex);
sInstances.erase(this);
}
}
}
bool LLPluginProcessParent::wantsPolling() const
{
return (mPollFD.client_data && (mState != STATE_DONE));
}
void LLPluginProcessParent::killSockets(void)
{
{
@ -371,48 +456,48 @@ void LLPluginProcessParent::idle(void)
break;
case STATE_LISTENING:
{
// Launch the plugin process.
{
// Launch the plugin process.
// Only argument to the launcher is the port number we're listening on
mProcessParams.args.add(stringize(mBoundPort));
if (! (mProcess = LLProcess::create(mProcessParams)))
{
errorState();
}
else
{
if(mDebug)
{
#if LL_DARWIN
// If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
// Only argument to the launcher is the port number we're listening on
mProcessParams.args.add(stringize(mBoundPort));
if (! (mProcess = LLProcess::create(mProcessParams)))
{
errorState();
}
else
{
if(mDebug)
{
#if LL_DARWIN
// If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
// The command we're constructing would look like this on the command line:
// osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
// The command we're constructing would look like this on the command line:
// osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
LLProcess::Params params;
params.executable = "/usr/bin/osascript";
params.args.add("-e");
params.args.add("tell application \"Terminal\"");
params.args.add("-e");
params.args.add(STRINGIZE("set win to do script \"gdb -pid "
<< mProcess->getProcessID() << "\""));
params.args.add("-e");
params.args.add("do script \"continue\" in win");
params.args.add("-e");
params.args.add("end tell");
mDebugger = LLProcess::create(params);
LLProcess::Params params;
params.executable = "/usr/bin/osascript";
params.args.add("-e");
params.args.add("tell application \"Terminal\"");
params.args.add("-e");
params.args.add(STRINGIZE("set win to do script \"gdb -pid "
<< mProcess->getProcessID() << "\""));
params.args.add("-e");
params.args.add("do script \"continue\" in win");
params.args.add("-e");
params.args.add("end tell");
mDebugger = LLProcess::create(params);
#endif
}
#endif
}
// This will allow us to time out if the process never starts.
mHeartbeat.start();
mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
setState(STATE_LAUNCHED);
}
}
break;
// This will allow us to time out if the process never starts.
mHeartbeat.start();
mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
setState(STATE_LAUNCHED);
}
}
break;
case STATE_LAUNCHED:
// waiting for the plugin to connect
@ -430,7 +515,7 @@ void LLPluginProcessParent::idle(void)
setState(STATE_CONNECTED);
}
}
break;
break;
case STATE_CONNECTED:
// waiting for hello message from the plugin
@ -439,7 +524,7 @@ void LLPluginProcessParent::idle(void)
{
errorState();
}
break;
break;
case STATE_HELLO:
LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL;
@ -453,7 +538,7 @@ void LLPluginProcessParent::idle(void)
}
setState(STATE_LOADING);
break;
break;
case STATE_LOADING:
// The load_plugin_response message will kick us from here into STATE_RUNNING
@ -461,15 +546,23 @@ void LLPluginProcessParent::idle(void)
{
errorState();
}
break;
break;
case STATE_RUNNING:
if(pluginLockedUpOrQuit())
{
errorState();
}
break;
break;
case STATE_GOODBYE:
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shutdown_plugin");
sendMessage(message);
}
setState(STATE_EXITING);
break;
case STATE_EXITING:
if (! LLProcess::isRunning(mProcess))
{
@ -480,7 +573,7 @@ void LLPluginProcessParent::idle(void)
LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL;
errorState();
}
break;
break;
case STATE_LAUNCH_FAILURE:
if(mOwner != NULL)
@ -488,7 +581,7 @@ void LLPluginProcessParent::idle(void)
mOwner->pluginLaunchFailed();
}
setState(STATE_CLEANUP);
break;
break;
case STATE_ERROR:
if(mOwner != NULL)
@ -496,19 +589,18 @@ void LLPluginProcessParent::idle(void)
mOwner->pluginDied();
}
setState(STATE_CLEANUP);
break;
break;
case STATE_CLEANUP:
LLProcess::kill(mProcess);
killSockets();
setState(STATE_DONE);
break;
dirtyPollSet();
break;
case STATE_DONE:
// just sit here.
break;
break;
}
} while (idle_again);
@ -651,14 +743,14 @@ void LLPluginProcessParent::updatePollset()
sPollSet = NULL;
}
std::list<LLPluginProcessParent*>::iterator iter;
mapInstances_t::iterator iter;
int count = 0;
// Count the number of instances that want to be in the pollset
for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
{
(*iter)->mPolledInput = false;
if((*iter)->mPollFD.client_data)
(*iter).second->mPolledInput = false;
if ((*iter).second->wantsPolling())
{
// This instance has a socket that needs to be polled.
++count;
@ -686,12 +778,12 @@ void LLPluginProcessParent::updatePollset()
// Pollset was created, add all instances to it.
for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
{
if((*iter)->mPollFD.client_data)
if ((*iter).second->wantsPolling())
{
status = apr_pollset_add(sPollSet, &((*iter)->mPollFD));
status = apr_pollset_add(sPollSet, &((*iter).second->mPollFD));
if(status == APR_SUCCESS)
{
(*iter)->mPolledInput = true;
(*iter).second->mPolledInput = true;
}
else
{
@ -756,45 +848,27 @@ void LLPluginProcessParent::poll(F64 timeout)
if(status == APR_SUCCESS)
{
// One or more of the descriptors signalled. Call them.
for(int i = 0; i < count; i++)
{
LLPluginProcessParent *self = (LLPluginProcessParent *)(descriptors[i].client_data);
// NOTE: the descriptor returned here is actually a COPY of the original (even though we create the pollset with APR_POLLSET_NOCOPY).
// This means that even if the parent has set its mPollFD.client_data to NULL, the old pointer may still there in this descriptor.
// It's even possible that the old pointer no longer points to a valid LLPluginProcessParent.
// This means that we can't safely dereference the 'self' pointer here without some extra steps...
if(self)
{
// Make sure this pointer is still in the instances list
bool valid = false;
{
LLMutexLock lock(sInstancesMutex);
for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
{
if(*iter == self)
{
// Lock the instance's mutex before unlocking the global mutex.
// This avoids a possible race condition where the instance gets deleted between this check and the servicePoll() call.
self->mIncomingQueueMutex.lock();
valid = true;
break;
}
}
}
if(valid)
{
// The instance is still valid.
// Pull incoming messages off the socket
self->servicePoll();
self->mIncomingQueueMutex.unlock();
}
else
{
LL_DEBUGS("PluginPoll") << "detected deleted instance " << self << LL_ENDL;
}
for (int i = 0; i < count; i++)
{
void *thatId = descriptors[i].client_data;
ptr_t that;
mapInstances_t::iterator it;
{
LLMutexLock lock(sInstancesMutex);
it = sInstances.find(thatId);
if (it != sInstances.end())
that = (*it).second;
}
if (that)
{
that->mIncomingQueueMutex.lock();
that->servicePoll();
that->mIncomingQueueMutex.unlock();
}
}
}
}
else if(APR_STATUS_IS_TIMEUP(status))
@ -812,6 +886,16 @@ void LLPluginProcessParent::poll(F64 timeout)
LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
}
}
// Remove instances in the done state from the sInstances map.
mapInstances_t::iterator itClean = sInstances.begin();
while (itClean != sInstances.end())
{
if ((*itClean).second->isDone())
sInstances.erase(itClean++);
else
++itClean;
}
}
void LLPluginProcessParent::servicePoll()

View File

@ -30,6 +30,7 @@
#define LL_LLPLUGINPROCESSPARENT_H
#include <queue>
#include <boost/enable_shared_from_this.hpp>
#include "llapr.h"
#include "llprocess.h"
@ -40,8 +41,9 @@
#include "lliosocket.h"
#include "llthread.h"
#include "llsd.h"
#include "llevents.h"
class LLPluginProcessParentOwner
class LLPluginProcessParentOwner : public boost::enable_shared_from_this < LLPluginProcessParentOwner >
{
public:
virtual ~LLPluginProcessParentOwner();
@ -55,8 +57,11 @@ public:
class LLPluginProcessParent : public LLPluginMessagePipeOwner
{
LOG_CLASS(LLPluginProcessParent);
LLPluginProcessParent(LLPluginProcessParentOwner *owner);
public:
LLPluginProcessParent(LLPluginProcessParentOwner *owner);
typedef boost::shared_ptr<LLPluginProcessParent> ptr_t;
~LLPluginProcessParent();
void init(const std::string &launcher_filename,
@ -89,7 +94,10 @@ public:
void sendMessage(const LLPluginMessage &message);
void receiveMessage(const LLPluginMessage &message);
static ptr_t create(LLPluginProcessParentOwner *owner);
void requestShutdown();
// Inherited from LLPluginMessagePipeOwner
/*virtual*/ void receiveMessageRaw(const std::string &message);
/*virtual*/ void receiveMessageEarly(const LLPluginMessage &message);
@ -121,7 +129,10 @@ public:
static bool canPollThreadRun() { return (sPollSet || sPollsetNeedsRebuild || sUseReadThread); };
static void setUseReadThread(bool use_read_thread);
static bool getUseReadThread() { return sUseReadThread; };
static void shutdown();
private:
typedef std::map<void *, ptr_t> mapInstances_t;
enum EState
{
@ -133,6 +144,7 @@ private:
STATE_HELLO, // first message from the plugin process has been received
STATE_LOADING, // process has been asked to load the plugin
STATE_RUNNING, //
STATE_GOODBYE,
STATE_LAUNCH_FAILURE, // Failure before plugin loaded
STATE_ERROR, // generic bailout state
STATE_CLEANUP, // clean everything up
@ -143,6 +155,9 @@ private:
EState mState;
void setState(EState state);
bool wantsPolling() const;
void removeFromProcessing();
bool pluginLockedUp();
bool pluginLockedUpOrQuit();
@ -185,12 +200,15 @@ private:
static apr_pollset_t *sPollSet;
static bool sPollsetNeedsRebuild;
static LLMutex *sInstancesMutex;
static std::list<LLPluginProcessParent*> sInstances;
static mapInstances_t sInstances;
static void dirtyPollSet();
static void updatePollset();
void servicePoll();
static LLThread *sReadThread;
LLTempBoundListener mPolling;
bool pollTick();
LLMutex mIncomingQueueMutex;
std::queue<LLPluginMessage> mIncomingQueue;
};

View File

@ -310,4 +310,3 @@ int main(int argc, char **argv)
return 0;
}

View File

@ -46,12 +46,30 @@ BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return FALSE;
}
// virtual
BOOL LLFocusableElement::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
{
return FALSE;
}
// virtual
BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
return FALSE;
}
// virtual
bool LLFocusableElement::wantsKeyUpKeyDown() const
{
return false;
}
//virtual
bool LLFocusableElement::wantsReturnKey() const
{
return false;
}
// virtual
LLFocusableElement::~LLFocusableElement()
{

View File

@ -57,8 +57,17 @@ public:
// These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus.
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
virtual BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
/**
* If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages
* even for normal character strokes.
* Default implementation returns false.
*/
virtual bool wantsKeyUpKeyDown() const;
virtual bool wantsReturnKey() const;
virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere
protected:
virtual void onFocusReceived();

View File

@ -866,6 +866,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
return handled;
}
BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
@ -898,6 +899,38 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return handled;
}
BOOL LLView::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
if (getVisible() && getEnabled())
{
if (called_from_parent)
{
// Downward traversal
handled = childrenHandleKeyUp(key, mask) != NULL;
}
if (!handled)
{
// For event logging we don't care which widget handles it
// So we capture the key at the end of this function once we know if it was handled
handled = handleKeyUpHere(key, mask);
if (handled)
{
LL_DEBUGS() << "Key handled by " << getName() << LL_ENDL;
}
}
}
if (!handled && !called_from_parent && mParentView)
{
// Upward traversal
handled = mParentView->handleKeyUp(key, mask, FALSE);
}
return handled;
}
// Called from handleKey()
// Handles key in this object. Checking parents and children happens in handleKey()
BOOL LLView::handleKeyHere(KEY key, MASK mask)
@ -905,6 +938,13 @@ BOOL LLView::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
// Called from handleKey()
// Handles key in this object. Checking parents and children happens in handleKey()
BOOL LLView::handleKeyUpHere(KEY key, MASK mask)
{
return FALSE;
}
BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
BOOL handled = FALSE;
@ -1020,6 +1060,12 @@ LLView* LLView::childrenHandleKey(KEY key, MASK mask)
return childrenHandleCharEvent("Key", &LLView::handleKey, key, mask);
}
// Called during downward traversal
LLView* LLView::childrenHandleKeyUp(KEY key, MASK mask)
{
return childrenHandleCharEvent("Key Up", &LLView::handleKeyUp, key, mask);
}
// Called during downward traversal
LLView* LLView::childrenHandleUnicodeChar(llwchar uni_char)
{

View File

@ -378,6 +378,7 @@ public:
// inherited from LLFocusableElement
/* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
/* virtual */ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
/* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@ -509,6 +510,7 @@ public:
//virtual BOOL addChildFromParam(const LLInitParam::BaseBlock& params) { return TRUE; }
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleKeyUpHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual void handleReshape(const LLRect& rect, bool by_user);
@ -538,6 +540,7 @@ protected:
void logMouseEvent();
LLView* childrenHandleKey(KEY key, MASK mask);
LLView* childrenHandleKeyUp(KEY key, MASK mask);
LLView* childrenHandleUnicodeChar(llwchar uni_char);
LLView* childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,

View File

@ -258,7 +258,7 @@ void LLKeyboardWin32::scanKeyboard()
// *TODO: I KNOW there must be a better way of
// interrogating the key state than this, using async key
// state can cause ALL kinds of bugs - Doug
if (key < KEY_BUTTON0)
if ((key < KEY_BUTTON0) && ((key < '0') || (key > '9')))
{
// ...under windows make sure the key actually still is down.
// ...translate back to windows key
@ -267,7 +267,7 @@ void LLKeyboardWin32::scanKeyboard()
if (!pending_key_events && !(GetAsyncKeyState(virtual_key) & 0x8000))
{
//LL_INFOS() << "Key up event missed, resetting" << LL_ENDL;
mKeyLevel[key] = FALSE;
mKeyLevel[key] = FALSE;
}
}
}

View File

@ -28,6 +28,11 @@
#include "llwindowmacosx-objc.h"
#import "llappdelegate-objc.h"
//---------------------------
@implementation NSScreen (PointConversion)
+ (NSScreen *)currentScreenForMouseLocation
@ -42,6 +47,7 @@
return screen;
}
- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint
{
float normalizedX = fabs(fabs(self.frame.origin.x) - fabs(aPoint.x));
@ -57,6 +63,21 @@
@end
void extractKeyDataFromEvent (NSEvent *theEvent, NativeKeyEventData * eventData)
{
eventData->mKeyEvent = NativeKeyEventData::KEYUNKNOWN;
eventData->mEventType = [theEvent type];
eventData->mEventModifiers = [theEvent modifierFlags];
eventData->mEventKeyCode = [theEvent keyCode];
NSString *strEventChars = [theEvent characters];
eventData->mEventChars = (strEventChars.length) ? [strEventChars characterAtIndex:0] : 0;
NSString *strEventUChars = [theEvent charactersIgnoringModifiers];
eventData->mEventUnmodChars = (strEventUChars.length) ? [strEventUChars characterAtIndex:0] : 0;
eventData->mEventRepeat = [theEvent isARepeat];
}
attributedStringInfo getSegments(NSAttributedString *str)
{
attributedStringInfo segments;
@ -402,11 +423,20 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) keyUp:(NSEvent *)theEvent
{
callKeyUp([theEvent keyCode], [theEvent modifierFlags]);
NativeKeyEventData eventData;
extractKeyDataFromEvent( theEvent, &eventData );
eventData.mKeyEvent = NativeKeyEventData::KEYUP;
callKeyUp(&eventData, [theEvent keyCode], [theEvent modifierFlags]);
}
- (void) keyDown:(NSEvent *)theEvent
{
NativeKeyEventData eventData;
extractKeyDataFromEvent( theEvent, &eventData );
eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
uint keycode = [theEvent keyCode];
// We must not depend on flagsChange event to detect modifier flags changed,
// must depend on the modifire flags in the event parameter.
@ -414,7 +444,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
// e.g. OS Window for upload something or Input Window...
// mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
mModifiers = [theEvent modifierFlags];
bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers);
bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers);
unichar ch;
if (acceptsText &&
!mMarkedTextAllowed &&
@ -435,12 +465,17 @@ attributedStringInfo getSegments(NSAttributedString *str)
// Since SL assumes we receive those, we fake it here.
if (mModifiers & NSCommandKeyMask && !mHasMarkedText)
{
callKeyUp([theEvent keyCode], mModifiers);
eventData.mKeyEvent = NativeKeyEventData::KEYUP;
callKeyUp(&eventData, [theEvent keyCode], mModifiers);
}
}
- (void)flagsChanged:(NSEvent *)theEvent
{
NativeKeyEventData eventData;
extractKeyDataFromEvent( theEvent, &eventData );
mModifiers = [theEvent modifierFlags];
callModifier([theEvent modifierFlags]);
@ -462,11 +497,13 @@ attributedStringInfo getSegments(NSAttributedString *str)
if (mModifiers & mask)
{
callKeyDown([theEvent keyCode], 0);
eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
callKeyDown(&eventData, [theEvent keyCode], 0);
}
else
{
callKeyUp([theEvent keyCode], 0);
eventData.mKeyEvent = NativeKeyEventData::KEYUP;
callKeyUp(&eventData, [theEvent keyCode], 0);
}
}

View File

@ -46,6 +46,26 @@ typedef void *CursorRef;
typedef void *NSWindowRef;
typedef void *GLViewRef;
struct NativeKeyEventData {
enum EventType {
KEYUNKNOWN,
KEYUP,
KEYDOWN,
KEYCHAR
};
EventType mKeyEvent;
uint32_t mEventType;
uint32_t mEventModifiers;
uint32_t mEventKeyCode;
uint32_t mEventChars;
uint32_t mEventUnmodChars;
bool mEventRepeat;
};
typedef const NativeKeyEventData * NSKeyEventRef;
// These are defined in llappviewermacosx.cpp.
bool initViewer();
void handleQuit();
@ -102,8 +122,8 @@ void setupInputWindow(NSWindowRef window, GLViewRef view);
// These are all implemented in llwindowmacosx.cpp.
// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
bool callKeyUp(unsigned short key, unsigned int mask);
bool callKeyDown(unsigned short key, unsigned int mask);
bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask);
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask);
void callResetKeys();
bool callUnicodeCallback(wchar_t character, unsigned int mask);
void callRightMouseDown(float *pos, unsigned int mask);

View File

@ -47,6 +47,10 @@ extern BOOL gDebugWindowProc;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
namespace
{
NSKeyEventRef mRawKeyEvent = NULL;
}
//
// LLWindowMacOSX
//
@ -194,14 +198,20 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
// These functions are used as wrappers for our internal event handling callbacks.
// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow.
bool callKeyUp(unsigned short key, unsigned int mask)
bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
{
return gKeyboard->handleKeyUp(key, mask);
mRawKeyEvent = event;
bool retVal = gKeyboard->handleKeyUp(key, mask);
mRawKeyEvent = NULL;
return retVal;
}
bool callKeyDown(unsigned short key, unsigned int mask)
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask)
{
return gKeyboard->handleKeyDown(key, mask);
mRawKeyEvent = event;
bool retVal = gKeyboard->handleKeyDown(key, mask);
mRawKeyEvent = NULL;
return retVal;
}
void callResetKeys()
@ -211,7 +221,23 @@ void callResetKeys()
bool callUnicodeCallback(wchar_t character, unsigned int mask)
{
return gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask);
NativeKeyEventData eventData;
memset(&eventData, 0, sizeof(NativeKeyEventData));
eventData.mKeyEvent = NativeKeyEventData::KEYCHAR;
eventData.mEventType = 0;
eventData.mEventModifiers = mask;
eventData.mEventKeyCode = 0;
eventData.mEventChars = character;
eventData.mEventUnmodChars = character;
eventData.mEventRepeat = false;
mRawKeyEvent = &eventData;
bool result = gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask);
mRawKeyEvent = NULL;
return result;
}
void callFocus()
@ -1713,49 +1739,15 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
LLSD LLWindowMacOSX::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
#if 0
#if 1
if(mRawKeyEvent)
{
char char_code = 0;
UInt32 key_code = 0;
UInt32 modifiers = 0;
UInt32 keyboard_type = 0;
GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code);
GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code);
GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type);
result["char_code"] = (S32)char_code;
result["key_code"] = (S32)key_code;
result["modifiers"] = (S32)modifiers;
result["keyboard_type"] = (S32)keyboard_type;
#if 0
// This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc)
// cause llsd serialization to create XML that the llsd deserializer won't parse!
std::string unicode;
S32 err = noErr;
EventParamType actualType = typeUTF8Text;
UInt32 actualSize = 0;
char *buffer = NULL;
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL);
if(err == noErr)
{
// allocate a buffer and get the actual data.
buffer = new char[actualSize];
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer);
if(err == noErr)
{
unicode.assign(buffer, actualSize);
}
delete[] buffer;
}
result["unicode"] = unicode;
#endif
result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType);
result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers);
result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode);
result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD();
result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD();
result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat);
}
#endif

View File

@ -42,6 +42,7 @@
#include "llgl.h"
#include "llstring.h"
#include "lldir.h"
#include "llsdutil.h"
#include "llglslshader.h"
// System includes
@ -2068,6 +2069,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next
window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff;
window_imp->mKeyVirtualKey = w_param;
window_imp->mRawMsg = u_msg;
window_imp->mRawWParam = w_param;
window_imp->mRawLParam = l_param;
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN");
{
@ -2090,6 +2094,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff;
window_imp->mKeyVirtualKey = w_param;
window_imp->mRawMsg = u_msg;
window_imp->mRawWParam = w_param;
window_imp->mRawLParam = l_param;
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP");
LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER);
@ -2177,6 +2184,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_CHAR:
window_imp->mKeyCharCode = w_param;
window_imp->mRawMsg = u_msg;
window_imp->mRawWParam = w_param;
window_imp->mRawLParam = l_param;
// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
// to figure out how that works. - Doug
@ -3239,6 +3249,9 @@ LLSD LLWindowWin32::getNativeKeyData()
result["scan_code"] = (S32)mKeyScanCode;
result["virtual_key"] = (S32)mKeyVirtualKey;
result["msg"] = ll_sd_from_U32(mRawMsg);
result["w_param"] = ll_sd_from_U32(mRawWParam);
result["l_param"] = ll_sd_from_U32(mRawLParam);
return result;
}

View File

@ -126,7 +126,7 @@ protected:
HCURSOR loadColorCursor(LPCTSTR name);
BOOL isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
LLSD getNativeKeyData();
virtual LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
@ -208,6 +208,9 @@ protected:
U32 mKeyCharCode;
U32 mKeyScanCode;
U32 mKeyVirtualKey;
U32 mRawMsg;
U32 mRawWParam;
U32 mRawLParam;
friend class LLWindowManager;
};

View File

@ -2,16 +2,17 @@
add_subdirectory(base)
add_subdirectory(webkit)
add_subdirectory(gstreamer010)
if (LINUX)
add_subdirectory(gstreamer010)
endif (LINUX)
if (WINDOWS OR DARWIN)
add_subdirectory(quicktime)
add_subdirectory(cef)
endif (WINDOWS OR DARWIN)
if (WINDOWS)
add_subdirectory(winmmshim)
endif (WINDOWS)
add_subdirectory(example)
### add_subdirectory(example)

View File

@ -1,6 +1,6 @@
# -*- cmake -*-
project(media_plugin_webkit)
project(media_plugin_cef)
include(00-Common)
include(LLCommon)
@ -9,17 +9,14 @@ include(LLPlugin)
include(LLMath)
include(LLRender)
include(LLWindow)
include(UI)
include(Linking)
include(PluginAPI)
include(MediaPluginBase)
include(OpenGL)
include(PulseAudio)
include(WebKitLibPlugin)
include(CEFPlugin)
include_directories(
${PULSEAUDIO_INCLUDE_DIRS}
${LLPLUGIN_INCLUDE_DIRS}
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
@ -27,14 +24,14 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${LLQTWEBKIT_INCLUDE_DIR}
${CEF_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
)
### media_plugin_webkit
### media_plugin_cef
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
@ -44,75 +41,72 @@ if(NOT WORD_SIZE EQUAL 32)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
set(media_plugin_webkit_SOURCE_FILES
media_plugin_webkit.cpp
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_webkit_LINK_LIBRARIES
set (media_plugin_cef_LINK_LIBRARIES
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
${WEBKIT_PLUGIN_LIBRARIES}
${PLUGIN_API_WINDOWS_LIBRARIES}
${PULSEAUDIO_LIBRARIES}
)
${CEF_PLUGIN_LIBRARIES}
${PLUGIN_API_WINDOWS_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
)
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_webkit_SOURCE_FILES mac_volume_catcher.cpp)
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_webkit_LINK_LIBRARIES
list(APPEND media_plugin_cef_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)
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_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES})
list(APPEND media_plugin_cef_SOURCE_FILES ${media_plugin_cef_HEADER_FILES})
add_library(media_plugin_webkit
add_library(media_plugin_cef
SHARED
${media_plugin_webkit_SOURCE_FILES}
${media_plugin_cef_SOURCE_FILES}
)
target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES})
add_dependencies(media_plugin_webkit
add_dependencies(media_plugin_cef
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
)
target_link_libraries(media_plugin_cef
${media_plugin_cef_LINK_LIBRARIES}
)
if (WINDOWS)
set_target_properties(
media_plugin_webkit
media_plugin_cef
PROPERTIES
LINK_FLAGS "/MANIFEST:NO"
LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /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_webkit
media_plugin_cef
PROPERTIES
PREFIX ""
BUILD_WITH_INSTALL_RPATH 1
@ -120,13 +114,4 @@ if (DARWIN)
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)

View File

@ -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;

View File

@ -0,0 +1,885 @@
/**
* @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"
#include "volume_catcher.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 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);
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);
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);
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(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();
void setVolume(F32 vol);
bool mEnableMediaPluginDebugging;
std::string mHostLanguage;
bool mCookiesEnabled;
bool mPluginsEnabled;
bool mJavascriptEnabled;
std::string mUserAgentSubtring;
std::string mAuthUsername;
std::string mAuthPassword;
bool mAuthOK;
bool mCanCut;
bool mCanCopy;
bool mCanPaste;
std::string mCachePath;
std::string mCookiePath;
LLCEFLib* mLLCEFLib;
VolumeCatcher mVolumeCatcher;
};
////////////////////////////////////////////////////////////////////////////////
//
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;
mCanCut = false;
mCanCopy = false;
mCanPaste = false;
mCachePath = "";
mCookiePath = "";
mLLCEFLib = new LLCEFLib();
}
////////////////////////////////////////////////////////////////////////////////
//
MediaPluginCEF::~MediaPluginCEF()
{
}
////////////////////////////////////////////////////////////////////////////////
//
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 x, int y, int width, int height, bool is_popup)
{
if (mPixels && pixels)
{
if (is_popup)
{
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);
}
}
////////////////////////////////////////////////////////////////////////////////
//
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::onRequestExitCallback()
{
mLLCEFLib->shutdown();
LLPluginMessage message("base", "goodbye");
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::onAddressChangeCallback(std::string url)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
message.setValue("uri", url);
sendMessage(message);
}
////////////////////////////////////////////////////////////////////////////////
//
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);
}
////////////////////////////////////////////////////////////////////////////////
//
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::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 = "";
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");
if (mAuthOK)
{
mAuthUsername = message.getValue("username");
mAuthPassword = message.getValue("password");
}
}
////////////////////////////////////////////////////////////////////////////////
//
void MediaPluginCEF::receiveMessage(const char* message_string)
{
// std::cerr << "MediaPluginCEF::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.1.3";
message.setValue("plugin_version", plugin_version);
sendMessage(message);
}
else if (message_name == "idle")
{
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
checkEditState();
}
else if (message_name == "cleanup")
{
mLLCEFLib->requestExit();
}
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
{
}
LLPluginMessage message("base", "shm_remove_response");
message.setValue("name", name);
sendMessage(message);
}
else
{
}
}
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, _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));
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->setOnFileDownloadCallback(boost::bind(&MediaPluginCEF::onFileDownloadCallback, this, _1));
mLLCEFLib->setOnCursorChangedCallback(boost::bind(&MediaPluginCEF::onCursorChangedCallback, this, _1, _2));
mLLCEFLib->setOnRequestExitCallback(boost::bind(&MediaPluginCEF::onRequestExitCallback, this));
LLCEFLib::LLCEFLibSettings settings;
settings.initial_width = 1024;
settings.initial_height = 1024;
settings.plugins_enabled = mPluginsEnabled;
settings.javascript_enabled = mJavascriptEnabled;
settings.cookies_enabled = mCookiesEnabled;
settings.cookie_store_path = mCookiePath;
settings.cache_enabled = true;
settings.cache_path = mCachePath;
settings.accept_language_list = mHostLanguage;
settings.user_agent_substring = mLLCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring);
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", true);
sendMessage(message);
}
else if (message_name == "set_user_data_path")
{
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")
{
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 == "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");
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")
{
std::string event = message_in.getValue("event");
S32 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
// 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 (event == "down" && button == 0)
{
mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y);
mLLCEFLib->setFocus(true);
std::stringstream str;
str << "Mouse down at = " << x << ", " << y;
postDebugMessage(str.str());
}
else if (event == "up" && button == 0)
{
mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y);
std::stringstream str;
str << "Mouse up at = " << x << ", " << y;
postDebugMessage(str.str());
}
else if (event == "double_click")
{
mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOUBLE_CLICK, x, y);
}
else
{
mLLCEFLib->mouseMove(x, y);
}
}
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(x, 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");
LLSD native_key_data = message_in.getValueLLSD("native_key_data");
#if 0
if (event == "down")
{
//mLLCEFLib->keyPress(key, true);
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(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");
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.
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, 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);
}
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)
{
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");
}
else if (message_name == "show_web_inspector")
{
mLLCEFLib->showDevTools(true);
}
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_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
{
if (message_name == "set_volume")
{
F32 volume = (F32)message_in.getValueReal("volume");
setVolume(volume);
}
}
else
{
};
}
}
LLCEFLib::EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers)
{
int result = 0;
if (modifiers.find("shift") != std::string::npos)
result |= LLCEFLib::KM_MODIFIER_SHIFT;
if (modifiers.find("alt") != std::string::npos)
result |= LLCEFLib::KM_MODIFIER_ALT;
if (modifiers.find("control") != std::string::npos)
result |= LLCEFLib::KM_MODIFIER_CONTROL;
if (modifiers.find("meta") != std::string::npos)
result |= LLCEFLib::KM_MODIFIER_META;
return (LLCEFLib::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(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers_x, LLSD native_key_data = LLSD::emptyMap())
{
#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();
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<char>(native_key_data["event_chars"].isUndefined() ? 0 : native_key_data["event_chars"].asInteger());
char eventUChars = static_cast<char>(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"]);
U64 lparam = ll_U32_from_sd(native_key_data["l_param"]);
mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam);
#endif
};
void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
{
#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"]);
U64 lparam = ll_U32_from_sd(native_key_data["l_param"]);
mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam);
#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);
}
}
void MediaPluginCEF::setVolume(F32 vol)
{
mVolumeCatcher.setVolume(vol);
}
////////////////////////////////////////////////////////////////////////////////
//
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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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()
{
}

View File

@ -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 <glib.h>
#include <glib-object.h>
#include <pulse/introspect.h>
#include <pulse/context.h>
#include <pulse/subscribe.h>
#include <pulse/glib-mainloop.h> // 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<U32> mSinkInputIndices;
std::map<U32,U32> 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<U32>::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*>((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*>((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*>((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();
}

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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}

View File

@ -44,7 +44,6 @@ include(OPENAL)
include(OpenGL)
include(OpenSSL)
include(PNG)
include(Prebuilt)
include(TemplateCheck)
include(UI)
include(UnixInstall)
@ -62,9 +61,6 @@ if(FMODEX)
include_directories(${FMODEX_INCLUDE_DIR})
endif(FMODEX)
# install SLPlugin host executable and its dynamic-library plugins
use_prebuilt_binary(slplugins)
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
${JSONCPP_INCLUDE_DIR}
@ -1772,44 +1768,12 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable_xp.txt
${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtcore4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtgui4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtnetwork4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtopengl4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtwebkit4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtxmlpatterns4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/ssleay32.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qgif4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qico4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qjpeg4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qmng4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qsvg4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qtiff4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecs4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecs4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecs4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecs4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtcored4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtguid4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtnetworkd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtopengld4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtwebkitd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtxmlpatternsd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/ssleay32.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qgifd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qicod4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qjpegd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qmngd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qsvgd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qtiffd4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecsd4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll
SLPlugin
media_plugin_quicktime
media_plugin_webkit
media_plugin_cef
winmm_shim
windows-crash-logger
)
@ -1854,10 +1818,10 @@ if (WINDOWS)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
## add_dependencies(${VIEWER_BINARY_NAME}
## SLPlugin
## windows-crash-logger
## )
add_dependencies(${VIEWER_BINARY_NAME}
SLPlugin
windows-crash-logger
)
# sets the 'working directory' for debugging from visual studio.
if (NOT UNATTENDED)
@ -2024,9 +1988,8 @@ if (LINUX)
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
linux-crash-logger
## SLPlugin
## media_plugin_webkit
## media_plugin_gstreamer010
SLPlugin
media_plugin_gstreamer010
llcommon
)
@ -2138,7 +2101,7 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
##add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-crash-logger)
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger)
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
if (ENABLE_SIGNING)
@ -2193,20 +2156,19 @@ if (PACKAGE)
if (DARWIN)
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
# *TODO: Generate these search dirs in the cmake files related to each binary.
## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}")
## list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/webkit/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}")
set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2")
## set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-crash-logger")
set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-crash-logger")
set(VIEWER_EXE_GLOBS "'Second Life' mac-crash-logger")
set(VIEWER_LIB_GLOB "*.dylib")
endif (DARWIN)
if (LINUX)
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged")
set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2")
## set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin")
set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*")
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)

View File

@ -734,7 +734,7 @@
<string>F32</string>
<key>Value</key>
<integer>60</integer>
</map>
</map>
<key>AvatarRotateThresholdFast</key>
<map>
<key>Comment</key>
@ -745,7 +745,7 @@
<string>F32</string>
<key>Value</key>
<integer>2</integer>
</map>
</map>
<key>AvatarBakedTextureUploadTimeout</key>
<map>
<key>Comment</key>
@ -1339,7 +1339,7 @@
<string>String</string>
<key>Value</key>
<string />
</map>
</map>
<key>CacheNumberOfRegionsForObjects</key>
<map>
<key>Comment</key>
@ -3799,7 +3799,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>FirstSelectedEnabledPopups</key>
<map>
<key>Comment</key>
@ -3810,7 +3810,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>FixedWeather</key>
<map>
<key>Comment</key>
@ -3932,7 +3932,7 @@
<key>Value</key>
<string>SW</string>
</map>
<key>FloaterStatisticsRect</key>
<map>
<key>Comment</key>
@ -4459,7 +4459,7 @@
<string>String</string>
<key>Value</key>
<string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/howto/index.html</string>
</map>
</map>
<key>HomeSidePanelURL</key>
<map>
<key>Comment</key>
@ -4525,7 +4525,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>HostID</key>
<map>
<key>Comment</key>
@ -4613,7 +4613,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>IgnorePixelDepth</key>
<map>
<key>Comment</key>
@ -4668,7 +4668,7 @@
<string>F32</string>
<key>Value</key>
<real>0.5</real>
</map>
</map>
<key>InspectorShowTime</key>
<map>
<key>Comment</key>
@ -4679,7 +4679,7 @@
<string>F32</string>
<key>Value</key>
<real>3.0</real>
</map>
</map>
<key>InstallLanguage</key>
<map>
<key>Comment</key>
@ -5241,7 +5241,7 @@
<key>Value</key>
<string>0.0.0</string>
</map>
<key>LastSnapshotToProfileHeight</key>
<map>
<key>Comment</key>
@ -6320,7 +6320,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>MenuAccessKeyTime</key>
<map>
<key>Comment</key>
@ -6485,7 +6485,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>MouseSun</key>
<map>
<key>Comment</key>
@ -6650,7 +6650,7 @@
<string>String</string>
<key>Value</key>
<string />
</map>
</map>
<key>NextLoginLocation</key>
<map>
<key>Comment</key>
@ -6774,7 +6774,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
</map>
</map>
<key>NotificationFriendIMOptions</key>
<map>
<key>Comment</key>
@ -6830,7 +6830,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
</map>
</map>
<key>NotificationObjectIMOptions</key>
<map>
<key>Comment</key>
@ -6844,7 +6844,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
</map>
</map>
<key>NotificationToastLifeTime</key>
<map>
<key>Comment</key>
@ -7403,7 +7403,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>PlaySoundFriendIM</key>
<map>
<key>Comment</key>
@ -7514,7 +7514,7 @@
<key>Value</key>
<real>0.9</real>
</map>
<key>PlainTextChatHistory</key>
<map>
<key>Comment</key>
@ -7526,7 +7526,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>PluginInstancesLow</key>
<map>
<key>Comment</key>
@ -7780,7 +7780,7 @@
<real>0.4</real>
</array>
</map>
<key>PreviewDirection2</key>
<map>
<key>Comment</key>
@ -8092,7 +8092,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>5.0</real>
<real>10.0</real>
</map>
<key>MediaRollOffMax</key>
<map>
@ -8390,7 +8390,7 @@
<key>RenderComplexityStaticMax</key>
<map>
<key>Comment</key>
<string>Sets a static max value for scaling of RenderComplexity
<string>Sets a static max value for scaling of RenderComplexity
display (-1 for dynamic scaling)</string>
<key>Persist</key>
<integer>1</integer>
@ -8468,7 +8468,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderLocalLights</key>
<map>
<key>Comment</key>
@ -8695,7 +8695,7 @@
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
@ -8732,7 +8732,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderAnimateRes</key>
<map>
<key>Comment</key>
@ -8905,7 +8905,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderDepthOfField</key>
<map>
<key>Comment</key>
@ -9034,7 +9034,7 @@
<key>Value</key>
<real>0.1</real>
</map>
<key>RenderHighlightBrightness</key>
<map>
<key>Comment</key>
@ -9058,7 +9058,7 @@
<key>Value</key>
<real>0.6</real>
</map>
<key>RenderHighlightColor</key>
<map>
<key>Comment</key>
@ -9087,7 +9087,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderSpecularResX</key>
<map>
<key>Comment</key>
@ -9992,7 +9992,7 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderAutoMuteByteLimit</key>
<map>
<key>Comment</key>
@ -10047,7 +10047,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>RenderAutoHideSurfaceAreaLimit</key>
<map>
<key>Comment</key>
@ -10533,7 +10533,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>SelectMovableOnly</key>
<map>
<key>Comment</key>
@ -10775,7 +10775,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
<key>ShowCrosshairs</key>
<map>
<key>Comment</key>
@ -10852,7 +10852,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>ShowMiniMapButton</key>
<map>
<key>Comment</key>
@ -10919,7 +10919,7 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>ShowObjectRenderingCost</key>
<key>ShowObjectRenderingCost</key>
<map>
<key>Comment</key>
<string>Show the object rendering cost in build tools</string>
@ -10928,9 +10928,9 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ShowNavbarFavoritesPanel</key>
<integer>1</integer>
</map>
<key>ShowNavbarFavoritesPanel</key>
<map>
<key>Comment</key>
<string>Show/hide navigation bar favorites panel</string>
@ -10939,9 +10939,9 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>1</integer>
</map>
<key>ShowNavbarNavigationPanel</key>
<key>ShowNavbarNavigationPanel</key>
<map>
<key>Comment</key>
<string>Show/hide navigation bar navigation panel</string>
@ -10950,7 +10950,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>1</integer>
</map>
<key>ShowWorldMapButton</key>
<map>
@ -11106,7 +11106,7 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>ShowPGSearchAll</key>
<key>ShowPGSearchAll</key>
<map>
<key>Comment</key>
<string>Display results of search All that are flagged as general</string>
@ -11622,7 +11622,7 @@
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>SnapshotQuality</key>
<map>
<key>Comment</key>
@ -12491,7 +12491,7 @@
<string>String</string>
<key>Value</key>
<string>B56AF90D-6684-48E4-B1E4-722D3DEB2CB6</string>
</map>
</map>
<key>NearByChatChannelUUID</key>
<map>
<key>Comment</key>
@ -12502,7 +12502,7 @@
<string>String</string>
<key>Value</key>
<string>E1158BD6-661C-4981-9DAD-4DCBFF062502</string>
</map>
</map>
<key>NotificationChannelUUID</key>
<map>
<key>Comment</key>
@ -12513,7 +12513,7 @@
<string>String</string>
<key>Value</key>
<string>AEED3193-8709-4693-8558-7452CCA97AE5</string>
</map>
</map>
<key>AlertChannelUUID</key>
<map>
<key>Comment</key>
@ -12524,7 +12524,7 @@
<string>String</string>
<key>Value</key>
<string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string>
</map>
</map>
<key>UIImgWhiteUUID</key>
<map>
<key>Comment</key>
@ -12546,7 +12546,7 @@
<string>S32</string>
<key>Value</key>
<integer>2</integer>
</map>
</map>
<key>UIMaxComboWidth</key>
<map>
<key>Comment</key>
@ -13459,7 +13459,7 @@
<string>String</string>
<key>Value</key>
<string>[i800,i600]</string>
</map>
</map>
<key>sourceid</key>
<map>
<key>Comment</key>
@ -14680,7 +14680,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
<key>EnablePlaceProfile</key>
<map>
<key>Comment</key>
@ -15502,7 +15502,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>PathfindingLineWidth</key>
<map>
<key>Comment</key>
@ -15543,7 +15543,7 @@
<real>1.0</real>
</array>
</map>
<key>HideUIControls</key>
<map>
<key>Comment</key>

View File

@ -125,6 +125,9 @@
#include "llleap.h"
#include "stringize.h"
#include "llcoros.h"
#if !LL_LINUX
#include "cef/llceflib.h"
#endif
// Third party library includes
#include <boost/bind.hpp>
@ -132,7 +135,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in processMarkerFiles
#else
@ -1732,6 +1734,9 @@ bool LLAppViewer::cleanup()
// to ensure shutdown order
LLMortician::setZealous(TRUE);
// Give any remaining SLPlugin instances a chance to exit cleanly.
LLPluginProcessParent::shutdown();
LLVoiceClient::getInstance()->terminate();
disconnectViewer();
@ -2792,7 +2797,7 @@ bool LLAppViewer::initConfiguration()
#endif
if (!gArgs.empty())
{
gWindowTitle += std::string(" ") + gArgs;
gWindowTitle += std::string(" ") + gArgs;
}
LLStringUtil::truncate(gWindowTitle, 255);
@ -3376,8 +3381,11 @@ LLSD LLAppViewer::getViewerInfo() const
info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
}
// TODO: Implement media plugin version query
info["QT_WEBKIT_VERSION"] = "4.7.1 (version number hard-coded)";
#if !LL_LINUX
info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION;
#else
info["LLCEFLIB_VERSION"] = "Undefined";
#endif
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
if (packets_in > 0)

View File

@ -108,6 +108,7 @@
#include "llpluginclassmedia.h"
#include "llteleporthistorystorage.h"
#include "llproxy.h"
#include "llweb.h"
#include "lllogininstance.h" // to check if logged in yet
#include "llsdserialize.h"
@ -1957,6 +1958,16 @@ BOOL LLPanelPreference::postBuild()
gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2));
}
#ifdef EXTERNAL_TOS
LLRadioGroup* ext_browser_settings = getChild<LLRadioGroup>("preferred_browser_behavior");
if (ext_browser_settings)
{
// turn off ability to set external/internal browser
ext_browser_settings->setSelectedByValue(LLWeb::BROWSER_EXTERNAL_ONLY, true);
ext_browser_settings->setEnabled(false);
}
#endif
apply();
return true;
}

View File

@ -46,7 +46,6 @@
#include "message.h"
#include "llstartup.h" // login_alert_done
LLFloaterTOS::LLFloaterTOS(const LLSD& data)
: LLModalDialog( data["message"].asString() ),
mMessage(data["message"].asString()),
@ -85,7 +84,7 @@ protected:
{
if ( mParent )
{
mParent->setSiteIsAlive( true );
mParent->setSiteIsAlive(true);
}
}
@ -136,6 +135,20 @@ BOOL LLFloaterTOS::postBuild()
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("tos_html");
if ( web_browser )
{
// if we are forced to send users to an external site in their system browser
// (e.g.) Linux users because of lack of media support for HTML ToS page
// remove exisiting UI and replace with a link to external page where users can accept ToS
#ifdef EXTERNAL_TOS
LLTextBox* header = getChild<LLTextBox>("tos_heading");
if (header)
header->setVisible(false);
LLTextBox* external_prompt = getChild<LLTextBox>("external_tos_required");
if (external_prompt)
external_prompt->setVisible(true);
web_browser->setVisible(false);
#else
web_browser->addObserver(this);
// Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer.
@ -147,6 +160,7 @@ BOOL LLFloaterTOS::postBuild()
// All links from tos_html should be opened in external browser
media_plugin->setOverrideClickTarget("_external");
}
#endif
}
return TRUE;
@ -154,6 +168,13 @@ BOOL LLFloaterTOS::postBuild()
void LLFloaterTOS::setSiteIsAlive( bool alive )
{
// if we are forced to send users to an external site in their system browser
// (e.g.) Linux users because of lack of media support for HTML ToS page
// force the regular HTML UI to deactivate so alternative is rendered instead.
#ifdef EXTERNAL_TOS
mSiteAlive = false;
#else
mSiteAlive = alive;
// only do this for TOS pages
@ -182,6 +203,7 @@ void LLFloaterTOS::setSiteIsAlive( bool alive )
tos_agreement->setEnabled( true );
}
}
#endif
}
LLFloaterTOS::~LLFloaterTOS()

View File

@ -1605,7 +1605,7 @@ bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCa
void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level)
{
llinfos << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << llendl;
LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << LL_ENDL;
}
// Make all relevant business logic checks on the marketplace listings starting with the folder as argument.

View File

@ -57,6 +57,7 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "lllineeditor.h"
#include "llfloaterwebcontent.h"
#include "llwindowshade.h"
@ -426,6 +427,23 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
return result;
}
////////////////////////////////////////////////////////////////////////////////
//
BOOL LLMediaCtrl::handleKeyUpHere(KEY key, MASK mask)
{
BOOL result = FALSE;
if (mMediaSource)
{
result = mMediaSource->handleKeyUpHere(key, mask);
}
if (!result)
result = LLPanel::handleKeyUpHere(key, mask);
return result;
}
////////////////////////////////////////////////////////////////////////////////
//
void LLMediaCtrl::onVisibilityChange ( BOOL new_visibility )
@ -989,19 +1007,23 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
std::string uuid = self->getClickUUID();
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
LLNotification::Params notify_params;
notify_params.name = "PopupAttempt";
notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
LLWeb::loadURL(url, target, std::string());
if (mTrusted)
{
LLNotifications::instance().forceResponse(notify_params, 0);
}
else
{
LLNotifications::instance().add(notify_params);
}
// CP: removing this code because we no longer support popups so this breaks the flow.
// replaced with a bare call to LLWeb::LoadURL(...)
//LLNotification::Params notify_params;
//notify_params.name = "PopupAttempt";
//notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
//notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
//if (mTrusted)
//{
// LLNotifications::instance().forceResponse(notify_params, 0);
//}
//else
//{
// LLNotifications::instance().add(notify_params);
//}
break;
};
@ -1072,6 +1094,13 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
};
break;
case MEDIA_EVENT_FILE_DOWNLOAD:
{
//llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl;
//LLNotificationsUtil::add("MediaFileDownloadUnsupported");
};
break;
case MEDIA_EVENT_DEBUG_MESSAGE:
{
LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL;
@ -1150,3 +1179,13 @@ void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent)
{
mContextMenu->updateParent(pNewParent);
}
bool LLMediaCtrl::wantsKeyUpKeyDown() const
{
return true;
}
bool LLMediaCtrl::wantsReturnKey() const
{
return true;
}

View File

@ -151,6 +151,7 @@ public:
// over-rides
virtual BOOL handleKeyHere( KEY key, MASK mask);
virtual BOOL handleKeyUpHere(KEY key, MASK mask);
virtual void onVisibilityChange ( BOOL new_visibility );
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE);
@ -171,6 +172,10 @@ public:
void updateContextMenuParent(LLView* pNewParent);
// The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true.
virtual bool wantsKeyUpKeyDown() const;
virtual bool wantsReturnKey() const;
protected:
void convertInputCoords(S32& x, S32& y);

View File

@ -106,7 +106,7 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
mMouseDownX = x;
mMouseDownY = y;
//left mouse down always picks transparent
//left mouse down always picks transparent (but see handleMouseUp)
mPick = gViewerWindow->pickImmediate(x, y, TRUE);
mPick.mKeyMask = mask;
@ -661,30 +661,52 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
&& gAgentAvatarp
&& !gAgentAvatarp->isSitting()
&& !mBlockClickToWalk // another behavior hasn't cancelled click to walk
&& !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
&& (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
|| mPick.mObjectID.notNull())) // or on an object
)
{
// handle special cases of steering picks
LLViewerObject* avatar_object = mPick.getObject();
// We may be doing click to walk, but we don't want to use a target on
// a transparent object because the user thought they were clicking on
// whatever they were seeing through it, so recompute what was clicked on
// ignoring transparent objects
LLPickInfo savedPick = mPick;
mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore particles */);
// get pointer to avatar
while (avatar_object && !avatar_object->isAvatar())
{
avatar_object = (LLViewerObject*)avatar_object->getParent();
}
if (!mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
&& (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
|| mPick.mObjectID.notNull())) // or on an object
{
// handle special cases of steering picks
LLViewerObject* avatar_object = mPick.getObject();
if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
{
const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
// pretend we picked some point a bit in front of avatar
mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
}
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
walkToClickedLocation();
LLFirstUse::notMoving(false);
// get pointer to avatar
while (avatar_object && !avatar_object->isAvatar())
{
avatar_object = (LLViewerObject*)avatar_object->getParent();
}
return TRUE;
if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
{
const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
// pretend we picked some point a bit in front of avatar
mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
}
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
walkToClickedLocation();
LLFirstUse::notMoving(false);
return TRUE;
}
else
{
LL_DEBUGS("maint5901") << "walk target was "
<< (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
<< ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
<< ", pick object was " << mPick.mObjectID
<< LL_ENDL;
// we didn't click to walk, so restore the original target
mPick = savedPick;
}
}
gViewerWindow->setCursor(UI_CURSOR_ARROW);
if (hasMouseCapture())
@ -716,14 +738,33 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLToolPie handleDoubleClick (becoming mouseDown)" << LL_ENDL;
}
if (handleMediaDblClick(mPick))
{
return TRUE;
}
if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
{
// We may be doing double click to walk, but we don't want to use a target on
// a transparent object because the user thought they were clicking on
// whatever they were seeing through it, so recompute what was clicked on
// ignoring transparent objects
LLPickInfo savedPick = mPick;
mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore particles */);
if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
(mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
{
walkToClickedLocation();
return TRUE;
}
else
{
// restore the original pick for any other purpose
mPick = savedPick;
}
}
else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
{
@ -1404,56 +1445,110 @@ static void handle_click_action_play()
bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
{
//FIXME: how do we handle object in different parcel than us?
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
LLPointer<LLViewerObject> objectp = pick.getObject();
//FIXME: how do we handle object in different parcel than us?
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
LLPointer<LLViewerObject> objectp = pick.getObject();
if (!parcel ||
objectp.isNull() ||
pick.mObjectFace < 0 ||
pick.mObjectFace >= objectp->getNumTEs())
{
LLViewerMediaFocus::getInstance()->clearFocus();
if (!parcel ||
objectp.isNull() ||
pick.mObjectFace < 0 ||
pick.mObjectFace >= objectp->getNumTEs())
{
LLViewerMediaFocus::getInstance()->clearFocus();
return false;
}
return false;
}
// Does this face have media?
const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
if(!tep)
return false;
// Does this face have media?
const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
if (!tep)
return false;
LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
if(!mep)
return false;
viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
if (!mep)
return false;
if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
{
if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
{
// It's okay to give this a null impl
LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
}
else
{
// Make sure keyboard focus is set to the media focus object.
gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
mMediaMouseCaptureID = mep->getMediaID();
setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
}
viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
return true;
}
if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
{
if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
{
// It's okay to give this a null impl
LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
}
else
{
// Make sure keyboard focus is set to the media focus object.
gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
LLViewerMediaFocus::getInstance()->clearFocus();
media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
mMediaMouseCaptureID = mep->getMediaID();
setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
}
return false;
return true;
}
LLViewerMediaFocus::getInstance()->clearFocus();
return false;
}
bool LLToolPie::handleMediaDblClick(const LLPickInfo& pick)
{
//FIXME: how do we handle object in different parcel than us?
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
LLPointer<LLViewerObject> objectp = pick.getObject();
if (!parcel ||
objectp.isNull() ||
pick.mObjectFace < 0 ||
pick.mObjectFace >= objectp->getNumTEs())
{
LLViewerMediaFocus::getInstance()->clearFocus();
return false;
}
// Does this face have media?
const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
if (!tep)
return false;
LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
if (!mep)
return false;
viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
{
if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
{
// It's okay to give this a null impl
LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
}
else
{
// Make sure keyboard focus is set to the media focus object.
gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
media_impl->mouseDoubleClick(pick.mUVCoords, gKeyboard->currentMask(TRUE));
mMediaMouseCaptureID = mep->getMediaID();
setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
}
return true;
}
LLViewerMediaFocus::getInstance()->clearFocus();
return false;
}
bool LLToolPie::handleMediaHover(const LLPickInfo& pick)

View File

@ -88,7 +88,8 @@ private:
ECursorType cursorFromObject(LLViewerObject* object);
bool handleMediaClick(const LLPickInfo& info);
bool handleMediaHover(const LLPickInfo& info);
bool handleMediaDblClick(const LLPickInfo& info);
bool handleMediaHover(const LLPickInfo& info);
bool handleMediaMouseUp();
BOOL handleTooltipLand(std::string line, std::string tooltip_msg);
BOOL handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg);

View File

@ -729,7 +729,10 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL
return mKeyHandledByUI[translated_key];
}
BOOL LLViewerKeyboard::handleKeyUp(KEY translated_key, MASK translated_mask)
{
return gViewerWindow->handleKeyUp(translated_key, translated_mask);
}
BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
{

View File

@ -89,6 +89,7 @@ public:
LLViewerKeyboard();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error

File diff suppressed because it is too large Load Diff

View File

@ -150,7 +150,7 @@ public:
static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") );
static void openIDSetup(const std::string &openid_url, const std::string &openid_token);
static void openIDCookieResponse(const std::string &cookie);
static void openIDCookieResponse(const std::string& url, const std::string &cookie);
static void proxyWindowOpened(const std::string &target, const std::string &uuid);
static void proxyWindowClosed(const std::string &uuid);
@ -163,7 +163,8 @@ public:
static LLSD getHeaders();
private:
static void setOpenIDCookie();
static bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure);
static void setOpenIDCookie(const std::string& url);
static void onTeleportFinished();
static LLPluginCookieStore *sCookieStore;
@ -225,7 +226,8 @@ public:
void mouseDown(const LLVector2& texture_coords, MASK mask, S32 button = 0);
void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0);
void mouseMove(const LLVector2& texture_coords, MASK mask);
void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0);
void mouseDoubleClick(const LLVector2& texture_coords, MASK mask);
void mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button = 0);
void scrollWheel(S32 x, S32 y, MASK mask);
void mouseCapture();
@ -238,6 +240,7 @@ public:
void navigateInternal();
void navigateStop();
bool handleKeyHere(KEY key, MASK mask);
bool handleKeyUpHere(KEY key, MASK mask);
bool handleUnicodeCharHere(llwchar uni_char);
bool canNavigateForward();
bool canNavigateBack();

View File

@ -352,6 +352,18 @@ BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return true;
}
BOOL LLViewerMediaFocus::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
{
LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
if (media_impl)
{
media_impl->handleKeyUpHere(key, mask);
}
return true;
}
BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
@ -603,3 +615,13 @@ LLUUID LLViewerMediaFocus::getControlsMediaID()
return LLUUID::null;
}
bool LLViewerMediaFocus::wantsKeyUpKeyDown() const
{
return true;
}
bool LLViewerMediaFocus::wantsReturnKey() const
{
return true;
}

View File

@ -56,6 +56,7 @@ public:
/*virtual*/ bool getFocus();
/*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
/*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
/*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
@ -87,6 +88,10 @@ public:
// Return the ID of the media instance the controls are currently attached to (either focus or hover).
LLUUID getControlsMediaID();
// The MoaP object wants keyup and keydown events. Overridden to return true.
virtual bool wantsKeyUpKeyDown() const;
virtual bool wantsReturnKey() const;
protected:
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();

View File

@ -590,7 +590,13 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
}
break;
case MEDIA_EVENT_FILE_DOWNLOAD:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_FILE_DOWNLOAD" << LL_ENDL;
}
break;
case MEDIA_EVENT_GEOMETRY_CHANGE:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;

View File

@ -1381,7 +1381,11 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
// it's all entered/processed.
if (key == KEY_RETURN && mask == MASK_NONE)
{
return FALSE;
// RIDER: although, at times some of the controlls (in particular the CEF viewer
// would like to know about the KEYDOWN for an enter key... so ask and pass it along.
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus && !keyboard_focus->wantsReturnKey())
return FALSE;
}
return gViewerKeyboard.handleKey(key, mask, repeated);
@ -1399,10 +1403,9 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
tool_inspectp->keyUp(key, mask);
}
return FALSE;
return gViewerKeyboard.handleKeyUp(key, mask);
}
void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
{
LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
@ -2019,6 +2022,7 @@ void LLViewerWindow::initWorldUI()
}
gHUDView = new LLHUDView(hud_rect);
getRootView()->addChild(gHUDView);
getRootView()->sendChildToBack(gHUDView);
}
LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("state_management_buttons_container");
@ -2544,21 +2548,67 @@ void LLViewerWindow::draw()
//#endif
}
// Takes a single keyup event, usually when UI is visible
BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask)
{
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus
&& !(mask & (MASK_CONTROL | MASK_ALT))
&& !gFocusMgr.getKeystrokesOnly())
{
// We have keyboard focus, and it's not an accelerator
if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
{
return keyboard_focus->handleKeyUp(key, mask, FALSE);
}
else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
return (gFocusMgr.getKeyboardFocus() != NULL);
}
}
if (keyboard_focus)
{
if (keyboard_focus->handleKeyUp(key, mask, FALSE))
{
LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL;
LLViewerEventRecorder::instance().logKeyEvent(key, mask);
return TRUE;
}
else {
LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned FALSE" << LL_ENDL;
}
}
// don't pass keys on to world when something in ui has focus
return gFocusMgr.childHasKeyboardFocus(mRootView)
|| LLMenuGL::getKeyboardMode()
|| (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
}
// Takes a single keydown event, usually when UI is visible
BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
{
// hide tooltips on keypress
LLToolTipMgr::instance().blockToolTips();
if (gFocusMgr.getKeyboardFocus()
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus
&& !(mask & (MASK_CONTROL | MASK_ALT))
&& !gFocusMgr.getKeystrokesOnly())
{
// We have keyboard focus, and it's not an accelerator
if (key < 0x80)
if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
{
return keyboard_focus->handleKey(key, mask, FALSE );
}
else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
return (gFocusMgr.getKeyboardFocus() != NULL);
return (keyboard_focus != NULL);
}
}
@ -2572,7 +2622,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
return TRUE;
}
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
// give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus
// as long as focus isn't locked
@ -2598,7 +2647,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
// give floaters first chance to handle TAB key
// so frontmost floater gets focus
// if nothing has focus, go to first or last UI element as appropriate
if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))
if (key == KEY_TAB && (mask & MASK_CONTROL || keyboard_focus == NULL))
{
LL_WARNS() << "LLviewerWindow::handleKey give floaters first chance at tab key " << LL_ENDL;
if (gMenuHolder) gMenuHolder->hideMenus();

View File

@ -314,6 +314,7 @@ public:
LLView* getHintHolder() { return mHintHolder.get(); }
LLView* getLoginPanelHolder() { return mLoginPanelHolder.get(); }
BOOL handleKey(KEY key, MASK mask);
BOOL handleKeyUp(KEY key, MASK mask);
void handleScrollWheel (S32 clicks);
// add and remove views from "popup" layer

View File

@ -234,6 +234,9 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
//static
bool LLWeb::useExternalBrowser(const std::string &url)
{
#ifdef EXTERNAL_TOS
return true;
#else
if (gSavedSettings.getU32("PreferredBrowserBehavior") == BROWSER_EXTERNAL_ONLY)
{
return true;
@ -250,4 +253,5 @@ bool LLWeb::useExternalBrowser(const std::string &url)
return !(boost::regex_search(uri_string, matches, pattern));
}
return false;
#endif
}

View File

@ -57,6 +57,21 @@
width="552">
Please read the following Terms of Service and Privacy Policy carefully. To continue logging in to [SECOND_LIFE], you must accept the agreement.
</text>
<text
type="string"
length="1"
follows="left|top"
font="SansSerif"
height="30"
layout="topleft"
left="16"
name="external_tos_required"
visible="false"
top="32"
word_wrap="true"
width="552">
You will need to go to my.secondlife.com and log in to accept the Terms of Service before you can proceed. Thank you!
</text>
<web_browser
trusted_content="true"
follows="left|top"

View File

@ -236,7 +236,7 @@
name="Web Content Floater Debug Test">
<menu_item_call.on_click
function="Advanced.WebContentTest"
parameter="http://google.com"/>
parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
</menu_item_call>
<menu
create_jump_keys="true"

View File

@ -1438,7 +1438,7 @@
function="Floater.Show"
parameter="bumps" />
</menu_item_call>
<menu_item_separator/>
<menu_item_separator/>
<menu_item_call
label="About [APP_NAME]"
name="About Second Life">
@ -3191,7 +3191,7 @@
shortcut="control|shift|Z">
<menu_item_call.on_click
function="Advanced.WebContentTest"
parameter="http://google.com"/>
parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
</menu_item_call>
<menu_item_call
label="FB Connect Test"

View File

@ -7,7 +7,7 @@
none
</defaultwidget>
<defaultimpl>
media_plugin_webkit
media_plugin_cef
</defaultimpl>
<widgetset name="web">
<label name="web_label">
@ -141,7 +141,7 @@
none
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="none/none">
@ -152,7 +152,7 @@
none
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/*">
@ -185,7 +185,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
@ -207,7 +207,7 @@
web
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/ogg">
@ -229,7 +229,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/postscript">
@ -240,7 +240,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/rtf">
@ -251,7 +251,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/smil">
@ -262,7 +262,7 @@
movie
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/xhtml+xml">
@ -273,7 +273,7 @@
web
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/x-director">
@ -284,7 +284,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mid">
@ -339,7 +339,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/gif">
@ -350,7 +350,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/jpeg">
@ -361,7 +361,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/png">
@ -372,7 +372,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="image/svg+xml">
@ -383,7 +383,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/tiff">
@ -394,7 +394,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/html">
@ -405,7 +405,7 @@
web
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/plain">
@ -416,7 +416,7 @@
text
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="text/xml">
@ -427,7 +427,7 @@
text
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/mpeg">

View File

@ -7,7 +7,7 @@
none
</defaultwidget>
<defaultimpl>
media_plugin_webkit
media_plugin_cef
</defaultimpl>
<widgetset name="web">
<label name="web_label">
@ -152,7 +152,7 @@
none
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/*">
@ -185,7 +185,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
@ -207,7 +207,7 @@
web
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/ogg">
@ -229,7 +229,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/postscript">
@ -240,7 +240,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/rtf">
@ -251,7 +251,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/smil">
@ -262,7 +262,7 @@
movie
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/xhtml+xml">
@ -273,7 +273,7 @@
web
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/x-director">
@ -284,7 +284,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mid">
@ -339,7 +339,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/gif">
@ -350,7 +350,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/jpeg">
@ -361,7 +361,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/png">
@ -372,7 +372,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="image/svg+xml">
@ -383,7 +383,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="image/tiff">
@ -394,7 +394,7 @@
image
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/html">
@ -405,7 +405,7 @@
web
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="text/plain">
@ -416,7 +416,7 @@
text
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype name="text/xml">
@ -427,7 +427,7 @@
text
</widgettype>
<impl>
media_plugin_webkit
media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/mpeg">

View File

@ -1599,10 +1599,23 @@ The object may be out of range or may have been deleted.
icon="alertmodal.tga"
name="CannotDownloadFile"
type="alertmodal">
Unable to download file
<tag>fail</tag>
Unable to download file
<tag>fail</tag>
</notification>
<notification
name="MediaFileDownloadUnsupported"
label=""
type="alert">
<unique/>
<tag>confirm</tag>
You have requested a file download, which is not supported within [SECOND_LIFE].
<usetemplate
ignoretext="Warn about unsupported file downloads"
name="okignore"
yestext="OK"/>
</notification>
<notification
icon="alertmodal.tga"
name="CannotWriteFile"

View File

@ -224,19 +224,6 @@
radio_style="false"
width="400"
top_pad="5"/>
<check_box
top_delta="4"
enabled="true"
follows="left|top"
height="14"
initial_value="false"
control_name="MediaEnablePopups"
label="Enable media browser pop-ups"
left_delta="0"
mouse_opaque="true"
name="media_popup_enabled"
width="400"
top_pad="5"/>
<text
type="string"
length="1"

View File

@ -50,7 +50,7 @@ OpenGL Version: [OPENGL_VERSION]
libcurl Version: [LIBCURL_VERSION]
J2C Decoder Version: [J2C_VERSION]
Audio Driver Version: [AUDIO_DRIVER_VERSION]
Qt Webkit Version: [QT_WEBKIT_VERSION]
LLCEFLib/CEF Version: [LLCEFLIB_VERSION]
Voice Server Version: [VOICE_VERSION]
</string>
<string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string>

View File

@ -26,7 +26,7 @@
#include "linden_common.h"
#include "../llviewerprecompiledheaders.h"
#include <iostream>
#include "../test/lltut.h"

View File

@ -340,9 +340,9 @@ class Windows_i686_Manifest(ViewerManifest):
self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
# Plugin host application
# The current slplugin package places slplugin.exe right into the
# packages base directory.
self.path2basename(pkgdir, "slplugin.exe")
self.path2basename(os.path.join(os.pardir,
'llplugin', 'slplugin', self.args['configuration']),
"slplugin.exe")
self.path2basename("../viewer_components/updater/scripts/windows", "update_install.bat")
# Get shared libs from the shared libs staging directory
@ -428,53 +428,120 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("featuretable_xp.txt")
# Media plugins - QuickTime
# Media plugins - WebKit/Qt
if self.prefix(src=os.path.join(pkgdir, "llplugin"), dst="llplugin"):
if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
self.path("media_plugin_quicktime.dll")
self.path("media_plugin_webkit.dll")
self.path("qtcore4.dll")
self.path("qtgui4.dll")
self.path("qtnetwork4.dll")
self.path("qtopengl4.dll")
self.path("qtwebkit4.dll")
self.path("qtxmlpatterns4.dll")
self.end_prefix()
# For WebKit/Qt plugin runtimes (image format plugins)
if self.prefix(src="imageformats", dst="imageformats"):
self.path("qgif4.dll")
self.path("qico4.dll")
self.path("qjpeg4.dll")
self.path("qmng4.dll")
self.path("qsvg4.dll")
self.path("qtiff4.dll")
self.end_prefix()
# For WebKit/Qt plugin runtimes (codec/character encoding plugins)
if self.prefix(src="codecs", dst="codecs"):
self.path("qcncodecs4.dll")
self.path("qjpcodecs4.dll")
self.path("qkrcodecs4.dll")
self.path("qtwcodecs4.dll")
self.end_prefix()
self.end_prefix()
# Media plugins - CEF
if self.prefix(src='../media_plugins/cef/%s' % self.args['configuration'], dst="llplugin"):
self.path("media_plugin_cef.dll")
self.end_prefix()
# winmm.dll shim
if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
self.path("winmm.dll")
self.end_prefix()
# CEF runtime files - debug
if self.args['configuration'].lower() == 'debug':
if self.prefix(src=debpkgdir, dst="llplugin"):
self.path("libeay32.dll")
self.path("ssleay32.dll")
if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'debug'), dst="llplugin"):
self.path("d3dcompiler_43.dll")
self.path("d3dcompiler_47.dll")
self.path("libcef.dll")
self.path("libEGL.dll")
self.path("libGLESv2.dll")
self.path("llceflib_host.exe")
self.path("natives_blob.bin")
self.path("snapshot_blob.bin")
self.path("widevinecdmadapter.dll")
self.path("wow_helper.exe")
self.end_prefix()
else:
# CEF runtime files - not debug (release, relwithdebinfo etc.)
if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"):
self.path("d3dcompiler_43.dll")
self.path("d3dcompiler_47.dll")
self.path("libcef.dll")
self.path("libEGL.dll")
self.path("libGLESv2.dll")
self.path("llceflib_host.exe")
self.path("natives_blob.bin")
self.path("snapshot_blob.bin")
self.path("widevinecdmadapter.dll")
self.path("wow_helper.exe")
self.end_prefix()
else:
if self.prefix(src=relpkgdir, dst="llplugin"):
self.path("libeay32.dll")
self.path("ssleay32.dll")
self.end_prefix()
# MSVC DLLs needed for CEF and have to be in same directory as plugin
if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', 'Release'), dst="llplugin"):
self.path("msvcp120.dll")
self.path("msvcr120.dll")
self.end_prefix()
# CEF files common to all configurations
if self.prefix(src=os.path.join(os.pardir, 'packages', 'resources'), dst="llplugin"):
self.path("cef.pak")
self.path("cef_100_percent.pak")
self.path("cef_200_percent.pak")
self.path("cef_extensions.pak")
self.path("devtools_resources.pak")
self.path("icudtl.dat")
self.end_prefix()
if self.prefix(src=os.path.join(os.pardir, 'packages', 'resources', 'locales'), dst=os.path.join('llplugin', 'locales')):
self.path("am.pak")
self.path("ar.pak")
self.path("bg.pak")
self.path("bn.pak")
self.path("ca.pak")
self.path("cs.pak")
self.path("da.pak")
self.path("de.pak")
self.path("el.pak")
self.path("en-GB.pak")
self.path("en-US.pak")
self.path("es-419.pak")
self.path("es.pak")
self.path("et.pak")
self.path("fa.pak")
self.path("fi.pak")
self.path("fil.pak")
self.path("fr.pak")
self.path("gu.pak")
self.path("he.pak")
self.path("hi.pak")
self.path("hr.pak")
self.path("hu.pak")
self.path("id.pak")
self.path("it.pak")
self.path("ja.pak")
self.path("kn.pak")
self.path("ko.pak")
self.path("lt.pak")
self.path("lv.pak")
self.path("ml.pak")
self.path("mr.pak")
self.path("ms.pak")
self.path("nb.pak")
self.path("nl.pak")
self.path("pl.pak")
self.path("pt-BR.pak")
self.path("pt-PT.pak")
self.path("ro.pak")
self.path("ru.pak")
self.path("sk.pak")
self.path("sl.pak")
self.path("sr.pak")
self.path("sv.pak")
self.path("sw.pak")
self.path("ta.pak")
self.path("te.pak")
self.path("th.pak")
self.path("tr.pak")
self.path("uk.pak")
self.path("vi.pak")
self.path("zh-CN.pak")
self.path("zh-TW.pak")
self.end_prefix()
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
@ -739,14 +806,13 @@ class Darwin_i386_Manifest(ViewerManifest):
dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
# our apps
for app_bld_dir, app in ((os.path.join(os.pardir,
"mac_crash_logger",
self.args['configuration']),
"mac-crash-logger.app"),
for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),
# plugin launcher
(pkgdir, "SLPlugin.app"),
(os.path.join("llplugin", "slplugin"), "SLPlugin.app"),
):
self.path2basename(app_bld_dir, app)
self.path2basename(os.path.join(os.pardir,
app_bld_dir, self.args['configuration']),
app)
# our apps dependencies on shared libs
# for each app, for each dylib we collected in dylibs,
@ -759,46 +825,57 @@ class Darwin_i386_Manifest(ViewerManifest):
symlinkf(src, dst)
except OSError as err:
print "Can't symlink %s -> %s: %s" % (src, dst, err)
# SLPlugin.app/Contents/Resources gets those Qt4 libraries it needs.
if self.prefix(src="", dst="SLPlugin.app/Contents/Resources"):
for libfile in ('libQtCore.4.dylib',
'libQtCore.4.7.1.dylib',
'libQtGui.4.dylib',
'libQtGui.4.7.1.dylib',
'libQtNetwork.4.dylib',
'libQtNetwork.4.7.1.dylib',
'libQtOpenGL.4.dylib',
'libQtOpenGL.4.7.1.dylib',
'libQtSvg.4.dylib',
'libQtSvg.4.7.1.dylib',
'libQtWebKit.4.dylib',
'libQtWebKit.4.7.1.dylib',
'libQtXml.4.dylib',
'libQtXml.4.7.1.dylib'):
self.path2basename(relpkgdir, libfile)
self.end_prefix("SLPlugin.app/Contents/Resources")
# Qt4 codecs go to llplugin. Not certain why but this is the first
# location probed according to dtruss so we'll go with that.
if self.prefix(src=os.path.join(pkgdir, "llplugin/codecs/"), dst="llplugin/codecs"):
self.path("libq*.dylib")
self.end_prefix("llplugin/codecs")
# LLCefLib helper apps go inside SLPlugin.app
if self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"):
for helperappfile in ('LLCefLib Helper.app',
'LLCefLib Helper EH.app'):
self.path2basename(relpkgdir, helperappfile)
# Similarly for imageformats.
if self.prefix(src=os.path.join(pkgdir, "llplugin/imageformats/"), dst="llplugin/imageformats"):
self.path("libq*.dylib")
self.end_prefix("llplugin/imageformats")
pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
# SLPlugin plugins proper
if self.prefix(src=os.path.join(pkgdir, "llplugin"), dst="llplugin"):
self.path("media_plugin_quicktime.dylib")
self.path("media_plugin_webkit.dylib")
self.end_prefix()
# SLPlugin plugins
if self.prefix(src="", dst="llplugin"):
self.path2basename("../media_plugins/quicktime/" + self.args['configuration'],
"media_plugin_quicktime.dylib")
self.path2basename("../media_plugins/cef/" + self.args['configuration'],
"media_plugin_cef.dylib")
self.end_prefix("llplugin")
self.end_prefix("Resources")
# CEF framework goes inside Second Life.app/Contents/Frameworks
if self.prefix(src="", dst="Frameworks"):
frameworkfile="Chromium Embedded Framework.framework"
self.path2basename(relpkgdir, frameworkfile)
self.end_prefix("Frameworks")
# This code constructs a relative path from the
# target framework folder back to the location of the symlink.
# It needs to be relative so that the symlink still works when
# (as is normal) the user moves the app bunlde out of the DMG
# and into the /Applications folder. Note we also call 'raise'
# to terminate the process if we get an error since without
# this symlink, Second Life web media can't possibly work.
# Real Framework folder:
# Second Life.app/Contents/Frameworks/Chromium Embedded Framework.framework/
# Location of symlink and why it'ds relavie
# Second Life.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework/
frameworkpath = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, "Frameworks", "Chromium Embedded Framework.framework")
try:
symlinkf(frameworkpath, pluginframeworkpath)
except OSError as err:
print "Can't symlink %s -> %s: %s" % (frameworkpath, pluginframeworkpath, err)
raise
self.end_prefix("Contents")
# fix up media_plugin.dylib so it knows where to look for CEF files it needs
self.run_command('install_name_tool -change "@executable_path/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "%(config)s/Second Life.app/Contents/Resources/llplugin/media_plugin_cef.dylib"' %
{ 'config' : self.args['configuration'] })
# NOTE: the -S argument to strip causes it to keep enough info for
# annotated backtraces (i.e. function names in the crash log). 'strip' with no
# arguments yields a slightly smaller binary but makes crash logs mostly useless.
@ -808,7 +885,6 @@ class Darwin_i386_Manifest(ViewerManifest):
self.run_command('strip -S %(viewer_binary)r' %
{ 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
def copy_finish(self):
# Force executable permissions to be set for scripts
# see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
@ -985,7 +1061,7 @@ class LinuxManifest(ViewerManifest):
if self.prefix(src="", dst="bin"):
self.path("secondlife-bin","do-not-directly-run-secondlife-bin")
self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
self.path2basename(pkgdir, "SLPlugin")
self.path2basename("../llplugin/slplugin", "SLPlugin")
self.path2basename("../viewer_components/updater/scripts/linux", "update_install")
self.end_prefix("bin")
@ -1005,9 +1081,8 @@ class LinuxManifest(ViewerManifest):
self.end_prefix(icon_path)
# plugins
if self.prefix(src=os.path.join(pkgdir, "llplugin"), dst="bin/llplugin"):
self.path("libmedia_plugin_webkit.so")
self.path("libmedia_plugin_gstreamer.so")
if self.prefix(src="", dst="bin/llplugin"):
self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
self.end_prefix("bin/llplugin")
# llcommon
@ -1147,37 +1222,6 @@ class Linux_i686_Manifest(LinuxManifest):
self.path("libvivoxplatform.so")
self.end_prefix("lib")
# plugin runtime
if self.prefix(src=os.path.join(pkgdir, "lib"), dst="lib"):
self.path("libQtCore.so*")
self.path("libQtGui.so*")
self.path("libQtNetwork.so*")
self.path("libQtOpenGL.so*")
self.path("libQtSvg.so*")
self.path("libQtWebKit.so*")
self.path("libQtXml.so*")
self.end_prefix("lib")
# For WebKit/Qt plugin runtimes (image format plugins)
if self.prefix(src=os.path.join(pkgdir, "llplugin", "imageformats"),
dst="bin/llplugin/imageformats"):
self.path("libqgif.so")
self.path("libqico.so")
self.path("libqjpeg.so")
self.path("libqmng.so")
self.path("libqsvg.so")
self.path("libqtiff.so")
self.end_prefix("bin/llplugin/imageformats")
# For WebKit/Qt plugin runtimes (codec/character encoding plugins)
if self.prefix(src=os.path.join(pkgdir, "llplugin", "codecs"),
dst="bin/llplugin/codecs"):
self.path("libqcncodecs.so")
self.path("libqjpcodecs.so")
self.path("libqkrcodecs.so")
self.path("libqtwcodecs.so")
self.end_prefix("bin/llplugin/codecs")
self.strip_binaries()

View File

@ -1,372 +0,0 @@
# -*- cmake -*-
project(llfbconnecttest)
include(00-Common)
include(FindOpenGL)
include(LLCommon)
include(LLPlugin)
include(Linking)
include(LLSharedLibs)
include(PluginAPI)
include(LLImage)
include(LLMath)
include(LLMessage)
include(LLRender)
include(LLWindow)
include(Glut)
include(Glui)
include_directories(
${LLPLUGIN_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
)
if (DARWIN)
include(CMakeFindFrameworks)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
endif (DARWIN)
### llfbconnecttest
set(llfbconnecttest_SOURCE_FILES
llfbconnecttest.cpp
llfbconnecttest.h
bookmarks.txt
)
add_executable(llfbconnecttest
WIN32
MACOSX_BUNDLE
${llfbconnecttest_SOURCE_FILES}
)
set_target_properties(llfbconnecttest
PROPERTIES
WIN32_EXECUTABLE
FALSE
)
target_link_libraries(llfbconnecttest
${GLUT_LIBRARY}
${GLUI_LIBRARY}
${OPENGL_LIBRARIES}
${LLPLUGIN_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLCOMMON_LIBRARIES}
${PLUGIN_API_WINDOWS_LIBRARIES}
)
if (DARWIN)
# The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app.
target_link_libraries(llfbconnecttest
${COREFOUNDATION_LIBRARY}
)
endif (DARWIN)
add_dependencies(llfbconnecttest
stage_third_party_libs
SLPlugin
media_plugin_webkit
${LLPLUGIN_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLCOMMON_LIBRARIES}
)
# turn off weird GLUI pragma
add_definitions(-DGLUI_NO_LIB_PRAGMA)
if (DARWIN OR LINUX)
# glui.h contains code that triggers the "overloaded-virtual" warning in gcc.
set_source_files_properties(llfbconnecttest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual")
endif (DARWIN OR LINUX)
# Gather build products of the various dependencies into the build directory for the testbed.
if (DARWIN)
# path inside the app bundle where we'll need to copy plugins and other related files
set(PLUGINS_DESTINATION_DIR
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llfbconnecttest.app/Contents/Resources
)
# create the Contents/Resources directory
add_custom_command(
TARGET llfbconnecttest POST_BUILD
COMMAND ${CMAKE_COMMAND}
ARGS
-E
make_directory
${PLUGINS_DESTINATION_DIR}
COMMENT "Creating Resources directory in app bundle."
)
else (DARWIN)
set(PLUGINS_DESTINATION_DIR
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
)
endif (DARWIN)
set(BUILT_SLPLUGIN $<TARGET_FILE:SLPlugin>)
add_custom_command(TARGET llfbconnecttest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_SLPLUGIN}
)
set(BUILT_LLCOMMON $<TARGET_FILE:llcommon>)
add_custom_command(TARGET llfbconnecttest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_LLCOMMON}
)
set(BUILT_WEBKIT_PLUGIN $<TARGET_FILE:media_plugin_webkit>)
add_custom_command(TARGET llfbconnecttest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_WEBKIT_PLUGIN}
)
# copy over bookmarks file if llfbconnecttest gets built
set(BUILT_LLFBCONNECTTEST $<TARGET_FILE:llfbconnecttest>)
add_custom_command(TARGET llfbconnecttest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS ${BUILT_LLFBCONNECTTEST}
)
# also copy it to the same place as SLPlugin, which is what the mac wants...
add_custom_command(TARGET llfbconnecttest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_LLFBCONNECTTEST}
)
if(WINDOWS)
#********************
# Plugin test library deploy
#
# Debug config runtime files required for the FB connect test
set(fbconnecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
set(fbconnecttest_debug_files
libeay32.dll
libglib-2.0-0.dll
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgthread-2.0-0.dll
qtcored4.dll
qtguid4.dll
qtnetworkd4.dll
qtopengld4.dll
qtwebkitd4.dll
ssleay32.dll
)
copy_if_different(
${fbconnecttest_debug_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Debug"
out_targets
${fbconnecttest_debug_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Debug config runtime files required for the FB connect test (Qt image format plugins)
set(fbconecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/imageformats")
set(fbconecttest_debug_files
qgifd4.dll
qicod4.dll
qjpegd4.dll
qmngd4.dll
qsvgd4.dll
qtiffd4.dll
)
copy_if_different(
${fbconecttest_debug_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats"
out_targets
${fbconecttest_debug_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Debug config runtime files required for the FB connect test (Qt codec plugins)
set(fbconnecttest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/codecs")
set(fbconnecttest_debug_files
qcncodecsd4.dll
qjpcodecsd4.dll
qkrcodecsd4.dll
qtwcodecsd4.dll
)
copy_if_different(
${fbconnecttest_debug_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs"
out_targets
${fbconnecttest_debug_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test
set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(fbconnecttest_release_files
libeay32.dll
libglib-2.0-0.dll
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgthread-2.0-0.dll
qtcore4.dll
qtgui4.dll
qtnetwork4.dll
qtopengl4.dll
qtwebkit4.dll
qtxmlpatterns4.dll
ssleay32.dll
)
copy_if_different(
${fbconnecttest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Release"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
copy_if_different(
${fbconnecttest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins)
set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/imageformats")
set(fbconnecttest_release_files
qgif4.dll
qico4.dll
qjpeg4.dll
qmng4.dll
qsvg4.dll
qtiff4.dll
)
copy_if_different(
${fbconnecttest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
copy_if_different(
${fbconnecttest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins)
set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/codecs")
set(fbconnecttest_release_files
qcncodecs4.dll
qjpcodecs4.dll
qkrcodecs4.dll
qtwcodecs4.dll
)
copy_if_different(
${fbconnecttest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Release/codecs"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
copy_if_different(
${fbconnecttest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
add_custom_target(copy_fbconnecttest_libs ALL
DEPENDS
${fbconnect_test_targets}
)
add_dependencies(llfbconnecttest copy_fbconnecttest_libs)
endif(WINDOWS)
if (DARWIN)
set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(fbconnecttest_release_files
libexception_handler.dylib
libaprutil-1.0.dylib
libapr-1.0.dylib
libexpat.1.5.2.dylib
libQtCore.4.7.1.dylib
libQtCore.4.dylib
libQtGui.4.7.1.dylib
libQtGui.4.dylib
libQtNetwork.4.7.1.dylib
libQtNetwork.4.dylib
libQtOpenGL.4.7.1.dylib
libQtOpenGL.4.dylib
libQtWebKit.4.7.1.dylib
libQtWebKit.4.dylib
libQtSvg.4.7.1.dylib
libQtSvg.4.dylib
libQtXml.4.7.1.dylib
libQtXml.4.dylib
)
copy_if_different(
${fbconnecttest_release_src_dir}
"${PLUGINS_DESTINATION_DIR}"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins)
set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/imageformats")
set(fbconnecttest_release_files
libqgif.dylib
libqico.dylib
libqjpeg.dylib
libqmng.dylib
libqsvg.dylib
libqtiff.dylib
)
copy_if_different(
${fbconnecttest_release_src_dir}
"${PLUGINS_DESTINATION_DIR}/imageformats"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins)
set(fbconnecttest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/codecs")
set(fbconnecttest_release_files
libqcncodecs.dylib
libqjpcodecs.dylib
libqkrcodecs.dylib
libqtwcodecs.dylib
)
copy_if_different(
${fbconnecttest_release_src_dir}
"${PLUGINS_DESTINATION_DIR}/codecs"
out_targets
${fbconnecttest_release_files}
)
set(fbconnect_test_targets ${fbconnect_test_targets} ${out_targets})
add_custom_target(copy_fbconnecttest_libs ALL
DEPENDS
${fbconnect_test_targets}
)
add_dependencies(llfbconnecttest copy_fbconnecttest_libs)
endif (DARWIN)
if (LINUX)
endif (LINUX)
ll_deploy_sharedlibs_command(llfbconnecttest)

View File

@ -1,20 +0,0 @@
1. Description
Exercises SLPlugin. Specific functions and goals aren't clear
from the source.
2. Running
2.1 Mac
Make certain '.' is included in PATH. E.g.:
PATH=.:"$PATH" open build-darwin-i386/test_apps/llfbconnecttest/RelWithDebInfo/llfbconnecttest.app
Otherwise the program won't find SLPlugin and will timeout and
fail after 30 seconds and give you little information as to why.
Running 'dtruss' on plugin test applications will give you a great
deal of insight into why they aren't activating.

View File

@ -1,4 +0,0 @@
# format is description, url (don't put ',' chars in description :)
# if no ',' found, whole line is used for both description and url
Google Home Page,http://www.google.com
Facebook Home Page,http://www.facebook.com

File diff suppressed because it is too large Load Diff

View File

@ -1,173 +0,0 @@
/**
* @file LLFBConnectTest.cpp
* @brief Facebook Connect Test App
*
* $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$
*/
#ifndef LL_FB_CONNECT_H
#define LL_FB_CONNECT_H
#include <vector>
#include <string>
#include "llpluginclassmedia.h"
#include "llgl.h"
// Forward declarations
class GLUI_Rotation;
class GLUI_Translation;
class GLUI_Listbox;
class GLUI_EditText;
class GLUI_StaticText;
class GLUI;
class GLUI_Button;
////////////////////////////////////////////////////////////////////////////////
//
struct mediaPanel
{
public:
mediaPanel();
~mediaPanel();
int mId;
std::string mStartUrl;
std::string mMimeType;
std::string mTarget;
LLPluginClassMedia *mMediaSource;
int mMediaWidth;
int mMediaHeight;
int mTextureWidth;
int mTextureHeight;
double mTextureScaleX;
double mTextureScaleY;
GLuint mMediaTextureHandle;
GLuint mPickTextureHandle;
unsigned char* mPickTexturePixels;
bool mAppTextureCoordsOpenGL;
bool mReadyToRender;
};
////////////////////////////////////////////////////////////////////////////////
//
class LLFBConnectTest : public LLPluginClassMediaOwner
{
public:
LLFBConnectTest( int app_window, int window_width, int window_height );
~LLFBConnectTest();
void reshape( int width, int height );
void display();
void idle();
void gluiCallback( int control_id );
void keyboard( int key );
void mousePassive( int x, int y );
void mouseButton( int button, int state, int x, int y );
void mouseMove( int x, int y );
void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1);
bool checkGLError(const char *name = "OpenGL");
void drawGeometry( int panel, bool selected );
void startPanelHighlight( float red, float green, float blue, float line_width );
void endPanelHighlight();
enum { DrawTypePickTexture, DrawTypeMediaTexture };
void draw( int draw_type );
void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id );
mediaPanel* addMediaPanel( std::string url );
void updateMediaPanel( mediaPanel* panel );
void remMediaPanel( mediaPanel* panel );
mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url );
void getRandomMediaSize( int& width, int& height, std::string mime_type );
void navigateToNewURI( std::string uri );
void initUrlHistory( std::string uri );
void selectPanelById( int id );
void selectPanel( mediaPanel* panel );
mediaPanel* findMediaPanel( LLPluginClassMedia* panel );
mediaPanel* findMediaPanel( const std::string &target_name );
void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );
void makeChrome();
void resetView();
void dumpPanelInfo();
void updateStatusBar();
GLfloat distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z );
// Inherited from LLPluginClassMediaOwner
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent);
private:
const int mVersionMajor;
const int mVersionMinor;
const int mVersionPatch;
const int mMaxPanels;
int mAppWindow;
int mWindowWidth;
int mWindowHeight;
int mCurMouseX;
int mCurMouseY;
unsigned char mPixelReadColor[ 3 ];
bool mFuzzyMedia;
const std::string mHomeWebUrl;
std::vector< mediaPanel* > mMediaPanels;
mediaPanel* mSelectedPanel;
std::string mimeTypeFromUrl( std::string& url );
std::string pluginNameFromMimeType( std::string& mime_type );
GLUI_Rotation* mViewRotationCtrl;
GLUI_Translation* mViewScaleCtrl;
GLUI_Translation* mViewTranslationCtrl;
float mViewportAspect;
float mViewPos[ 3 ];
float mViewRotation[ 16 ];
float mDistanceCameraToSelectedGeometry;
std::vector< std::pair< std::string, std::string > > mBookmarks;
GLUI_Listbox* mBookmarkList;
int mIdBookmarks;
int mIdUrlEdit;
GLUI_EditText* mUrlEdit;
int mSelBookmark;
int mIdControlExitApp;
GLUI* mGluiMediaBrowserControlWindow;
int mIdMediaBrowserControlBack;
GLUI_Button* mMediaBrowserControlBackButton;
int mIdMediaBrowserControlStop;
int mIdMediaBrowserControlForward;
GLUI_Button* mMediaBrowserControlForwardButton;
bool mGluiMediaBrowserControlWindowFlag;
bool mMediaBrowserControlBackButtonFlag;
bool mMediaBrowserControlForwardButtonFlag;
int mIdMediaBrowserControlHome;
int mIdMediaBrowserControlReload;
GLUI* mBottomGLUIWindow;
GLUI_StaticText* mStatusText;
};
#endif // LL_FB_CONNECT_H

View File

@ -254,138 +254,8 @@ endif (DARWIN)
# )
#endif (DARWIN)
### llmediaplugintest
set(llmediaplugintest_SOURCE_FILES
llmediaplugintest.cpp
llmediaplugintest.h
bookmarks.txt
)
add_executable(llmediaplugintest
WIN32
MACOSX_BUNDLE
${llmediaplugintest_SOURCE_FILES}
)
set_target_properties(llmediaplugintest
PROPERTIES
WIN32_EXECUTABLE
FALSE
)
target_link_libraries(llmediaplugintest
${GLUT_LIBRARY}
${GLUI_LIBRARY}
${OPENGL_LIBRARIES}
${LLPLUGIN_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLCOMMON_LIBRARIES}
${PLUGIN_API_WINDOWS_LIBRARIES}
)
if (DARWIN)
# The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app.
target_link_libraries(llmediaplugintest
${COREFOUNDATION_LIBRARY}
)
endif (DARWIN)
add_dependencies(llmediaplugintest
stage_third_party_libs
SLPlugin
media_plugin_quicktime
media_plugin_webkit
media_plugin_example
${LLPLUGIN_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLCOMMON_LIBRARIES}
)
# turn off weird GLUI pragma
add_definitions(-DGLUI_NO_LIB_PRAGMA)
if (DARWIN OR LINUX)
# glui.h contains code that triggers the "overloaded-virtual" warning in gcc.
set_source_files_properties(llmediaplugintest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual")
endif (DARWIN OR LINUX)
# Gather build products of the various dependencies into the build directory for the testbed.
if (DARWIN)
# path inside the app bundle where we'll need to copy plugins and other related files
set(PLUGINS_DESTINATION_DIR
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llmediaplugintest.app/Contents/Resources
)
# create the Contents/Resources directory
add_custom_command(
TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND}
ARGS
-E
make_directory
${PLUGINS_DESTINATION_DIR}
COMMENT "Creating Resources directory in app bundle."
)
else (DARWIN)
set(PLUGINS_DESTINATION_DIR
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
)
endif (DARWIN)
set(BUILT_SLPLUGIN $<TARGET_FILE:SLPlugin>)
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_SLPLUGIN}
)
set(BUILT_LLCOMMON $<TARGET_FILE:llcommon>)
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_LLCOMMON}
)
set(BUILT_WEBKIT_PLUGIN $<TARGET_FILE:media_plugin_webkit>)
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_WEBKIT_PLUGIN}
)
if (DARWIN OR WINDOWS)
set(BUILT_QUICKTIME_PLUGIN $<TARGET_FILE:media_plugin_quicktime>)
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_QUICKTIME_PLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_QUICKTIME_PLUGIN}
)
endif (DARWIN OR WINDOWS)
set(BUILT_EXAMPLE_PLUGIN $<TARGET_FILE:media_plugin_example>)
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_EXAMPLE_PLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_EXAMPLE_PLUGIN}
)
# copy over bookmarks file if llmediaplugintest gets built
set(BUILT_LLMEDIAPLUGINTEST $<TARGET_FILE:llmediaplugintest>)
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
)
# also copy it to the same place as SLPlugin, which is what the mac wants...
add_custom_command(TARGET llmediaplugintest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
)
if (DARWIN)
# add_custom_command(TARGET llmediaplugintest POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib ${PLUGINS_DESTINATION_DIR}
# DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
# )
endif (DARWIN)
if(WINDOWS)
#********************
# Plugin test library deploy
@ -398,11 +268,6 @@ if(WINDOWS)
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgthread-2.0-0.dll
qtcored4.dll
qtguid4.dll
qtnetworkd4.dll
qtopengld4.dll
qtwebkitd4.dll
ssleay32.dll
)
copy_if_different(
@ -413,40 +278,6 @@ if(WINDOWS)
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Debug config runtime files required for the plugin test mule (Qt image format plugins)
set(plugintest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/imageformats")
set(plugintest_debug_files
qgifd4.dll
qicod4.dll
qjpegd4.dll
qmngd4.dll
qsvgd4.dll
qtiffd4.dll
)
copy_if_different(
${plugintest_debug_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats"
out_targets
${plugintest_debug_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Debug config runtime files required for the plugin test mule (Qt codec plugins)
set(plugintest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}/codecs")
set(plugintest_debug_files
qcncodecsd4.dll
qjpcodecsd4.dll
qkrcodecsd4.dll
qtwcodecsd4.dll
)
copy_if_different(
${plugintest_debug_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs"
out_targets
${plugintest_debug_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the plugin test mule
set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(plugintest_release_files
@ -455,12 +286,6 @@ if(WINDOWS)
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgthread-2.0-0.dll
qtcore4.dll
qtgui4.dll
qtnetwork4.dll
qtopengl4.dll
qtwebkit4.dll
qtxmlpatterns4.dll
ssleay32.dll
)
copy_if_different(
@ -479,63 +304,11 @@ if(WINDOWS)
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/imageformats")
set(plugintest_release_files
qgif4.dll
qico4.dll
qjpeg4.dll
qmng4.dll
qsvg4.dll
qtiff4.dll
)
copy_if_different(
${plugintest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats"
out_targets
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
copy_if_different(
${plugintest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats"
out_targets
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt codec plugins)
set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}/codecs")
set(plugintest_release_files
qcncodecs4.dll
qjpcodecs4.dll
qkrcodecs4.dll
qtwcodecs4.dll
)
copy_if_different(
${plugintest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/Release/codecs"
out_targets
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
copy_if_different(
${plugintest_release_src_dir}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs"
out_targets
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
add_custom_target(copy_plugintest_libs ALL
DEPENDS
${plugin_test_targets}
)
add_dependencies(llmediaplugintest copy_plugintest_libs)
endif(WINDOWS)
if (DARWIN)
@ -545,20 +318,6 @@ if (DARWIN)
libaprutil-1.0.dylib
libapr-1.0.dylib
libexpat.1.5.2.dylib
libQtCore.4.7.1.dylib
libQtCore.4.dylib
libQtGui.4.7.1.dylib
libQtGui.4.dylib
libQtNetwork.4.7.1.dylib
libQtNetwork.4.dylib
libQtOpenGL.4.7.1.dylib
libQtOpenGL.4.dylib
libQtWebKit.4.7.1.dylib
libQtWebKit.4.dylib
libQtSvg.4.7.1.dylib
libQtSvg.4.dylib
libQtXml.4.7.1.dylib
libQtXml.4.dylib
)
copy_if_different(
${plugintest_release_src_dir}
@ -568,46 +327,10 @@ if (DARWIN)
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt image format plugins)
set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/imageformats")
set(plugintest_release_files
libqgif.dylib
libqico.dylib
libqjpeg.dylib
libqmng.dylib
libqsvg.dylib
libqtiff.dylib
)
copy_if_different(
${plugintest_release_src_dir}
"${PLUGINS_DESTINATION_DIR}/imageformats"
out_targets
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
# Release & ReleaseDebInfo config runtime files required for the FB connect test (Qt codec plugins)
set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_PLUGINS}/codecs")
set(plugintest_release_files
libqcncodecs.dylib
libqjpcodecs.dylib
libqkrcodecs.dylib
libqtwcodecs.dylib
)
copy_if_different(
${plugintest_release_src_dir}
"${PLUGINS_DESTINATION_DIR}/codecs"
out_targets
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
add_custom_target(copy_plugintest_libs ALL
DEPENDS
${plugin_test_targets}
)
add_dependencies(llmediaplugintest copy_plugintest_libs)
endif (DARWIN)
ll_deploy_sharedlibs_command(llmediaplugintest)

File diff suppressed because it is too large Load Diff

View File

@ -1,207 +0,0 @@
/**
* @file LLMediaPluginTest.cpp
* @brief Primary test application for LLMedia (Separate Process) Plugin system
*
* $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$
*/
#ifndef LL_MEDIA_PLUGIN_TEST_H
#define LL_MEDIA_PLUGIN_TEST_H
#include <vector>
#include <string>
#include "llpluginclassmedia.h"
#include "llgl.h"
// Forward declarations
class GLUI_Rotation;
class GLUI_Translation;
class GLUI_Listbox;
class GLUI_EditText;
class GLUI_StaticText;
class GLUI;
class GLUI_Button;
////////////////////////////////////////////////////////////////////////////////
//
struct mediaPanel
{
public:
mediaPanel();
~mediaPanel();
int mId;
std::string mStartUrl;
std::string mMimeType;
std::string mTarget;
LLPluginClassMedia *mMediaSource;
int mMediaWidth;
int mMediaHeight;
int mTextureWidth;
int mTextureHeight;
double mTextureScaleX;
double mTextureScaleY;
GLuint mMediaTextureHandle;
GLuint mPickTextureHandle;
unsigned char* mPickTexturePixels;
bool mAppTextureCoordsOpenGL;
bool mReadyToRender;
};
////////////////////////////////////////////////////////////////////////////////
//
class LLMediaPluginTest : public LLPluginClassMediaOwner
{
public:
LLMediaPluginTest( int app_window, int window_width, int window_height );
~LLMediaPluginTest();
void reshape( int width, int height );
void display();
void idle();
void gluiCallback( int control_id );
void keyboard( int key );
void mousePassive( int x, int y );
void mouseButton( int button, int state, int x, int y );
void mouseMove( int x, int y );
void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1);
bool checkGLError(const char *name = "OpenGL");
void drawGeometry( int panel, bool selected );
void startPanelHighlight( float red, float green, float blue, float line_width );
void endPanelHighlight();
enum { DrawTypePickTexture, DrawTypeMediaTexture };
void draw( int draw_type );
void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id );
mediaPanel* addMediaPanel( std::string url );
void updateMediaPanel( mediaPanel* panel );
void remMediaPanel( mediaPanel* panel );
mediaPanel* replaceMediaPanel( mediaPanel* panel, std::string url );
void getRandomMediaSize( int& width, int& height, std::string mime_type );
void navigateToNewURI( std::string uri );
void initUrlHistory( std::string uri );
void selectPanelById( int id );
void selectPanel( mediaPanel* panel );
mediaPanel* findMediaPanel( LLPluginClassMedia* panel );
mediaPanel* findMediaPanel( const std::string &target_name );
void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );
void makeChrome();
void resetView();
void dumpPanelInfo();
void updateStatusBar();
GLfloat distanceToCamera( GLfloat point_x, GLfloat point_y, GLfloat point_z );
// Inherited from LLPluginClassMediaOwner
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent);
private:
const int mVersionMajor;
const int mVersionMinor;
const int mVersionPatch;
const int mMaxPanels;
int mAppWindow;
int mWindowWidth;
int mWindowHeight;
int mCurMouseX;
int mCurMouseY;
unsigned char mPixelReadColor[ 3 ];
bool mFuzzyMedia;
const std::string mHomeWebUrl;
std::vector< mediaPanel* > mMediaPanels;
mediaPanel* mSelectedPanel;
std::string mimeTypeFromUrl( std::string& url );
std::string pluginNameFromMimeType( std::string& mime_type );
GLUI_Rotation* mViewRotationCtrl;
GLUI_Translation* mViewScaleCtrl;
GLUI_Translation* mViewTranslationCtrl;
float mViewportAspect;
float mViewPos[ 3 ];
float mViewRotation[ 16 ];
float mDistanceCameraToSelectedGeometry;
int mIdControlAddPanel;
int mIdControlRemPanel;
std::vector< std::pair< std::string, std::string > > mBookmarks;
GLUI_Listbox* mBookmarkList;
int mIdBookmarks;
int mIdUrlEdit;
GLUI_EditText* mUrlEdit;
int mIdUrlInitHistoryEdit;
GLUI_EditText* mUrlInitHistoryEdit;
int mSelBookmark;
int mIdRandomPanelCount;
int mRandomPanelCount;
int mIdRandomBookmarks;
int mRandomBookmarks;
int mIdDisableTimeout;
int mDisableTimeout;
int mIdUsePluginReadThread;
int mUsePluginReadThread;
int mIdLargePanelSpacing;
int mLargePanelSpacing;
int mIdControlCrashPlugin;
int mIdControlHangPlugin;
int mIdControlExitApp;
GLUI* mGluiMediaTimeControlWindow;
int mIdMediaTimeControlPlay;
int mIdMediaTimeControlLoop;
int mIdMediaTimeControlPause;
int mIdMediaTimeControlStop;
int mIdMediaTimeControlSeek;
int mIdMediaTimeControlVolume;
int mMediaTimeControlVolume;
int mIdMediaTimeControlSeekSeconds;
int mMediaTimeControlSeekSeconds;
int mIdMediaTimeControlRewind;
int mIdMediaTimeControlFastForward;
GLUI* mGluiMediaBrowserControlWindow;
int mIdMediaBrowserControlBack;
GLUI_Button* mMediaBrowserControlBackButton;
int mIdMediaBrowserControlStop;
int mIdMediaBrowserControlForward;
GLUI_Button* mMediaBrowserControlForwardButton;
bool mGluiMediaTimeControlWindowFlag;
bool mGluiMediaBrowserControlWindowFlag;
bool mMediaBrowserControlBackButtonFlag;
bool mMediaBrowserControlForwardButtonFlag;
int mIdMediaBrowserControlHome;
int mIdMediaBrowserControlReload;
int mIdMediaBrowserControlClearCache;
int mIdMediaBrowserControlClearCookies;
int mIdMediaBrowserControlEnableCookies;
int mMediaBrowserControlEnableCookies;
GLUI* mBottomGLUIWindow;
GLUI_StaticText* mStatusText;
};
#endif // LL_MEDIA_PLUGIN_TEST_H