merge changes for 4.0.1-release

master
Oz Linden 2016-01-15 16:55:04 -05:00
commit bc22e58743
205 changed files with 4577 additions and 10763 deletions

View File

@ -510,3 +510,5 @@ 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
759710a9acef61aaf7b69f4bc4a5a913de87ad8a 4.0.1-release

View File

@ -72,12 +72,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 use the TeamCity parameter
# setting screen for your project or build configuration to set the

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>6b9eaaf83fcf8bfd4bb6966c24df7f29</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/310043/arch/Darwin/installer/llceflib-1.5.1.310043-darwin-310043.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>578f21be02efc98bbf426529f916fce8</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/310043/arch/CYGWIN/installer/llceflib-1.5.1.310043-windows-310043.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>1.5.1.310043</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

@ -186,6 +186,7 @@ Ansariel Hiller
STORM-1984
STORM-1979
MAINT-5533
MAINT-5756
Aralara Rajal
Arare Chantilly
CHUIBUG-191
@ -767,6 +768,7 @@ Kitty Barnett
STORM-1905
VWR-24217
STORM-1804
MAINT-5416
Kolor Fall
Komiko Okamoto
Korvel Noh

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

@ -821,7 +821,8 @@ LLDAELoader::LLDAELoader(
opaque_userdata,
jointMap,
jointsFromNodes),
mGeneratedModelLimit(modelLimit)
mGeneratedModelLimit(modelLimit),
mForceIdNaming(false)
{
}
@ -944,6 +945,32 @@ bool LLDAELoader::OpenFile(const std::string& filename)
mTransform.condition();
mForceIdNaming = false;
std::vector<std::string> checkNames;
for (daeInt idx = 0; idx < count; ++idx)
{
domMesh* mesh = NULL;
db->getElement((daeElement**)&mesh, idx, NULL, COLLADA_TYPE_MESH);
if (mesh)
{
std::string name = getLodlessLabel(mesh, false);
std::vector<std::string>::iterator it;
it = std::find(checkNames.begin(), checkNames.end(), name);
if (it != checkNames.end())
{
LL_WARNS() << "document has duplicate names, using IDs instead" << LL_ENDL;
mForceIdNaming = true;
break;
}
else
{
checkNames.push_back(name);
}
}
}
U32 submodel_limit = count > 0 ? mGeneratedModelLimit/count : 0;
for (daeInt idx = 0; idx < count; ++idx)
{ //build map of domEntities to LLModel
@ -1578,9 +1605,9 @@ void LLDAELoader::processChildJoints( domNode* pParentNode )
//-----------------------------------------------------------------------------
bool LLDAELoader::isNodeAJoint( domNode* pNode )
{
if ( !pNode )
if ( !pNode || !pNode->getName() )
{
LL_INFOS()<<"Created node is NULL"<<LL_ENDL;
LL_INFOS()<<"Created node is NULL or invalid"<<LL_ENDL;
return false;
}
@ -1944,7 +1971,7 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
if (model->mLabel.empty())
{
label = getLodlessLabel(instance_geo);
label = getLodlessLabel(instance_geo, mForceIdNaming);
llassert(!label.empty());
@ -2159,12 +2186,17 @@ LLImportMaterial LLDAELoader::profileToMaterial(domProfile_COMMON* material, DAE
return mat;
}
// try to get a decent label for this element
std::string LLDAELoader::getElementLabel(daeElement *element)
{
return getElementLabel(element, mForceIdNaming);
}
// try to get a decent label for this element
std::string LLDAELoader::getElementLabel(daeElement *element, bool forceIdNaming)
{
// if we have a name attribute, use it
std::string name = element->getAttribute("name");
if (name.length())
if (name.length() && !forceIdNaming)
{
return name;
}
@ -2187,7 +2219,7 @@ std::string LLDAELoader::getElementLabel(daeElement *element)
// if parent has a name or ID, use it
std::string name = parent->getAttribute("name");
if (!name.length())
if (!name.length() || forceIdNaming)
{
name = std::string(parent->getID());
}
@ -2230,9 +2262,9 @@ size_t LLDAELoader::getSuffixPosition(std::string label)
}
// static
std::string LLDAELoader::getLodlessLabel(daeElement *element)
std::string LLDAELoader::getLodlessLabel(daeElement *element, bool forceIdNaming)
{
std::string label = getElementLabel(element);
std::string label = getElementLabel(element, forceIdNaming);
size_t ext_pos = getSuffixPosition(label);
if (ext_pos != -1)
{
@ -2303,8 +2335,13 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh)
return (status == LLModel::NO_ERRORS);
}
//static
LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
{
return loadModelFromDomMesh(mesh, mForceIdNaming);
}
//static
LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh, bool forceIdNaming)
{
LLVolumeParams volume_params;
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
@ -2312,7 +2349,7 @@ LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
createVolumeFacesFromDomMesh(ret, mesh);
if (ret->mLabel.empty())
{
ret->mLabel = getElementLabel(mesh);
ret->mLabel = getElementLabel(mesh, forceIdNaming);
}
return ret;
}
@ -2330,7 +2367,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
LLModel* ret = new LLModel(volume_params, 0.f);
std::string model_name = getLodlessLabel(mesh);
std::string model_name = getLodlessLabel(mesh, mForceIdNaming);
ret->mLabel = model_name + lod_suffix[mLod];
llassert(!ret->mLabel.empty());

View File

@ -89,19 +89,22 @@ protected:
static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh);
static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
static LLModel* loadModelFromDomMesh(domMesh* mesh);
static LLModel* loadModelFromDomMesh(domMesh* mesh, bool forceIdNaming);
LLModel* loadModelFromDomMesh(domMesh* mesh);
// Loads a mesh breaking it into one or more models as necessary
// to get around volume face limitations while retaining >8 materials
//
bool loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& models_out, U32 submodel_limit);
static std::string getElementLabel(daeElement *element);
static std::string getElementLabel(daeElement *element, bool forceIdNaming);
std::string getElementLabel(daeElement *element);
static size_t getSuffixPosition(std::string label);
static std::string getLodlessLabel(daeElement *element);
static std::string getLodlessLabel(daeElement *element, bool forceIdNaming = false);
private:
U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
bool mForceIdNaming;
};
#endif // LL_LLDAELLOADER_H

View File

@ -116,6 +116,7 @@ LLModelLoader::LLModelLoader(
, LLThread("Model Loader")
, mFilename(filename)
, mLod(lod)
, mTrySLM(false)
, mFirstTransform(TRUE)
, mNumOfFetchingTextures(0)
, mLoadCallback(load_cb)
@ -123,6 +124,9 @@ LLModelLoader::LLModelLoader(
, mTextureLoadFunc(texture_load_func)
, mStateCallback(state_cb)
, mOpaqueData(opaque_userdata)
, mRigParityWithScene(false)
, mRigValidJointUpload(false)
, mLegacyRigValid(false)
, mNoNormalize(false)
, mNoOptimize(false)
, mCacheOnlyHitIfRigged(false)

View File

@ -317,9 +317,9 @@ S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID
return mTextureList.setMaterialID(index, pMaterialID);
}
S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer)
S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams)
{
return mTextureList.setMaterialParams(index, pMaterialParams, isInitFromServer);
return mTextureList.setMaterialParams(index, pMaterialParams);
}
LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index)

View File

@ -384,7 +384,7 @@ public:
virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
virtual S32 setTEGlow(const U8 te, const F32 glow);
virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer);
virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
virtual void setTESelected(const U8 te, bool sel);

View File

@ -368,18 +368,11 @@ S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMateri
return TEM_CHANGE_NONE;
}
S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer)
S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams)
{
if (index < mEntryList.size())
{
if (!isInitFromServer && mEntryList[index]->isMatParamsInitFromServer())
{
return TEM_CHANGE_NONE;
}
else
{
return mEntryList[index]->setMaterialParams(pMaterialParams);
}
return mEntryList[index]->setMaterialParams(pMaterialParams);
}
return TEM_CHANGE_NONE;
}

View File

@ -105,7 +105,7 @@ public:
S32 setMediaFlags(const U8 index, const U8 media_flags);
S32 setGlow(const U8 index, const F32 glow);
S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID);
S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer);
S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
LLMaterialPtr getMaterialParams(const U8 index);

View File

@ -63,7 +63,6 @@ LLTextureEntry::LLTextureEntry()
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
, mInitMatParamsFromServer(false)
{
init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
@ -72,7 +71,6 @@ LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
, mInitMatParamsFromServer(false)
{
init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
@ -81,7 +79,6 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
, mInitMatParamsFromServer(false)
{
mID = rhs.mID;
mScaleS = rhs.mScaleS;
@ -565,7 +562,6 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
mMaterialUpdatePending = true;
}
mMaterial = pMaterialParams;
this->mInitMatParamsFromServer = TRUE;
return TEM_CHANGE_TEXTURE;
}

View File

@ -160,8 +160,6 @@ public:
const LLMaterialID& getMaterialID() const { return mMaterialID; };
const LLMaterialPtr getMaterialParams() const { return mMaterial; };
bool isMatParamsInitFromServer() const { return mInitMatParamsFromServer; };
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
// to NOT return NULL.
@ -219,8 +217,6 @@ protected:
bool mMaterialUpdatePending;
LLMaterialID mMaterialID;
LLMaterialPtr mMaterial;
bool mInitMatParamsFromServer; // Flag to identification when material paramas initialized from
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face

View File

@ -702,77 +702,102 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
{
BOOL res = TRUE;
mTotalUniformSize = 0;
mActiveTextureChannels = 0;
mUniform.clear();
mUniformMap.clear();
mUniformNameMap.clear();
mTexture.clear();
mValue.clear();
//initialize arrays
U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
bind();
BOOL res = TRUE;
//get the number of active uniforms
GLint activeCount;
glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount);
mTotalUniformSize = 0;
mActiveTextureChannels = 0;
mUniform.clear();
mUniformMap.clear();
mUniformNameMap.clear();
mTexture.clear();
mValue.clear();
//initialize arrays
U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
bind();
//get the number of active uniforms
GLint activeCount;
glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount);
//........................................................................................................................................
//........................................................................................
/*
EXPLANATION:
This is part of code is temporary because as the final result the mapUniform() should be rewrited.
But it's a huge a volume of work which is need to be a more carefully performed for avoid possible
This is part of code is temporary because as the final result the mapUniform() should be rewrited.
But it's a huge a volume of work which is need to be a more carefully performed for avoid possible
regression's (i.e. it should be formalized a separate ticket in JIRA).
RESON:
The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear
first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels)
The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear
first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels)
it influence to which is texture matrix will be updated during rendering.
But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want
, even if the "diffuseMap" will be appear and use first in shader code.
As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
And tickets: MAINT-4165, MAINT-4839
And tickets: MAINT-4165, MAINT-4839, MAINT-3568
*/
S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");
S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
std::set<S32> skip_index;
if(diffuseMap != -1 && bumpMap != -1)
if (-1 != diffuseMap && (-1 != bumpMap || -1 != environmentMap))
{
GLenum type;
GLsizei length;
GLint size = -1;
char name[1024];
char name[1024];
diffuseMap = bumpMap = environmentMap = -1;
//diffuse map
for (S32 i = 0; i < activeCount; i++)
{
name[0] = 0;
name[0] = '\0';
glGetActiveUniformARB(mProgramObject, i, 1024, &length, &size, &type, (GLcharARB *)name);
if(std::string(name) == "diffuseMap") {
if (-1 == diffuseMap && std::string(name) == "diffuseMap")
{
diffuseMap = i;
continue;
}
if(std::string(name) == "bumpMap") {
if (-1 == bumpMap && std::string(name) == "bumpMap")
{
bumpMap = i;
continue;
}
if (-1 == environmentMap && std::string(name) == "environmentMap")
{
environmentMap = i;
continue;
}
}
if(bumpMap < diffuseMap)
bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
if (bumpLessDiff && envLessDiff)
{
mapUniform(diffuseMap, uniforms);
mapUniform(bumpMap, uniforms);
mapUniform(environmentMap, uniforms);
skip_index.insert(diffuseMap);
skip_index.insert(bumpMap);
skip_index.insert(environmentMap);
}
else if (bumpLessDiff)
{
mapUniform(diffuseMap, uniforms);
mapUniform(bumpMap, uniforms);
@ -780,26 +805,35 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
skip_index.insert(diffuseMap);
skip_index.insert(bumpMap);
}
else if (envLessDiff)
{
mapUniform(diffuseMap, uniforms);
mapUniform(environmentMap, uniforms);
skip_index.insert(diffuseMap);
skip_index.insert(environmentMap);
}
}
//........................................................................................
for (S32 i = 0; i < activeCount; i++)
{
for (S32 i = 0; i < activeCount; i++)
{
//........................................................................................
if(skip_index.end() != skip_index.find(i)) continue;
if (skip_index.end() != skip_index.find(i)) continue;
//........................................................................................
mapUniform(i, uniforms);
}
mapUniform(i, uniforms);
}
//........................................................................................................................................
unbind();
unbind();
LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
return res;
LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
return res;
}
BOOL LLGLSLShader::link(BOOL suppress_errors)
{
BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors);

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

@ -296,7 +296,7 @@ void LLKeywords::processTokensGroup(const LLSD& tokens, const std::string& group
}
color_group = getColorGroup(group);
LL_INFOS("SyntaxLSL") << "Group: '" << group << "', using color: '" << color_group << "'" << LL_ENDL;
LL_DEBUGS("SyntaxLSL") << "Group: '" << group << "', using color: '" << color_group << "'" << LL_ENDL;
if (tokens.isMap())
{
@ -331,7 +331,14 @@ void LLKeywords::processTokensGroup(const LLSD& tokens, const std::string& group
switch (token_type)
{
case LLKeywordToken::TT_CONSTANT:
color_group = getColorGroup(group + "-" + getAttribute("type"));
if (getAttribute("type").length() > 0)
{
color_group = getColorGroup(group + "-" + getAttribute("type"));
}
else
{
color_group = getColorGroup(group);
}
tooltip = "Type: " + getAttribute("type") + ", Value: " + getAttribute("value");
break;
case LLKeywordToken::TT_EVENT:

View File

@ -1715,6 +1715,30 @@ void LLNotifications::cancelByName(const std::string& name)
}
}
void LLNotifications::cancelByOwner(const LLUUID ownerId)
{
std::vector<LLNotificationPtr> notifs_to_cancel;
for (LLNotificationSet::iterator it = mItems.begin(), end_it = mItems.end();
it != end_it;
++it)
{
LLNotificationPtr pNotif = *it;
if (pNotif && pNotif->getPayload().get("owner_id").asUUID() == ownerId)
{
notifs_to_cancel.push_back(pNotif);
}
}
for (std::vector<LLNotificationPtr>::iterator it = notifs_to_cancel.begin(), end_it = notifs_to_cancel.end();
it != end_it;
++it)
{
LLNotificationPtr pNotif = *it;
pNotif->cancel();
updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
}
}
void LLNotifications::update(const LLNotificationPtr pNotif)
{
LLNotificationSet::iterator it=mItems.find(pNotif);

View File

@ -924,6 +924,7 @@ public:
void add(const LLNotificationPtr pNotif);
void cancel(LLNotificationPtr pNotif);
void cancelByName(const std::string& name);
void cancelByOwner(const LLUUID ownerId);
void update(const LLNotificationPtr pNotif);
LLNotificationPtr find(LLUUID uuid);

View File

@ -449,7 +449,10 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
//
LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
{
mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*",
mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com)"
"|"
"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?))"
"\\/\\S*",
boost::regex::perl|boost::regex::icase);
mIcon = "Hand";

View File

@ -41,7 +41,8 @@ LLUrlRegistry::LLUrlRegistry()
mUrlEntry.reserve(20);
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
mUrlEntryNoLink = new LLUrlEntryNoLink();
registerUrl(mUrlEntryNoLink);
mUrlEntryIcon = new LLUrlEntryIcon();
registerUrl(mUrlEntryIcon);
mLLUrlEntryInvalidSLURL = new LLUrlEntryInvalidSLURL();
@ -214,7 +215,6 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
// did we find a match? if so, return its details in the match object
if (match_entry)
{
// Skip if link is an email with an empty username (starting with @). See MAINT-5371.
if (match_start > 0 && text.substr(match_start - 1, 1) == "@")
return false;
@ -223,7 +223,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
std::string url = text.substr(match_start, match_end - match_start + 1);
LLUrlEntryBase *stripped_entry = NULL;
if(LLStringUtil::containsNonprintable(url))
if((match_entry != mUrlEntryNoLink) && (match_entry != mUrlEntryHTTPLabel) && (match_entry !=mUrlEntrySLLabel)
&& LLStringUtil::containsNonprintable(url))
{
LLStringUtil::stripNonprintable(url);

View File

@ -98,6 +98,7 @@ private:
LLUrlEntryBase* mLLUrlEntryInvalidSLURL;
LLUrlEntryBase* mUrlEntryHTTPLabel;
LLUrlEntryBase* mUrlEntrySLLabel;
LLUrlEntryBase* mUrlEntryNoLink;
};
#endif

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

@ -838,17 +838,21 @@ namespace tut
"search something https://marketplace.secondlife.com/products/search on marketplace and test the https",
"https://marketplace.secondlife.com/products/search");
testRegex("match urls with port", url,
"let's specify some port http://secondlife.com:888/status",
"http://secondlife.com:888/status");
testRegex("match HTTPS urls with port", url,
"let's specify some port https://secondlife.com:888/status",
"https://secondlife.com:888/status");
testRegex("don't match HTTP urls with port", url,
"let's specify some port for HTTP http://secondlife.com:888/status",
"");
testRegex("don't match urls w/o protocol", url,
"looks like an url something www.marketplace.secondlife.com/products but no https prefix",
"");
testRegex("but with a protocol www is fine", url,
"so let's add a protocol http://www.marketplace.secondlife.com:8888/products",
"http://www.marketplace.secondlife.com:8888/products");
"so let's add a protocol https://www.marketplace.secondlife.com:8888/products",
"https://www.marketplace.secondlife.com:8888/products");
testRegex("don't match urls w/o protocol", url,
"and even no www something secondlife.com/status",

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,886 @@
/**
* @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.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granualrity/query UI
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}
@ -1373,7 +1369,6 @@ if (DARWIN)
set(viewer_RESOURCE_FILES
secondlife.icns
macview.r
gpu_table.txt
Info-SecondLife.plist
SecondLife.xib/
# CMake doesn't seem to support Xcode language variants well just yet
@ -1766,44 +1761,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
)
@ -1848,10 +1811,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)
@ -2018,9 +1981,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
)
@ -2128,7 +2090,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)
@ -2182,20 +2144,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

@ -1 +1 @@
3.8.7
4.0.2

View File

@ -19,7 +19,7 @@ else (IS_ARTWORK_PRESENT)
message(STATUS "WARNING: Artwork is not present, and will not be installed")
endif (IS_ARTWORK_PRESENT)
install(FILES featuretable_linux.txt featuretable_solaris.txt gpu_table.txt
install(FILES featuretable_linux.txt featuretable_solaris.txt
DESTINATION ${APP_SHARE_DIR}
)

View File

@ -2314,6 +2314,15 @@
<key>tooltip</key>
<string>Gets the attachment point to which the object is attached.\nReturns 0 if the object is not an attachment (or is an avatar, etc).</string>
</map>
<key>OBJECT_BODY_SHAPE_TYPE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>26</integer>
<key>tooltip</key>
<string>This is a flag used with llGetObjectDetails to get the body type of the avatar, based on shape data.\nIf no data is available, -1.0 is returned.\nThis is normally between 0 and 1.0, with 0.5 and larger considered 'male'</string>
</map>
<key>OBJECT_CHARACTER_TIME</key>
<map>
<key>type</key>
@ -2323,6 +2332,15 @@
<key>tooltip</key>
<string>Units in seconds</string>
</map>
<key>OBJECT_CLICK_ACTION</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>28</integer>
<key>tooltip</key>
<string>This is a flag used with llGetObjectDetails to get the click action.\nThe default is 0</string>
</map>
<key>OBJECT_CREATOR</key>
<map>
<key>type</key>
@ -2350,6 +2368,24 @@
<key>tooltip</key>
<string>Gets the prims's group key. If id is an avatar, a NULL_KEY is returned.</string>
</map>
<key>OBJECT_HOVER_HEIGHT</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>25</integer>
<key>tooltip</key>
<string>This is a flag used with llGetObjectDetails to get hover height of the avatar\nIf no data is available, 0.0 is returned.</string>
</map>
<key>OBJECT_LAST_OWNER_ID</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>27</integer>
<key>tooltip</key>
<string>Gets the object's last owner ID.</string>
</map>
<key>OBJECT_NAME</key>
<map>
<key>type</key>
@ -3277,6 +3313,51 @@
<key>tooltip</key>
<string>Play animation going forwards, then backwards.</string>
</map>
<key>PRIM_ALPHA_MODE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>38</integer>
<key>tooltip</key>
<string>Prim parameter for materials using integer face, integer alpha_mode, integer alpha_cutoff.\nDefines how the alpha channel of the diffuse texture should be rendered.\nValid options for alpha_mode are PRIM_ALPHA_MODE_BLEND, _NONE, _MASK, and _EMISSIVE.\nalpha_cutoff is used only for PRIM_ALPHA_MODE_MASK.</string>
</map>
<key>PRIM_ALPHA_MODE_NONE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>0</integer>
<key>tooltip</key>
<string>Prim parameter setting for PRIM_ALPHA_MODE.\nIndicates that the diffuse texture's alpha channel should be ignored.</string>
</map>
<key>PRIM_ALPHA_MODE_BLEND</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>1</integer>
<key>tooltip</key>
<string>Prim parameter setting for PRIM_ALPHA_MODE.\nIndicates that the diffuse texture's alpha channel should be rendered as alpha-blended.</string>
</map>
<key>PRIM_ALPHA_MODE_MASK</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>2</integer>
<key>tooltip</key>
<string>Prim parameter setting for PRIM_ALPHA_MODE.\nIndicates that the diffuse texture's alpha channel should be rendered as fully opaque for alpha values above alpha_cutoff and fully transparent otherwise.</string>
</map>
<key>PRIM_ALPHA_MODE_EMISSIVE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>3</integer>
<key>tooltip</key>
<string>Prim parameter setting for PRIM_ALPHA_MODE.\nIndicates that the diffuse texture's alpha channel should be rendered as an emissivity mask.</string>
</map>
<key>PRIM_BUMP_BARK</key>
<map>
<key>type</key>
@ -3882,6 +3963,15 @@
<key>tooltip</key>
<string/>
</map>
<key>PRIM_NORMAL</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>37</integer>
<key>tooltip</key>
<string>Prim parameter for materials using integer face, string texture, vector repeats, vector offsets, float rotation_in_radians</string>
</map>
<key>PRIM_OMEGA</key>
<map>
<key>type</key>
@ -4108,6 +4198,15 @@
<key>tooltip</key>
<string/>
</map>
<key>PRIM_SPECULAR</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>36</integer>
<key>tooltip</key>
<string>Prim parameter for materials using integer face, string texture, vector repeats, vector offsets, float rotation_in_radians, vector color, integer glossy, integer environment</string>
</map>
<key>PRIM_TEMP_ON_REZ</key>
<map>
<key>type</key>
@ -5020,6 +5119,15 @@
<key>tooltip</key>
<string/>
</map>
<key>REGION_FLAG_BLOCK_FLYOVER</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<string>0x8000000</string>
<key>tooltip</key>
<string/>
</map>
<key>REGION_FLAG_BLOCK_TERRAFORM</key>
<map>
<key>type</key>
@ -5979,6 +6087,177 @@
<key>tooltip</key>
<string/>
</map>
<key>XP_ERROR_EXPERIENCES_DISABLED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>2</integer>
<key>tooltip</key>
<string>The region currently has experiences disabled.</string>
</map>
<key>XP_ERROR_EXPERIENCE_DISABLED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>8</integer>
<key>tooltip</key>
<string>The experience owner has temporarily disabled the experience.</string>
</map>
<key>XP_ERROR_EXPERIENCE_SUSPENDED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>9</integer>
<key>tooltip</key>
<string>The experience has been suspended by Linden Customer Support.</string>
</map>
<key>XP_ERROR_INVALID_EXPERIENCE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>7</integer>
<key>tooltip</key>
<string>The script is associated with an experience that no longer exists.</string>
</map>
<key>XP_ERROR_INVALID_PARAMETERS</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>3</integer>
<key>tooltip</key>
<string>One of the string arguments was too big to fit in the key-value store.</string>
</map>
<key>XP_ERROR_KEY_NOT_FOUND</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>14</integer>
<key>tooltip</key>
<string>The requested key does not exist.</string>
</map>
<key>XP_ERROR_MATURITY_EXCEEDED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>16</integer>
<key>tooltip</key>
<string>The content rating of the experience exceeds that of the region.</string>
</map>
<key>XP_ERROR_NONE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>0</integer>
<key>tooltip</key>
<string>No error was detected.</string>
</map>
<key>XP_ERROR_NOT_FOUND</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>6</integer>
<key>tooltip</key>
<string>The sim was unable to verify the validity of the experience. Retrying after a short wait is advised.</string>
</map>
<key>XP_ERROR_NOT_PERMITTED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>4</integer>
<key>tooltip</key>
<string>This experience is not allowed to run by the requested agent.</string>
</map>
<key>XP_ERROR_NOT_PERMITTED_LAND</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>17</integer>
<key>tooltip</key>
<string>This experience is not allowed to run on the current region.</string>
</map>
<key>XP_ERROR_NO_EXPERIENCE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>5</integer>
<key>tooltip</key>
<string>This script is not associated with an experience.</string>
</map>
<key>XP_ERROR_QUOTA_EXCEEDED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>11</integer>
<key>tooltip</key>
<string>An attempted write data to the key-value store failed due to the data quota being met.</string>
</map>
<key>LSL_XP_ERROR_REQUEST_PERM_TIMEOUT</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>18</integer>
<key>tooltip</key>
<string>The request for experience permissions was ignored and timed out.</string>
</map>
<key>XP_ERROR_RETRY_UPDATE</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>15</integer>
<key>tooltip</key>
<string>A checked update failed due to an out of date request.</string>
</map>
<key>XP_ERROR_STORAGE_EXCEPTION</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>13</integer>
<key>tooltip</key>
<string>Unable to communicate with the key-value store.</string>
</map>
<key>XP_ERROR_STORE_DISABLED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>12</integer>
<key>tooltip</key>
<string>The key-value store is currently disabled on this region.</string>
</map>
<key>XP_ERROR_THROTTLED</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>1</integer>
<key>tooltip</key>
<string>The call failed due to too many recent calls.</string>
</map>
<key>XP_ERROR_UNKNOWN_ERROR</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>10</integer>
<key>tooltip</key>
<string>Other unknown error.</string>
</map>
<key>ZERO_ROTATION</key>
<map>
<key>type</key>
@ -6280,6 +6559,34 @@
<string>This event is triggered when an email sent to this script arrives.
The number remaining tells how many more emails are known to be still pending.</string>
</map>
<key>experience_permissions</key>
<map>
<key>arguments</key>
<map>
<key>agent_id</key>
<map>
<key>type</key>
<string>key</string>
<key>tooltip</key>
<string>ID of the agent approving permission for the Experience.</string>
</map>
</map>
</map>
<key>experience_permissions_denied</key>
<map>
<key>arguments</key>
<map>
<key>agent_id</key>
<map>
<key>type</key>
<string>key</string>
<key>tooltip</key>
<string>ID of the agent denying permission for the Experience.</string>
</map>
</map>
<key>tooltip</key>
<string>One of the XP_ERROR_... constants describing the reason why the Experience permissions were denied for the agent.</string>
</map>
<key>http_request</key>
<map>
<key>arguments</key>
@ -6965,6 +7272,29 @@
<key>tooltip</key>
<string>Adjusts the volume (0.0 - 1.0) of the currently playing attached sound.\nThis function has no effect on sounds started with llTriggerSound.</string>
</map>
<key>llAgentInExperience</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>integer</string>
<key>arguments</key>
<map>
<key>AgentID</key>
<map>
<key>type</key>
<string>key</string>
<key>tooltip</key>
<string></string>
</map>
</map>
<key>tooltip</key>
<string>
Returns TRUE if the agent is in the Experience and the Experience can run in the current location.
</string>
</map>
<key>llAllowInventoryDrop</key>
<map>
<key>energy</key>
@ -7696,6 +8026,36 @@
<key>tooltip</key>
<string>Convert link-set to AI/Physics character.\nCreates a path-finding entity, known as a "character", from the object containing the script. Required to activate use of path-finding functions.\nOptions is a list of key/value pairs.</string>
</map>
<key>llCreateKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<map>
<key>Key</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
<key>Value</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
</map>
<key>tooltip</key>
<string>
Starts an asychronous transaction to create a key-value pair. Will fail with XP_ERROR_STORAGE_EXCEPTION if the key already exists. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value passed to the function.
</string>
</map>
<key>llCreateLink</key>
<map>
<key>energy</key>
@ -7751,6 +8111,21 @@
<key>tooltip</key>
<string>Create a list from a string of comma separated values specified in Text.</string>
</map>
<key>llDataSizeKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<undef/>
<key>tooltip</key>
<string>
Starts an asychronous transaction the request the used and total amount of data allocated for the Experience. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the the amount in use and the third item will be the total available.
</string>
</map>
<key>llDeleteCharacter</key>
<map>
<key>energy</key>
@ -7764,6 +8139,29 @@
<key>tooltip</key>
<string>Convert link-set from AI/Physics character to Physics object.\nConvert the current link-set back to a standard object, removing all path-finding properties.</string>
</map>
<key>llDeleteKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<map>
<key>Key</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
</map>
<key>tooltip</key>
<string>
Starts an asychronous transaction to delete a key-value pair. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value associated with the key.
</string>
</map>
<key>llDeleteSubList</key>
<map>
<key>energy</key>
@ -8915,7 +9313,30 @@
<key>arguments</key>
<undef/>
<key>tooltip</key>
<string>Returns the object's attachment point, or 0 if not attached.\nReturns the object attachment point, or 0 if not attached.</string>
<string>Returns the object's attachment point, or 0 if not attached.</string>
</map>
<key>llGetAttachedList</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>list</string>
<key>arguments</key>
<array>
<map>
<key>ID</key>
<map>
<key>type</key>
<string>key</string>
<key>tooltip</key>
<string>Avatar to get attachments</string>
</map>
</map>
</array>
<key>tooltip</key>
<string>Returns a list of keys of all visible (not HUD) attachments on the avatar identified by the ID argument</string>
</map>
<key>llGetBoundingBox</key>
<map>
@ -9119,6 +9540,52 @@
<key>tooltip</key>
<string>Returns a string with the requested data about the region.</string>
</map>
<key>llGetExperienceDetails</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>list</string>
<key>arguments</key>
<map>
<key>ExperienceID</key>
<map>
<key>type</key>
<string>key</string>
<key>tooltip</key>
<string>May be NULL_KEY to retrieve the details for the script's Experience</string>
</map>
</map>
<key>tooltip</key>
<string>
Returns a list with the following Experience properties: [Experience Name, Owner ID, Group ID, Experience ID, State, State Message]. State is an integer corresponding to one of the constants XP_ERROR_... and State Message is the string returned by llGetExperienceErrorMessage for that integer.
</string>
</map>
<key>llGetExperienceErrorMessage</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>string</string>
<key>arguments</key>
<map>
<key>Error</key>
<map>
<key>type</key>
<string>integer</string>
<key>tooltip</key>
<string>An Experience error code to translate.</string>
</map>
</map>
<key>tooltip</key>
<string>
Returns a string describing the error code passed or the string corresponding with XP_ERROR_UNKNOWN_ERROR if the value is not a valid Experience error code.
</string>
</map>
<key>llGetForce</key>
<map>
<key>energy</key>
@ -11446,6 +11913,51 @@
<key>tooltip</key>
<string>Returns the name of the prim or avatar specified by ID. The ID must be a valid rezzed prim or avatar key in the current simulator, otherwise an empty string is returned.\nFor avatars, the returned name is the legacy name</string>
</map>
<key>llKeyCountKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<undef/>
<key>tooltip</key>
<string>
Starts an asychronous transaction the request the number of keys in the data store. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will the the number of keys in the system.
</string>
</map>
<key>llKeysKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<map>
<key>First</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string>Index of the first key to return.</string>
</map>
<key>Count</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string>The number of keys to return.</string>
</map>
</map>
<key>tooltip</key>
<string>
Starts an asychronous transaction the request a number of keys from the data store. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. The error XP_ERROR_KEY_NOT_FOUND is returned if First is greater than or equal to the number of keys in the data store. In the success case the subsequent items will be the keys requested. The number of keys returned may be less than requested if the return value is too large or if there is not enough keys remaining. The order keys are returned is not guaranteed but is stable between subsequent calls as long as no keys are added or removed. Because the keys are returned in a comma-delimited list it is not recommended to use commas in key names if this function is used.
</string>
</map>
<key>llLinkParticleSystem</key>
<map>
<key>energy</key>
@ -13577,6 +14089,29 @@
<key>tooltip</key>
<string>Applies Impulse and AngularImpulse to ObjectID.\nApplies the supplied impulse and angular impulse to the object specified.</string>
</map>
<key>llReadKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<map>
<key>Key</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
</map>
<key>tooltip</key>
<string>
Starts an asychronous transaction to retrieve the value associated with the key given. Will fail with XP_ERROR_KEY_NOT_FOUND if the key does not exist. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value associated with the key.
</string>
</map>
<key>llRefreshPrimURL</key>
<map>
<key>energy</key>
@ -13997,6 +14532,36 @@
<key>tooltip</key>
<string>Requests the display name of the agent. When the display name is available the dataserver event will be raised.\nThe avatar identified does not need to be in the same region or online at the time of the request.\nReturns a key that is used to identify the dataserver event when it is raised.</string>
</map>
<key>llRequestExperiencePermissions</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>void</string>
<key>arguments</key>
<map>
<key>AvatarID</key>
<map>
<key>type</key>
<string>key</string>
<key>tooltip</key>
<string/>
</map>
<key>unused</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string>Not used, should be &quot;&quot;</string>
</map>
</map>
<key>tooltip</key>
<string>
Ask the agent for permission to participate in an experience. This request is similar to llRequestPermissions with the following permissions: PERMISSION_TAKE_CONTROLS, PERMISSION_TRIGGER_ANIMATION, PERMISSION_ATTACH, PERMISSION_TRACK_CAMERA, PERMISSION_CONTROL_CAMERA and PERMISSION_TELEPORT. However, unlike llRequestPermissions the decision to allow or block the request is persistent and applies to all scripts using the experience grid wide. Subsequent calls to llRequestExperiencePermissions from scripts in the experience will receive the same response automatically with no user interaction. One of experience_permissions or experience_permissions_denied will be generated in response to this call. Outstanding permission requests will be lost if the script is derezzed, moved to another region or reset.
</string>
</map>
<key>llRequestInventoryData</key>
<map>
<key>energy</key>
@ -17913,6 +18478,50 @@
<key>tooltip</key>
<string>Updates settings for a pathfinding character.</string>
</map>
<key>llUpdateKeyValue</key>
<map>
<key>energy</key>
<real>10.0</real>
<key>sleep</key>
<real>0.0</real>
<key>return</key>
<string>key</string>
<key>arguments</key>
<map>
<key>Key</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
<key>Value</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
<key>Checked</key>
<map>
<key>type</key>
<string>integer</string>
<key>tooltip</key>
<string></string>
</map>
<key>OriginalValue</key>
<map>
<key>type</key>
<string>string</string>
<key>tooltip</key>
<string></string>
</map>
</map>
<key>tooltip</key>
<string>
Starts an asychronous transaction to update the value associated with the key given. The dataserver callback will be executed with the key returned from this call and a string describing the result. The result is a two element commma-delimited list. The first item is an integer specifying if the transaction succeeded (1) or not (0). In the failure case, the second item will be an integer corresponding to one of the XP_ERROR_... constants. In the success case the second item will be the value associated with the key. If Checked is 1 the existing value in the data store must match the OriginalValue passed or XP_ERROR_RETRY_UPDATE will be returned. If Checked is 0 the key will be created if necessary.
</string>
</map>
<key>llVecDist</key>
<map>
<key>energy</key>

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>
@ -3788,7 +3788,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>FirstSelectedEnabledPopups</key>
<map>
<key>Comment</key>
@ -3799,7 +3799,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>FixedWeather</key>
<map>
<key>Comment</key>
@ -3921,7 +3921,7 @@
<key>Value</key>
<string>SW</string>
</map>
<key>FloaterStatisticsRect</key>
<map>
<key>Comment</key>
@ -4448,7 +4448,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>
@ -4514,7 +4514,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>HostID</key>
<map>
<key>Comment</key>
@ -4602,7 +4602,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>IgnorePixelDepth</key>
<map>
<key>Comment</key>
@ -4657,7 +4657,7 @@
<string>F32</string>
<key>Value</key>
<real>0.5</real>
</map>
</map>
<key>InspectorShowTime</key>
<map>
<key>Comment</key>
@ -4668,7 +4668,7 @@
<string>F32</string>
<key>Value</key>
<real>3.0</real>
</map>
</map>
<key>InstallLanguage</key>
<map>
<key>Comment</key>
@ -5230,7 +5230,7 @@
<key>Value</key>
<string>0.0.0</string>
</map>
<key>LastSnapshotToProfileHeight</key>
<map>
<key>Comment</key>
@ -6309,7 +6309,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>MenuAccessKeyTime</key>
<map>
<key>Comment</key>
@ -6474,7 +6474,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>MouseSun</key>
<map>
<key>Comment</key>
@ -6639,7 +6639,7 @@
<string>String</string>
<key>Value</key>
<string />
</map>
</map>
<key>NextLoginLocation</key>
<map>
<key>Comment</key>
@ -6763,7 +6763,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
</map>
</map>
<key>NotificationFriendIMOptions</key>
<map>
<key>Comment</key>
@ -6819,7 +6819,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
</map>
</map>
<key>NotificationObjectIMOptions</key>
<map>
<key>Comment</key>
@ -6833,7 +6833,7 @@
<string>String</string>
<key>Value</key>
<string>toast</string>
</map>
</map>
<key>NotificationToastLifeTime</key>
<map>
<key>Comment</key>
@ -7392,7 +7392,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>PlaySoundFriendIM</key>
<map>
<key>Comment</key>
@ -7503,7 +7503,7 @@
<key>Value</key>
<real>0.9</real>
</map>
<key>PlainTextChatHistory</key>
<map>
<key>Comment</key>
@ -7515,7 +7515,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>PluginInstancesLow</key>
<map>
<key>Comment</key>
@ -7769,7 +7769,7 @@
<real>0.4</real>
</array>
</map>
<key>PreviewDirection2</key>
<map>
<key>Comment</key>
@ -8081,7 +8081,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>5.0</real>
<real>10.0</real>
</map>
<key>MediaRollOffMax</key>
<map>
@ -8379,7 +8379,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>
@ -8457,7 +8457,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderLocalLights</key>
<map>
<key>Comment</key>
@ -8684,7 +8684,7 @@
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
@ -8721,7 +8721,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderAnimateRes</key>
<map>
<key>Comment</key>
@ -8894,7 +8894,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderDepthOfField</key>
<map>
<key>Comment</key>
@ -9023,7 +9023,7 @@
<key>Value</key>
<real>0.1</real>
</map>
<key>RenderHighlightBrightness</key>
<map>
<key>Comment</key>
@ -9047,7 +9047,7 @@
<key>Value</key>
<real>0.6</real>
</map>
<key>RenderHighlightColor</key>
<map>
<key>Comment</key>
@ -9076,7 +9076,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderSpecularResX</key>
<map>
<key>Comment</key>
@ -9981,7 +9981,7 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderAutoMuteByteLimit</key>
<map>
<key>Comment</key>
@ -10036,7 +10036,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>RenderAutoHideSurfaceAreaLimit</key>
<map>
<key>Comment</key>
@ -10522,7 +10522,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>SelectMovableOnly</key>
<map>
<key>Comment</key>
@ -10764,7 +10764,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
<key>ShowCrosshairs</key>
<map>
<key>Comment</key>
@ -10841,7 +10841,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>ShowMiniMapButton</key>
<map>
<key>Comment</key>
@ -10908,7 +10908,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>
@ -10917,9 +10917,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>
@ -10928,9 +10928,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>
@ -10939,7 +10939,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>1</integer>
</map>
<key>ShowWorldMapButton</key>
<map>
@ -11095,7 +11095,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>
@ -11611,7 +11611,7 @@
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
<key>SnapshotQuality</key>
<map>
<key>Comment</key>
@ -12480,7 +12480,7 @@
<string>String</string>
<key>Value</key>
<string>B56AF90D-6684-48E4-B1E4-722D3DEB2CB6</string>
</map>
</map>
<key>NearByChatChannelUUID</key>
<map>
<key>Comment</key>
@ -12491,7 +12491,7 @@
<string>String</string>
<key>Value</key>
<string>E1158BD6-661C-4981-9DAD-4DCBFF062502</string>
</map>
</map>
<key>NotificationChannelUUID</key>
<map>
<key>Comment</key>
@ -12502,7 +12502,7 @@
<string>String</string>
<key>Value</key>
<string>AEED3193-8709-4693-8558-7452CCA97AE5</string>
</map>
</map>
<key>AlertChannelUUID</key>
<map>
<key>Comment</key>
@ -12513,7 +12513,7 @@
<string>String</string>
<key>Value</key>
<string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string>
</map>
</map>
<key>UIImgWhiteUUID</key>
<map>
<key>Comment</key>
@ -12535,7 +12535,7 @@
<string>S32</string>
<key>Value</key>
<integer>2</integer>
</map>
</map>
<key>UIMaxComboWidth</key>
<map>
<key>Comment</key>
@ -13448,7 +13448,7 @@
<string>String</string>
<key>Value</key>
<string>[i800,i600]</string>
</map>
</map>
<key>sourceid</key>
<map>
<key>Comment</key>
@ -14669,7 +14669,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
<key>EnablePlaceProfile</key>
<map>
<key>Comment</key>
@ -15491,7 +15491,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>PathfindingLineWidth</key>
<map>
<key>Comment</key>
@ -15532,7 +15532,7 @@
<real>1.0</real>
</array>
</map>
<key>HideUIControls</key>
<map>
<key>Comment</key>

View File

@ -1,663 +0,0 @@
//GPU_TABLE - that token on line 1 tags this as a gpu table file
//
// Categorizes graphics chips into various classes by name
//
// The table contains regular expressions to match
// against driver strings, a class number, and whether we claim
// to support them or not.
//
// Case is not significant in either the regular expressions or the
// driver strings; the recognizer code lowercases both before using
// them.
//
// If you modify this table, use the (perl) gpu_table_tester
// to compare the results of recognizing known cards (it is easy
// to mess this up by putting things in the wrong order):
//
// perl ../../scripts/gpu_table_tester -g gpu_table.txt tests/gpus_seen.txt | diff - tests/gpus_results.txt
//
// Format:
// Fields are separated by one or more tab (not space) characters
// <recognizer name> <regular expression> <class> <supported> <stats based> <expected OpenGL version>
//
// Class Numbers:
// 0 - Defaults to low graphics settings. No shaders on by default
// 1 - Defaults to low-mid graphics settings. Basic shaders on by default
// 2 - Defaults to mid graphics settings. Atmospherics on by default
// 3 - Defaults to mid-high graphics settings. Advanced Lighting Model on by default
// 4 - Defaults to high graphics settings. Ambient Occlusion on by default
// 5 - Defaults to high-ultra graphics settings. Shadows set to "Sun/Moon+Projectors."
//
// Supported Number:
// 0 - We claim to not support this card.
// 1 - We claim to support this card.
//
3Dfx .*3Dfx.* 0 0 0 0
3Dlabs .*3Dlabs.* 0 0 0 0
Hijacker .*Mohr.*Hijacker.* 0 0 0 0
ATI 3D-Analyze .*ATI.*3D-Analyze.* 0 0 0 0
ATI ARES .*ATI.*ARES.* 0 0 0 0
ATI All-in-Wonder 7500 .*ATI.*All-in-Wonder 75.* 0 1 0 0
ATI All-in-Wonder 8500 .*ATI.*All-in-Wonder 85.* 0 1 0 0
ATI All-in-Wonder 9200 .*ATI.*All-in-Wonder 92.* 0 1 0 0
ATI All-in-Wonder 9xxx .*ATI.*All-in-Wonder 9.* 1 1 0 2.1
ATI All-in-Wonder HD .*ATI.*All-in-Wonder HD.* 1 1 1 3.3
ATI All-in-Wonder X600 .*ATI.*All-in-Wonder X6.* 1 1 0 0
ATI All-in-Wonder X800 .*ATI.*All-in-Wonder X8.* 1 1 1 2.1
ATI All-in-Wonder X1800 .*ATI.*All-in-Wonder X18.* 3 1 0 0
ATI All-in-Wonder X1900 .*ATI.*All-in-Wonder X19.* 3 1 0 0
ATI All-in-Wonder PCI-E .*ATI.*All-in-Wonder.*PCI-E.* 1 1 0 0
ATI All-in-Wonder Radeon .*ATI.*All-in-Wonder Radeon.* 0 1 0 0
ATI Radeon X1300 .*ATI.*(Radeon|Diamond|ASUS) *X13.* ?.* 2 1 1 2.1
ATI Radeon X1400 .*ATI.*(Radeon|Diamond|ASUS) *X14.* ?.* 2 1 1 2.1
ATI Radeon X1500 .*ATI.*(Radeon|Diamond|ASUS) *X15.* ?.* 2 1 1 2.1
ATI Radeon X1600 .*ATI.*(Radeon|Diamond|ASUS) *X16.* ?.* 2 1 1 2.1
ATI Radeon X1700 .*ATI.*(Radeon|Diamond|ASUS) *X17.* ?.* 2 1 1 2.1
ATI Radeon X1800 .*ATI.*(Radeon|Diamond|ASUS) *X18.* ?.* 3 1 1 2.1
ATI Radeon X1900 .*ATI.*(Radeon|Diamond|ASUS) *X19.* ?.* 2 1 1 2.1
ATI Radeon X2800 .*ATI.*(Radeon|Diamond|ASUS) *X28.* ?.* 2 1 1 2.1
ATI Display Adapter .*ATI.*display adapter.* 1 1 1 4.1
ATI FireGL 5200 .*ATI.*FireGL V52.* 1 1 1 2.1
ATI FireGL 5xxx .*ATI.*FireGL V5.* 2 1 1 3.3
ATI FireGL .*ATI.*Fire.*GL.* 4 1 1 4.2
ATI FirePro M3900 .*ATI.*FirePro.*M39.* 2 1 0 4.1
ATI FirePro M5800 .*ATI.*FirePro.*M58.* 3 1 0 0
ATI FirePro M7740 .*ATI.*FirePro.*M77.* 3 1 0 0
ATI FirePro M7820 .*ATI.*FirePro.*M78.* 5 1 1 4.2
ATI FireMV .*ATI.*FireMV.* 0 1 1 3.2
ATI Generic .*ATI.*Generic.* 0 0 0 0
ATI Hercules 9800 .*ATI.*Hercules.* 9800.* 1 1 0 0
ATI IGP 340M .*ATI.*IGP.* 34[0-9]M.* 0 0 0 1.3
ATI M52 .*ATI.*M52.* 1 1 0 0
ATI M54 .*ATI.*M54.* 1 1 0 0
ATI M56 .*ATI.*M56.* 1 1 0 0
ATI M71 .*ATI.*M71.* 1 1 0 0
ATI M72 .*ATI.*M72.* 1 1 0 0
ATI M76 .*ATI.*M76.* 3 1 0 0
ATI Mobility Radeon 4100 .*ATI.*Mobility.* 41.. 1 1 1 3.3
ATI Mobility Radeon 5000 .*ATI.*Mobility.* 50.. 1 1 1 4.2
ATI Mobility Radeon 7xxx .*ATI.*Mobility.*Radeon 7.* 0 1 1 1.3
ATI Mobility Radeon 8xxx .*ATI.*Mobility.*Radeon 8.* 0 1 0 0
ATI Mobility Radeon 9800 .*ATI.*Mobility.* 98.* 1 1 0 0
ATI Mobility Radeon 9700 .*ATI.*Mobility.* 97.* 0 1 1 2.1
ATI Mobility Radeon 9600 .*ATI.*Mobility.* 96.* 1 1 1 2.1
ATI Mobility Radeon HD 530v .*ATI.*Mobility.*HD 530v.* 1 1 1 3.3
ATI Mobility Radeon HD 540v .*ATI.*Mobility.*HD 540v.* 1 1 1 3.3
ATI Mobility Radeon HD 545v .*ATI.*Mobility.*HD 545v.* 2 1 1 4
ATI Mobility Radeon HD 550v .*ATI.*Mobility.*HD 550v.* 3 1 1 4
ATI Mobility Radeon HD 560v .*ATI.*Mobility.*HD 560v.* 3 1 1 3.2
ATI Mobility Radeon HD 565v .*ATI.*Mobility.*HD 565v.* 3 1 1 3.3
ATI Mobility Radeon HD 2300 .*ATI.*Mobility.*HD 23.* 0 1 1 2.1
ATI Mobility Radeon HD 2400 .*ATI.*Mobility.*HD 24.* 1 1 1 3.3
ATI Mobility Radeon HD 2600 .*ATI.*Mobility.*HD 26.* 1 1 1 3.3
ATI Mobility Radeon HD 2700 .*ATI.*Mobility.*HD 27.* 3 1 0 0
ATI Mobility Radeon HD 3100 .*ATI.*Mobility.*HD 31.* 0 1 0 0
ATI Mobility Radeon HD 3200 .*ATI.*Mobility.*HD 32.* 0 1 0 0
ATI Mobility Radeon HD 3400 .*ATI.*Mobility.*HD 34.* 1 1 1 4
ATI Mobility Radeon HD 3600 .*ATI.*Mobility.*HD 36.* 1 1 1 4
ATI Mobility Radeon HD 3800 .*ATI.*Mobility.*HD 38.* 3 1 1 3.3
ATI Mobility Radeon HD 4200 .*ATI.*Mobility.*HD 42.* 1 1 1 4
ATI Mobility Radeon HD 4300 .*ATI.*Mobility.*(HD |HD)43.* 1 1 1 4
ATI Mobility Radeon HD 4500 .*ATI.*Mobility.*HD 45.* 1 1 1 4
ATI Mobility Radeon HD 4600 .*ATI.*Mobility.*HD 46.* 2 1 1 3.3
ATI Mobility Radeon HD 4800 .*ATI.*Mobility.*HD 48.* 3 1 1 3.3
ATI Mobility Radeon HD 5000 Series .*ATI.*Mobility.*HD 50.* 3 1 1 3.2
ATI Mobility Radeon HD 5100 .*ATI.*Mobility.*HD 51.* 3 1 1 3.2
ATI Mobility Radeon HD 5300 .*ATI.*Mobility.*HD 53.* 3 1 0 0
ATI Mobility Radeon HD 5400 .*ATI.*Mobility.*HD 54.* 2 1 1 4.2
ATI Mobility Radeon HD 5500 .*ATI.*Mobility.*HD 55.* 3 1 0 4.2
ATI Mobility Radeon HD 5600 .*ATI.*Mobility.*HD 56.* 3 1 1 4.2
ATI Mobility Radeon HD 5700 .*ATI.*Mobility.*HD 57.* 3 1 1 4.1
ATI Mobility Radeon X1000 .*ATI.*Mobility.*Radeon ?X1..* 2 1 0 2.1
ATI Mobility Radeon X1200 .*ATI.*Mobility.*Radeon ?X12.* 2 1 0 2.1
ATI Mobility Radeon X2000 .*ATI.*Mobility.*Radeon ?X20.* 2 1 0 2.1
ATI Mobility Radeon X2300 .*ATI.*Mobility.*Radeon ?X23.* 2 1 0 2.1
ATI Mobility Radeon X2500 .*ATI.*Mobility.*Radeon ?X25.* 2 1 0 2.1
ATI Mobility Radeon XX000 .*ATI.*Mobility.*Radeon ?Xx.* 2 1 0 2.1
ATI Radeon HD 5xx .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)5x. 1 1 1 4
ATI Radeon HD 6200D/G/M .*ATI.*AMD Radeon.* (HD|HD )62..[DGM].* 3 1 0 4.2
ATI Radeon HD 6300D/G/M .*ATI.*AMD Radeon.* (HD|HD )63..[DGM].* 3 1 1 4.2
ATI Radeon HD 6400D/G/M .*ATI.*AMD Radeon.* (HD|HD )64..[DGM].* 3 1 0 4.2
ATI Radeon HD 6500D/G/M .*ATI.*AMD Radeon.* (HD|HD )65..[DGM].* 4 1 1 4.2
ATI Radeon HD 6600D/G/M .*ATI.*AMD Radeon.* (HD|HD )66..[DGM].* 4 1 0 4.2
ATI Radeon HD 6700D/G/M .*ATI.*AMD Radeon.* (HD|HD )67..[DGM].* 4 1 0 4.2
ATI Radeon HD 6800D/G/M .*ATI.*AMD Radeon.* (HD|HD )68..[DGM].* 4 1 0 4.2
ATI Radeon HD 6900D/G/M .*ATI.*AMD Radeon.* (HD|HD )69..[DGM].* 4 1 0 4.2
ATI Radeon HD 7200D/G/M .*ATI.*AMD Radeon.* (HD|HD )72..[DGM].* 3 1 0 4.2
ATI Radeon HD 7300D/G/M .*ATI.*AMD Radeon.* (HD|HD )73..[DGM].* 3 1 0 4.2
ATI Radeon HD 7400D/G/M .*ATI.*AMD Radeon.* (HD|HD )74..[DGM].* 3 1 0 4.2
ATI Radeon HD 7500D/G/M .*ATI.*AMD Radeon.* (HD|HD )75..[DGM].* 4 1 0 4.2
ATI Radeon HD 7600D/G/M .*ATI.*AMD Radeon.* (HD|HD )76..[DGM].* 4 1 0 4.2
ATI Radeon HD 7700D/G/M .*ATI.*AMD Radeon.* (HD|HD )77..[DGM].* 4 1 0 4.2
ATI Radeon HD 7800D/G/M .*ATI.*AMD Radeon.* (HD|HD )78..[DGM].* 4 1 0 4.2
ATI Radeon HD 7900D/G/M .*ATI.*AMD Radeon.* (HD|HD )79..[DGM].* 4 1 0 4.2
ATI Radeon HD 8200D/G/M .*ATI.*AMD Radeon.* (HD|HD )82..[DGM].* 3 1 0 4.2
ATI Radeon HD 8300D/G/M .*ATI.*AMD Radeon.* (HD|HD )83..[DGM].* 3 1 0 4.2
ATI Radeon HD 8400D/G/M .*ATI.*AMD Radeon.* (HD|HD )84..[DGM].* 4 1 0 4.2
ATI Radeon HD 8500D/G/M .*ATI.*AMD Radeon.* (HD|HD )85..[DGM].* 4 1 0 4.2
ATI Radeon HD 8600D/G/M .*ATI.*AMD Radeon.* (HD|HD )86..[DGM].* 4 1 0 4.2
ATI Radeon HD 8700D/G/M .*ATI.*AMD Radeon.* (HD|HD )87..[DGM].* 4 1 0 4.2
ATI Radeon HD 8800D/G/M .*ATI.*AMD Radeon.* (HD|HD )88..[DGM].* 4 1 0 4.2
ATI Radeon HD 8900D/G/M .*ATI.*AMD Radeon.* (HD|HD )89..[DGM].* 4 1 0 4.2
ATI Radeon HD 2300 .*ATI.*Radeon.* (HD|HD )23.. 0 1 1 3.3
ATI Radeon HD 2400 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)24.. 1 1 1 4
ATI Radeon HD 2600 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)26.. 2 1 1 4
ATI Radeon HD 2900 .*ATI.*Radeon.* (HD|HD )29.. 3 1 1 3.3
ATI Radeon HD 3000 .*ATI.*Radeon.* (HD|HD )30.. 0 1 0 0
ATI Radeon HD 3100 .*ATI.*Radeon.* (HD|HD )31.. 1 1 0 0
ATI Radeon HD 3200 .*ATI.*Radeon.* (HD|HD )32.. 1 1 1 4
ATI Radeon HD 3300 .*ATI.*Radeon.* (HD|HD )33.. 1 1 1 3.3
ATI Radeon HD 3400 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |AH||AX|EAH)34.. 1 1 1 4
ATI Radeon HD 3500 .*ATI.*Radeon.* (HD|HD )35.. 2 1 0 0
ATI Radeon HD 3600 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |AH||AX|EAH)36.. 3 1 1 4
ATI Radeon HD 3700 .*ATI.*Radeon.* (HD|HD )37.. 3 1 0 3.3
ATI HD3700 .*ATI.* HD37.. 3 1 0 3.3
ATI Radeon HD 3800 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH|AX|)38.. 3 1 1 4
ATI Radeon HD 4100 .*ATI.*Radeon.* (HD|HD )41.. 1 1 0 0
ATI Radeon HD 4200 .*ATI.*Radeon.* (HD|HD )42.. 1 1 1 4
ATI Radeon HD 4300 .*ATI.*(Radeon|ASUS).* (AH|AX|HD4|HD 4|EAH4|4)3.. 2 1 1 4
ATI Radeon HD 4400 .*ATI.*Radeon.* (HD|HD )44.. 2 1 0 0
ATI Radeon HD 4500 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)45.. 2 1 1 3.3
ATI RADEON E4690 .*ATI.*RADEON.* E46.. 3 1 1 4
ATI Radeon HD 4600 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)46.. 3 1 1 4
ATI Radeon HD 4700 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)47.. 3 1 1 3.3
ATI Radeon HD 4800 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)48.. 3 1 1 4
ATI Radeon HD 5000 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)50.. 3 1 1 4.2
ATI Radeon HD 5400 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)54.. 3 1 1 4.2
ATI Radeon HD 5500 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)55.. 3 1 1 4.2
ATI Radeon HD 5600 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)56.. 3 1 1 4.2
ATI Radeon HD 5700 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)57.. 3 1 1 4.2
ATI Radeon HD 5800 .*ATI.*(Radeon|ASUS).* (AH|AX|HD|HD |EAH)58.. 4 1 1 4.2
ATI Radeon HD 5900 .*ATI.*Radeon.* (HD|HD )59.. 4 1 1 4.2
ATI Radeon HD 6200 .*ATI.*Radeon.* (HD|HD )62.. 0 1 1 4.2
ATI Radeon HD 6300 .*ATI.*Radeon.* (HD|HD )63.. 1 1 1 4.2
ATI Radeon HD 6400 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)64.. 3 1 1 4.2
ATI Radeon HD 6500 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)65.. 3 1 1 4.2
ATI Radeon HD 6600 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)66.. 3 1 1 4.2
ATI Radeon HD 6700 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)67.. 3 1 1 4.2
ATI Radeon HD 6800 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)68.. 4 1 1 4.2
ATI Radeon HD 6900 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)69.. 5 1 1 4.2
ATI Radeon HD 6x00 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)6x.. 5 1 1 4.2
ATI Radeon HD 7100 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)71.* 2 1 0 0
ATI Radeon HD 7200 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)72.* 2 1 0 4.2
ATI Radeon HD 7300 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)73.* 2 1 0 4.2
ATI Radeon HD 7400 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)74.* 2 1 0 4.2
ATI Radeon HD 7500 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)75.* 3 1 1 4.2
ATI Radeon HD 7600 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)76.* 3 1 0 4.2
ATI Radeon HD 7700 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)77.* 4 1 1 4.2
ATI Radeon HD 7800 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)78.* 5 1 1 4.2
ATI Radeon HD 7900 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)79.* 5 1 1 4.2
ATI Radeon HD 7000 Series .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)7000 Series.* 3 1 1 4.2
ATI Radeon HD 8200 .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)82.* 2 1 0 4.2
ATI Radeon HD 8300 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)83.* 2 1 0 4.2
ATI Radeon HD 8400 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)84.* 2 1 0 4.2
ATI Radeon HD 8500 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)85.* 3 1 1 4.2
ATI Radeon HD 8600 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)86.* 3 1 0 4.2
ATI Radeon HD 8700 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)87.* 4 1 1 4.2
ATI Radeon HD 8800 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)88.* 5 1 1 4.2
ATI Radeon HD 8900 (OEM) .*ATI.*(Radeon|ASUS).* (HD|HD |EAH)89.* 5 1 1 4.2
ATI Radeon OpenGL .*ATI.*Radeon OpenGL.* 0 0 0 0
ATI Radeon 2100 .*ATI.*Radeon 21.. 0 1 1 2.1
ATI Radeon 3000 .*ATI.*Radeon 30.. 1 1 1 4
ATI Radeon 3100 .*ATI.*Radeon 31.. 0 1 1 3.3
ATI Radeon 5xxx .*ATI.*Radeon 5... 3 1 0 0
ATI Radeon 6xxx .*ATI.*Radeon 6... 0 1 0 0
ATI Radeon 7xxx .*ATI.*Radeon 7... 0 1 1 2
ATI Radeon 8xxx .*ATI.*Radeon 8... 0 1 0 0
ATI Radeon 9000 .*ATI.*Radeon 90.. 0 1 1 1.3
ATI Radeon 9100 .*ATI.*Radeon 91.. 0 1 0 0
ATI Radeon 9200 .*ATI.*Radeon 92.. 0 1 1 1.3
ATI Radeon 9500 .*ATI.*Radeon 95.. 0 1 1 2.1
ATI Radeon 9600 .*ATI.*Radeon 96.. 0 1 1 2.1
ATI Radeon 9700 .*ATI.*Radeon 97.. 1 1 0 0
ATI Radeon 9800 .*ATI.*Radeon 98.. 1 1 1 2.1
ATI Radeon R7 .*ATI.*(Radeon|ASUS).* R7.* 4 1 0 4.2
ATI Radeon R9 .*ATI.*(Radeon|ASUS).* R9.* 5 1 0 4.2
ATI Radeon RV250 .*ATI.*RV250.* 0 1 0 0
ATI Radeon RV600 .*ATI.*RV6.* 1 1 0 0
ATI Radeon RX700 .*ATI.*RX70.* 1 1 0 0
ATI Radeon RX800 .*ATI.*Radeon RX80.* 2 1 0 0
ATI RS880M .*ATI.*RS880M 1 1 0 0
ATI Radeon RX9550 .*ATI.*RX9550.* 1 1 0 0
ATI Radeon VE .*ATI.*Radeon.*VE.* 0 0 0 0
ATI Radeon X300 .*ATI.*Radeon X3.* 1 1 1 2.1
ATI RADEON X300SE .*ATI.*RADEON[ ]*X300SE* 1 1 1 2.1
ATI Radeon X400 .*ATI.*Radeon ?X4.* 0 1 0 0
ATI Radeon X500 .*ATI.*Radeon ?X5.* 1 1 1 2.1
ATI Radeon X600 .*ATI.*(Radeon |ASUS Extreme A)X6.* 1 1 1 2.1
ATI Radeon X700 .*ATI.*Radeon ?X7.* 2 1 1 2.1
ATI Radeon X800 .*ATI.*Radeon ?X8.* 1 1 1 2.1
ATI Radeon X900 .*ATI.*Radeon ?X9.* 2 1 0 0
ATI Radeon X1000 .*ATI.*Radeon ?X10.* 2 1 0 2.1
ATI Radeon X1100 .*ATI.*Radeon ?X11.* 2 1 0 2.1
ATI Radeon X1200 .*ATI.*Radeon ?X12.* 2 1 0 2.1
ATI Radeon X1xxx .*ATI.*Radeon ?X1xx.* 2 1 0 2.1
ATI Radeon X12xx .*ATI.*Radeon ?X12x.* 2 1 0 2.1
ATI Radeon X2xxx .*ATI.*Radeon ?X2x.* 2 1 0 2.1
ATI Radeon X2300 .*ATI.*Radeon ?X23.* 2 1 0 2.1
ATI Radeon Xpress .*ATI.*Radeon Xpress.* 0 1 1 2.1
ATI Radeon .*ATI.*Radeon$ 3 1 0 0
ATI Rage 128 .*ATI.*Rage 128.* 0 1 0 0
ATI R300 (9700) .*R300.* 0 1 1 2.1
ATI R350 (9800) .*R350.* 1 1 0 0
ATI R580 (X1900) .*R580.* 3 1 0 0
ATI RC410 (Xpress 200) .*RC410.* 0 0 0 0
ATI RS48x (Xpress 200x) .*RS48.* 0 0 0 0
ATI RS600 (Xpress 3200) .*RS600.* 0 0 0 0
ATI RV350 (9600) .*RV350.* 0 1 0 0
ATI RV370 (X300) .*RV370.* 0 1 0 0
ATI RV410 (X700) .*RV410.* 1 1 0 0
ATI RV515 .*RV515.* 1 1 0 0
ATI RV570 (X1900 GT/PRO) .*RV570.* 3 1 0 0
ATI RV380 .*RV380.* 0 1 0 0
ATI RV530 .*RV530.* 1 1 0 0
ATI RX480 (Xpress 200P) .*RX480.* 0 1 0 0
ATI RX700 .*RX700.* 1 1 0 0
AMD ANTILLES (HD 6990) .*(AMD|ATI).*Antilles.* 3 1 0 0
ATI ROBSON .*(AMD|ATI).*ROBSON.* 3 1 0 4
AMD ARUBA (HD 6800) .*(AMD|ATI).*ARUBA.* 3 1 1 2.1
AMD BARTS (HD 6800) .*(AMD|ATI).*Barts.* 3 1 1 2.1
AMD BA (HD 6800) .*(AMD|ATI).*BA.* 3 1 1 2.1
AMD WRESTLER .*(AMD|ATI).*WRESTLER.* 3 1 1 4
AMD SUMO .*(AMD|ATI).*SUMO.* 3 1 1 4.1
AMD CAICOS (HD 6400) .*(AMD|ATI).*Caicos.* 3 1 0 0
AMD CAYMAN (HD 6900) .*(AMD|ATI).*(Cayman|CAYMAM).* 3 1 0 0
AMD CEDAR (HD 5450) .*(AMD|ATI).*Cedar.* 2 1 0 2.1
AMD CYPRESS (HD 5800) .*(AMD|ATI).*Cypress.* 3 1 0 0
AMD HEMLOCK (HD 5970) .*(AMD|ATI).*Hemlock.* 3 1 0 0
AMD JUNIPER (HD 5700) .*(AMD|ATI).*Juniper.* 3 1 0 0
AMD PARK .*(AMD|ATI).*Park.* 3 1 0 0
AMD REDWOOD (HD 5500/5600) .*(AMD|ATI).*Redwood.* 3 1 0 1.4
AMD TURKS (HD 6500/6600) .*(AMD|ATI).*Turks.* 3 1 0 2.1
AMD PITCAIRN (HD 7870) .*(AMD|ATI).*Pitcairn.* 3 1 0 2.1
AMD TAHITI (HD 7000) .*(AMD|ATI).*Tahiti.* 3 1 0 2.1
AMD RS780 (HD 3200) .*RS780.* 0 1 1 2.1
AMD RS880 (HD 4200) .*RS880.* 0 1 1 3.2
AMD RV610 (HD 2400) .*RV610.* 1 1 0 0
AMD RV620 (HD 3400) .*RV620.* 1 1 0 0
AMD RV630 (HD 2600) .*RV630.* 2 1 0 0
AMD RV635 (HD 3600) .*RV635.* 3 1 0 1.4
AMD RV670 (HD 3800) .*RV670.* 3 1 0 0
AMD R680 (HD 3870 X2) .*R680.* 3 1 0 0
AMD R700 (HD 4800 X2) .*R700.* 3 1 0 0
AMD RV710 (HD 4300) .*RV710.* 0 1 1 1.4
AMD RV730 (HD 4600) .*RV730.* 3 1 0 1.4
AMD RV740 (HD 4700) .*RV740.* 3 1 0 0
AMD RV770 (HD 4800) .*RV770.* 3 1 0 0
AMD RV790 (HD 4800) .*RV790.* 3 1 0 0
ATI 760G/Radeon 3000 .*ATI.*AMD 760G.* 1 1 1 3.3
ATI 780L/Radeon 3000 .*ATI.*AMD 780L.* 1 1 0 0
ATI Radeon DDR .*ATI.*Radeon ?DDR.* 0 1 0 0
ATI FirePro 2000 .*ATI.*FirePro [V]*2.* 2 1 1 4.2
ATI FirePro 3000 .*ATI.*FirePro [V]*3.* 2 1 0 0
ATI FirePro 4000 .*ATI.*FirePro [V]*4.* 2 1 0 4.1
ATI FirePro 5000 .*ATI.*FirePro [V]*5.* 3 1 0 0
ATI FirePro 7000 .*ATI.*FirePro [V]*7.* 3 1 0 0
ATI FirePro M .*ATI.*FirePro M.* 3 1 1 4.2
Intel X3100 .*Intel.*X3100.* 1 1 1 2.1
Intel GMA 3600 .*Intel.* 3600.* 0 1 1 3
Intel Royal BNA .*Intel.*Royal[ ]*BNA.* 0 0 0 0
Intel 830M .*Intel.*830M 0 0 0 0
Intel 845G .*Intel.*845G 0 0 1 1.4
Intel 855GM .*Intel.*855GM 0 0 1 1.4
Intel 865G .*Intel.*865G 0 0 1 1.4
Intel 900 .*Intel.*900.*900 0 0 0 0
Intel 915GM .*Intel.*915GM 0 0 1 1.4
Intel 915G .*Intel.*915G 0 0 1 1.4
Intel 945GM .*Intel.*945GM.* 0 1 1 1.4
Intel 945G .*Intel.*945G.* 0 1 1 1.4
Intel 950 .*Intel.*950.* 0 1 1 1.4
Intel 965 .*Intel.*965.* 0 1 1 2.1
Intel G33 .*Intel.*G33.* 1 0 1 1.4
Intel G41 .*Intel.*G41.* 1 1 1 2.1
Intel G45 .*Intel.*G45.* 1 1 1 2.1
Intel Bear Lake .*Intel.*Bear Lake.* 1 0 1 1.4
Intel Broadwater .*Intel.*Broadwater.* 0 0 1 1.4
Intel Brookdale .*Intel.*Brookdale.* 0 0 1 1.3
Intel Cantiga .*Intel.*Cantiga.* 0 0 1 2
Intel Eaglelake .*Intel.*Eaglelake.* 1 1 1 2
Intel Graphics Media HD .*Intel.*Graphics Media.*HD.* 1 1 1 2.1
Intel HD Graphics 2500 .*Intel.*HD Graphics 25.* 2 1 0 4.2
Intel HD Graphics 2000 .*Intel.*HD Graphics 2.* 2 1 0 3.1
Intel HD Graphics 3000 .*Intel.*HD Graphics 3.* 3 1 1 3.1
Intel HD Graphics 4200 .*Intel.*HD Graphics 42.* 3 1 0 4.2
Intel HD Graphics 4400 .*Intel.*HD Graphics 44.* 3 1 0 4.2
Intel HD Graphics 4600 .*Intel.*HD Graphics 46.* 3 1 0 4.2
Intel HD Graphics 4000 .*Intel.*HD Graphics 4.* 3 1 1 4.2
Intel Intel Iris Pro Graphics 5200 .*Intel.*Iris Pro Graphics 52.* 4 1 0 4
Intel Intel Iris Graphics 5100 .*Intel.*Iris Graphics 51.* 4 1 0 4
Intel Intel Iris OpenGL Engine .*Intel.*Iris OpenGL.* 4 1 0 4
Intel Intel Iris Pro OpenGL Engine .*Intel.*Iris Pro OpenGL.* 5 1 0 4
Intel HD Graphics 5000 .*Intel.*HD Graphics 5.* 4 1 0 4
Intel HD Graphics .*Intel.*HD Graphics.* 2 1 1 4
Intel Mobile 4 Series .*Intel.*Mobile.* 4 Series.* 0 1 1 2.1
Intel Mobile 45 Express .*Intel.*Mobile.* 45 Express Chipset.* 0 1 0 2.1
Intel 4 Series Internal .*Intel.* 4 Series Internal.* 1 1 1 2.1
Intel Media Graphics HD .*Intel.*Media Graphics HD.* 0 1 0 0
Intel Montara .*Intel.*Montara.* 0 0 1 1.3
Intel Pineview .*Intel.*Pineview.* 0 1 1 1.4
Intel Springdale .*Intel.*Springdale.* 0 0 1 1.3
Intel Grantsdale .*Intel.*Grantsdale.* 1 1 0 0
Intel Q45/Q43 .*Intel.*Q4.* 1 1 1 2.1
Intel B45/B43 .*Intel.*B4.* 1 1 1 2.1
Intel 3D-Analyze .*Intel.*3D-Analyze.* 2 1 0 0
Matrox .*Matrox.* 0 0 0 0
Mesa .*Mesa.* 1 0 1 3
Gallium .*Gallium.* 1 1 1 2.1
NVIDIA GeForce Pre-Release .*NVIDIA .*GeForce[ ]Pre-Release.* 2 1 1 3.3
NVIDIA D1xP1 .*NVIDIA .*D1[0-4]P1.* 0 0 0 0
NVIDIA Mystery PCI Card .*NVIDIA .Corporation [/]PCI]/]SSE2.* 0 0 0 0
NVIDIA Quadro FX 770M .*Quadro.*FX 77[0-9]M.* 2 1 0 3.3
NVIDIA Quadro FX 1500M .*Quadro.*FX 150[0-9]M.* 1 1 0 2.1
NVIDIA Quadro FX 1600M .*Quadro.*FX 160[0-9]M.* 2 1 0 3.3
NVIDIA Quadro FX 2500M .*Quadro.*FX 250[0-9]M.* 2 1 0 2.1
NVIDIA Quadro FX 2700M .*Quadro.*FX 270[0-9]M.* 3 1 0 3.3
NVIDIA Quadro FX 2800M .*Quadro.*FX 280[0-9]M.* 3 1 0 3.3
NVIDIA Quadro FX 3500 .*Quadro.*FX 3500.* 2 1 0 2.1
NVIDIA Quadro FX 3600 .*Quadro.*FX 3600.* 3 1 0 3.3
NVIDIA Quadro FX 3700 .*Quadro.*FX 3700.* 3 1 0 3.3
NVIDIA Quadro FX 3800 .*Quadro.*FX 3800.* 3 1 0 3.3
NVIDIA Quadro FX 4500 .*Quadro.*FX 45.* 3 1 0 2.1
NVIDIA Quadro FX 880M .*Quadro.*FX 88[0-9]M.* 3 1 0 3.3
NVIDIA Quadro FX 4800 .*NVIDIA .*Quadro FX 4800.* 3 1 0 3.1
NVIDIA Quadro FX .*NVIDIA .*Quadro FX.* 1 1 0 3.3
NVIDIA Quadro NVS 1xxM .*NVIDIA .*(Quadro)* NVS *1.[05]M.* 0 1 1 3.3
NVIDIA Quadro NVS 300M .*NVIDIA .*(Quadro)*[ ]+NVS *30[0-9]M.* 2 1 0 0
NVIDIA Quadro NVS 320M .*NVIDIA .*(Quadro)*[ ]+NVS *32[0-9]M.* 2 1 0 0
NVIDIA Quadro NVS 2100M .*NVIDIA .*(Quadro)*[ ]+NVS *210[0-9]M.* 2 1 0 3.3
NVIDIA Quadro NVS 3100M .*NVIDIA .*(Quadro)*[ ]+NVS *310[0-9]M.* 2 1 0 3.3
NVIDIA Quadro NVS 4200M .*NVIDIA .*(Quadro)*[ ]+NVS *420[0-9]M.* 2 1 0 4.2
NVIDIA Quadro NVS 5100M .*NVIDIA .*(Quadro)*[ ]+NVS *510[0-9]M.* 2 1 0 0
NVIDIA Quadro NVS 5200M .*NVIDIA .*(Quadro)*[ ]+NVS *520[0-9]M.* 2 1 0 0
NVIDIA Quadro NVS 5400M .*NVIDIA .*(Quadro)*[ ]+NVS *540[0-9]M.* 2 1 0 0
NVIDIA Quadro NVS .*NVIDIA .*(Quadro)*[ ]+NVS 0 1 0 4.2
NVIDIA Quadro2 .*Quadro2.* 0 1 0 1.5
NVIDIA Quadro 1000M .*Quadro.* (K1|1)00[0-9]M.* 2 1 0 4.2
NVIDIA Quadro 1100M .*Quadro.* *110[0-9]M.* 2 1 0 3.3
NVIDIA Quadro K600 .*Quadro.* (K6|6)0[0-9][^0].* 2 1 0 4.2
NVIDIA Quadro K1000 .*Quadro.* (K1|1)00[0-9].* 2 1 0 4.2
NVIDIA Quadro 2000 M/D .*Quadro.* (K2|2)000.* 3 1 0 4.2
NVIDIA Quadro 3000M .*Quadro.* (K3|3)00[0-9]M.* 3 1 0 4.2
NVIDIA Quadro 4000M .*Quadro.* (K4|4)00[0-9]M.* 3 1 0 4.2
NVIDIA Quadro 4000 .*Quadro.* (K4|4)000.* 3 1 0 4.2
NVIDIA Quadro 50x0 M .*Quadro.* (K5|5)0.0.* 3 1 0 4.2
NVIDIA Quadro 6000 .*Quadro.* (K6|6)000.* 3 1 0 0
NVIDIA Quadro 400 .*Quadro.* 400.* 2 1 0 3.3
NVIDIA Quadro 600 .*Quadro.* 600.* 2 1 0 4.2
NVIDIA Quadro4 .*Quadro4.* 0 1 0 1.5
NVIDIA Quadro DCC .*Quadro DCC.* 0 1 0 0
NVIDIA Quadro CX .*Quadro.*CX.* 3 1 0 0
NVIDIA G 100M .*NVIDIA .*G *10[0-9]M.* 1 1 1 3.3
NVIDIA G 110M .*NVIDIA .*G *11[0-9]M.* 1 1 1 3.3
NVIDIA G 120M .*NVIDIA .*G *12[0-9]M.* 1 1 1 3.3
NVIDIA G 200M .*NVIDIA .*G *20[0-9]M.* 1 1 0 0
NVIDIA G 410M .*NVIDIA .*G *41[0-9]M.* 3 1 1 4.2
NVIDIA GT 130M .*NVIDIA .*GT *13[0-9]M.* 3 1 1 3.3
NVIDIA GT 140M .*NVIDIA .*GT *14[0-9]M.* 3 1 1 3.3
NVIDIA GT 150M .*NVIDIA .*GTS *15[0-9]M.* 2 1 0 0
NVIDIA GTS 160M .*NVIDIA .*GTS *16[0-9]M.* 2 1 0 0
NVIDIA G210M .*NVIDIA .*G *21[0-9]M.* 3 1 0 3.3
NVIDIA GT 220M .*NVIDIA .*GT 22[0-9]M.* 3 1 1 3.3
NVIDIA GT 230M .*NVIDIA .*GT 23[0-9]M.* 3 1 1 3.3
NVIDIA GT 240M .*NVIDIA .*GT 24[0-9]M.* 3 1 1 3.3
NVIDIA GT 260M .*NVIDIA .*GT 26[0-9]M.* 3 1 1 3.3
NVIDIA GTS 250M .*NVIDIA .*GTS 25[0-9]M.* 3 1 0 3.3
NVIDIA GTS 260M .*NVIDIA .*GTS 26[0-9]M.* 3 1 0 0
NVIDIA GTX 260M .*NVIDIA .*GTX 26[0-9]M.* 3 1 0 3.3
NVIDIA GTX 270M .*NVIDIA .*GTX 27[0-9]M.* 3 1 0 0
NVIDIA GTX 280M .*NVIDIA .*GTX 28[0-9]M.* 3 1 0 3.3
NVIDIA 300M .*NVIDIA .*GT 30[0-9]M.* 3 1 1 4.2
NVIDIA G 310M .*NVIDIA .*G[T]* 31[0-9]M.* 2 1 0 3.3
NVIDIA GT 320M .*NVIDIA .*G[T]* 32[0-9]M.* 3 1 0 3.3
NVIDIA GT 330M .*NVIDIA .*G[T]* 33[0-9]M.* 3 1 1 3.3
NVIDIA GT 340M .*NVIDIA .*G[T]* 34[0-9]M.* 4 1 1 3.3
NVIDIA GTS 350M .*NVIDIA .*GTS 35[0-9]M.* 4 1 1 3.3
NVIDIA GTS 360M .*NVIDIA .*GTS 36[0-9]M.* 5 1 1 3.3
NVIDIA 310M .*NVIDIA .*31[0-9]M.* 2 1 0 3.3
NVIDIA 320M .*NVIDIA .*320M.* 2 1 0 3.3
NVIDIA 400M .*NVIDIA .*[ ]+40[0-9]M.* 2 1 0 0
NVIDIA 410M .*NVIDIA .*[ ]+41[0-9]M.* 3 1 0 0
NVIDIA GT 420M .*NVIDIA .*GT *42[0-9]M.* 3 1 1 4.3
NVIDIA GT 430M .*NVIDIA .*GT *43[0-9]M.* 3 1 1 4.3
NVIDIA GT 440M .*NVIDIA .*GT *44[0-9]M.* 3 1 1 4.3
NVIDIA GT 450M .*NVIDIA .*GT *45[0-9]M.* 3 1 0 0
NVIDIA GTX 460M .*NVIDIA .*GTX *46[0-9]M.* 4 1 1 4.3
NVIDIA GTX 470M .*NVIDIA .*GTX *47[0-9]M.* 3 1 0 4.3
NVIDIA GTX 480M .*NVIDIA .*GTX *48[0-9]M.* 3 1 1 4.3
NVIDIA GT 520M .*NVIDIA .*GT *52[0-9]M.* 3 1 1 4.3
NVIDIA GT 530M .*NVIDIA .*GT *53[0-9]M.* 3 1 1 4.3
NVIDIA GT 540M .*NVIDIA .*GT *54[0-9]M.* 3 1 1 4.3
NVIDIA GT 550M .*NVIDIA .*GT *55[0-9]M.* 3 1 1 4.3
NVIDIA GTX 560M .*NVIDIA .*GTX *56[0-9]M.* 3 1 0 4.3
NVIDIA GTX 570M .*NVIDIA .*GTX *57[0-9]M.* 5 1 0 4.3
NVIDIA GTX 580M .*NVIDIA .*GTX *58[0-9]M.* 5 1 1 4.3
NVIDIA 610M .*NVIDIA.* 61[0-9]M.* 3 1 1 4.3
NVIDIA GT 620M .*NVIDIA .*GT *62[0-9]M.* 3 1 0 4.3
NVIDIA GT 630M .*NVIDIA .*GT *63[0-9]M.* 3 1 0 4.3
NVIDIA GT 640M .*NVIDIA .*GT *64[0-9]M.* 3 1 0 4.3
NVIDIA GT 650M .*NVIDIA .*GT *65[0-9]M.* 3 1 0 4.3
NVIDIA GTX 660M .*NVIDIA .*GTX *66[0-9]M.* 5 1 0 4.3
NVIDIA GTX 670M .*NVIDIA .*GTX *67[0-9]M.* 5 1 1 4.3
NVIDIA GTX 680M .*NVIDIA .*GTX *68[0-9]M.* 5 1 0 4.3
NVIDIA GTX 690M .*NVIDIA .*GTX *69[0-9]M.* 5 1 0 4.3
NVIDIA 710M .*NVIDIA.* 71[0-9]M.* 3 1 0 4.3
NVIDIA GT 720M .*NVIDIA .*GT *72[0-9]M.* 3 1 0 4.3
NVIDIA GT 730M .*NVIDIA .*GT *73[0-9]M.* 3 1 0 4.3
NVIDIA GT 740M .*NVIDIA .*GT *74[0-9]M.* 3 1 0 4.3
NVIDIA GT 750M .*NVIDIA .*GT *75[0-9]M.* 3 1 0 4.3
NVIDIA GTX 760M .*NVIDIA .*GTX *76[0-9]M.* 5 1 0 4.3
NVIDIA GTX 770M .*NVIDIA .*GTX *77[0-9]M.* 5 1 0 4.3
NVIDIA GTX 780M .*NVIDIA .*GTX *78[0-9]M.* 5 1 0 4.3
NVIDIA G100 .*NVIDIA .*G10.* 3 1 1 4.2
NVIDIA GT 120 .*NVIDIA .*GT 12.* 2 1 0 3.3
NVIDIA GT 130 .*NVIDIA .*GT 13.* 2 1 0 3.3
NVIDIA GT 140 .*NVIDIA .*GT 14.* 2 1 0 3.3
NVIDIA GT 150 .*NVIDIA .*GT 15.* 2 1 1 3.3
NVIDIA GTS 150 .*NVIDIA .*GTS 15.* 2 1 0 0
NVIDIA 200 .*NVIDIA .[ ]+200[^0].* 2 1 1 3.3
NVIDIA G200 .*NVIDIA .*G[ ]*200.* 2 1 1 3.3
NVIDIA G210 .*NVIDIA .*G[ ]*210.* 3 1 1 3.3
NVIDIA 205 .*NVIDIA .*205[^0]*.* 3 1 1 3.3
NVIDIA 210 .*NVIDIA .*210$ 3 1 1 3.3
NVIDIA GeForce 210 .*NVIDIA .*(GeForce)[ ]210[^0]*$ 3 1 1 3.3
NVIDIA GT 220 .*NVIDIA .*GT *22.* 2 1 1 3.3
NVIDIA GT 230 .*NVIDIA .*GT *23.* 2 1 1 3.3
NVIDIA GT 240 .*NVIDIA .*GT *24.* 4 1 1 3.3
NVIDIA GTS 240 .*NVIDIA .*GTS *24.* 4 1 1 3.3
NVIDIA GTS 250 .*NVIDIA .*GTS *25.* 4 1 1 3.3
NVIDIA GTS 360 .*NVIDIA .*GTS *36.* 4 1 1 3.3
NVIDIA GTX 260 .*NVIDIA .*GTX *26.* 4 1 1 3.3
NVIDIA GTX 270 .*NVIDIA .*GTX *27.* 4 1 0 3.3
NVIDIA GTX 280 .*NVIDIA .*GTX *28.* 4 1 1 3.3
NVIDIA GTX 290 .*NVIDIA .*GTX *29.* 5 1 0 3.3
NVIDIA GT 320 .*NVIDIA .*GT *32.* 3 1 0 3.3
NVIDIA GT 330 .*NVIDIA .*GT *33.* 3 1 0 3.3
NVIDIA GT 340 .*NVIDIA .*GT *34.* 3 1 0 0
NVIDIA 310 .*NVIDIA .*310[^0M]*.* 3 1 1 3.3
NVIDIA 315 .*NVIDIA .*315[^0M]*.* 3 1 1 3.3
NVIDIA 320 .*NVIDIA .*320[^0M]*.* 3 1 1 3.3
NVIDIA 405 .*NVIDIA .*405[^0]*.* 3 1 0 3.3
NVIDIA 410 .*NVIDIA .*410[^0]*.* 3 1 0 3.3
NVIDIA GT 415 .*NVIDIA .*GT *415.* 3 1 1 4.3
NVIDIA GT 420 .*NVIDIA .*GT *42.* 3 1 1 4.3
NVIDIA GT 430 .*NVIDIA .*GT *43.* 3 1 1 4.3
NVIDIA GT 440 .*NVIDIA .*GT *44.* 4 1 1 4.3
NVIDIA GT 450 .*NVIDIA .*GT *45.* 4 1 1 4.3
NVIDIA GTS 450 .*NVIDIA .*GTS *45.* 4 1 1 4.3
NVIDIA GTX 460 .*NVIDIA .*GTX *46.* 5 1 1 4.3
NVIDIA GTX 470 .*NVIDIA .*GTX *47.* 5 1 1 4.3
NVIDIA GTX 480 .*NVIDIA .*GTX *48.* 5 1 1 4.3
NVIDIA 505 .*NVIDIA .*505[^0]*.* 3 1 0 0
NVIDIA 510 .*NVIDIA .*510[^0]*.* 3 1 0 0
NVIDIA GT 520 .*NVIDIA .*GT *52.* 3 1 1 4.3
NVIDIA GT 530 .*NVIDIA .*GT *53.* 3 1 1 4.3
NVIDIA GT 540 .*NVIDIA .*GT *54.* 3 1 1 4.3
NVIDIA GT 550 .*NVIDIA .*GT *55.* 3 1 1 4.3
NVIDIA GTX 550 .*NVIDIA .*GTX *55.* 5 1 1 4.3
NVIDIA GTX 560 .*NVIDIA .*GTX *56.* 5 1 1 4.3
NVIDIA GTX 570 .*NVIDIA .*GTX *57.* 5 1 1 4.3
NVIDIA GTX 580 .*NVIDIA .*GTX *58.* 5 1 1 4.3
NVIDIA GTX 590 .*NVIDIA .*GTX *59.* 5 1 1 4.3
NVIDIA 605 .*NVIDIA .*605[^0]*.* 3 1 1 4.3
NVIDIA GT 61x .*NVIDIA .*GT 61.* 3 1 1 4.3
NVIDIA GT 62x .*NVIDIA .*GT 62.* 3 1 0 4.3
NVIDIA GT 63x .*NVIDIA .*GT 63.* 3 1 0 4.3
NVIDIA GT 64x .*NVIDIA .*GT 64.* 3 1 0 4.3
NVIDIA GT 65x .*NVIDIA .*GT 65.* 3 1 1 4.3
NVIDIA GTX 64x .*NVIDIA .*GTX 64.* 3 1 1 4.3
NVIDIA GTX 65x .*NVIDIA .*GTX 65.* 3 1 1 4.3
NVIDIA GTX 66x .*NVIDIA .*GTX 66.* 5 1 0 4.3
NVIDIA GTX 67x .*NVIDIA .*GTX 67.* 5 1 1 4.3
NVIDIA GTX 68x .*NVIDIA .*GTX 68.* 5 1 1 4.3
NVIDIA GTX 69x .*NVIDIA .*GTX 69.* 5 1 1 4.3
NVIDIA GT 71x .*NVIDIA .*GT *71.* 3 1 0 4.3
NVIDIA GT 72x .*NVIDIA .*GT *72.* 3 1 0 4.3
NVIDIA GT 73x .*NVIDIA .*GT *73.* 3 1 0 4.3
NVIDIA GT 74x .*NVIDIA .*GT *74.* 3 1 0 4.3
NVIDIA GTX 75x .*NVIDIA .*GTX *75.* 3 1 0 4.3
NVIDIA GTX 76x .*NVIDIA .*GTX *76.* 5 1 0 4.3
NVIDIA GTX 77x .*NVIDIA .*GTX *77.* 5 1 0 4.3
NVIDIA GTX 78x .*NVIDIA .*GTX *78.* 5 1 0 4.3
NVIDIA GTX TITAN .*NVIDIA .*GTX *TITAN.* 5 1 0 4.3
NVIDIA C51 .*NVIDIA .*C51.* 0 1 1 2
NVIDIA G72 .*NVIDIA .*G72.* 1 1 0 0
NVIDIA G73 .*NVIDIA .*G73.* 1 1 0 0
NVIDIA G84 .*NVIDIA .*G84.* 2 1 0 0
NVIDIA G86 .*NVIDIA .*G86.* 3 1 0 0
NVIDIA G92 .*NVIDIA .*G92.* 3 1 0 0
NVIDIA GK106 .*NVIDIA .*GK106.* 5 1 0 4.3
NVIDIA GeForce .*GeForce 256.* 0 0 0 0
NVIDIA GeForce 2 .*GeForce ?2 ?.* 0 1 1 1.5
NVIDIA GeForce 3 .*GeForce ?3 ?.* 2 1 1 2.1
NVIDIA GeForce 3 Ti .*GeForce ?3 Ti.* 0 1 0 0
NVIDIA GeForce 4 .*NVIDIA .*GeForce ?4.* 0 1 1 1.5
NVIDIA GeForce 4 Go .*NVIDIA .*GeForce ?4.*Go.* 0 1 0 0
NVIDIA GeForce 4 MX .*NVIDIA .*GeForce ?4 MX.* 0 1 0 0
NVIDIA GeForce 4 PCX .*NVIDIA .*GeForce ?4 PCX.* 0 1 0 0
NVIDIA GeForce 4 Ti .*NVIDIA .*GeForce ?4 Ti.* 0 1 0 0
NVIDIA GeForce 6100 .*NVIDIA .*GeForce 61.* 3 1 1 4.2
NVIDIA GeForce 6200 .*NVIDIA .*GeForce 62.* 0 1 1 2.1
NVIDIA GeForce 6500 .*NVIDIA .*GeForce 65.* 1 1 1 2.1
NVIDIA GeForce 6600 .*NVIDIA .*GeForce 66.* 2 1 1 2.1
NVIDIA GeForce 6700 .*NVIDIA .*GeForce 67.* 2 1 1 2.1
NVIDIA GeForce 6800 .*NVIDIA .*GeForce 68.* 1 1 1 2.1
NVIDIA GeForce 7000 .*NVIDIA .*GeForce 70.* 1 1 1 2.1
NVIDIA GeForce 7100 .*NVIDIA .*GeForce 71.* 1 1 1 2.1
NVIDIA GeForce 7200 .*NVIDIA .*GeForce 72.* 1 1 0 0
NVIDIA GeForce 7300 .*NVIDIA .*GeForce 73.* 1 1 1 2.1
NVIDIA GeForce 7500 .*NVIDIA .*GeForce 75.* 2 1 1 2.1
NVIDIA GeForce 7600 .*NVIDIA .*GeForce 76.* 2 1 1 2.1
NVIDIA GeForce 7800 .*NVIDIA .*GeForce 78.* 2 1 1 2.1
NVIDIA GeForce 7900 .*NVIDIA .*GeForce 79.* 3 1 1 2.1
NVIDIA GeForce 8100 .*NVIDIA .*GeForce 81.* 1 1 0 3.3
NVIDIA GeForce 8200M .*NVIDIA .*GeForce 820[0-9]M.* 1 1 0 3.3
NVIDIA GeForce 8200 .*NVIDIA .*GeForce 82.* 1 1 0 3.3
NVIDIA GeForce 8300 .*NVIDIA .*GeForce 83.* 3 1 1 3.3
NVIDIA GeForce 8400M .*NVIDIA .*GeForce 840[0-9]M.* 1 1 1 3.3
NVIDIA GeForce 8400 .*NVIDIA .*GeForce 84.* 2 1 1 3.3
NVIDIA GeForce 8500 .*NVIDIA .*GeForce 85.* 2 1 1 3.3
NVIDIA GeForce 8600M .*NVIDIA .*GeForce 860[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 8600 .*NVIDIA .*GeForce 86.* 3 1 1 3.3
NVIDIA GeForce 8700M .*NVIDIA .*GeForce 870[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 8700 .*NVIDIA .*GeForce 87.* 3 1 0 0
NVIDIA GeForce 8800M .*NVIDIA .*GeForce 880[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 8800 .*NVIDIA .*GeForce 88.* 3 1 1 3.3
NVIDIA GeForce 9100M .*NVIDIA .*GeForce 910[0-9]M.* 0 1 0 3.3
NVIDIA GeForce 9100 .*NVIDIA .*GeForce 91.* 0 1 0 3.3
NVIDIA GeForce 9200M .*NVIDIA .*GeForce 920[0-9]M.* 1 1 0 3.3
NVIDIA GeForce 9200 .*NVIDIA .*GeForce 92.* 1 1 0 3.3
NVIDIA GeForce 9300M .*NVIDIA .*GeForce 930[0-9]M.* 1 1 1 3.3
NVIDIA GeForce 9300 .*NVIDIA .*GeForce 93.* 1 1 1 3.3
NVIDIA GeForce 9400M .*NVIDIA .*GeForce 940[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 9400 .*NVIDIA .*GeForce 94.* 3 1 1 3.3
NVIDIA GeForce 9500M .*NVIDIA .*GeForce 950[0-9]M.* 1 1 1 3.3
NVIDIA GeForce 9500 .*NVIDIA .*GeForce 95.* 3 1 1 3.3
NVIDIA GeForce 9600M .*NVIDIA .*GeForce 960[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 9600 .*NVIDIA .*GeForce 96.* 3 1 1 3.3
NVIDIA GeForce 9700M .*NVIDIA .*GeForce 970[0-9]M.* 0 1 1 3.3
NVIDIA GeForce 9800M .*NVIDIA .*GeForce 980[0-9]M.* 2 1 1 3.3
NVIDIA GeForce 9800 .*NVIDIA .*GeForce 98.* 3 1 1 3.3
NVIDIA GeForce FX 5100 .*NVIDIA .*GeForce FX 51.* 0 1 0 0
NVIDIA GeForce FX 5200 .*NVIDIA .*GeForce FX 52.* 0 1 0 2.1
NVIDIA GeForce FX 5300 .*NVIDIA .*GeForce FX 53.* 0 1 0 0
NVIDIA GeForce FX 5500 .*NVIDIA .*GeForce FX 55.* 0 1 1 2.1
NVIDIA GeForce FX 5600 .*NVIDIA .*GeForce FX 56.* 1 1 1 2.1
NVIDIA GeForce FX 5700 .*NVIDIA .*GeForce FX 57.* 0 1 1 2.1
NVIDIA GeForce FX 5800 .*NVIDIA .*GeForce FX 58.* 1 1 0 0
NVIDIA GeForce FX 5900 .*NVIDIA .*GeForce FX 59.* 1 1 1 2.1
NVIDIA GeForce FX Go5100 .*NVIDIA .*GeForce FX Go51.* 0 1 0 0
NVIDIA GeForce FX Go5200 .*NVIDIA .*GeForce FX Go52.* 0 1 0 1.5
NVIDIA GeForce FX Go5300 .*NVIDIA .*GeForce FX Go53.* 0 1 0 0
NVIDIA GeForce FX Go5500 .*NVIDIA .*GeForce FX Go55.* 0 1 0 0
NVIDIA GeForce FX Go5600 .*NVIDIA .*GeForce FX Go56.* 0 1 1 2.1
NVIDIA GeForce FX Go5700 .*NVIDIA .*GeForce FX Go57.* 1 1 1 1.5
NVIDIA GeForce FX Go5800 .*NVIDIA .*GeForce FX Go58.* 1 1 0 0
NVIDIA GeForce FX Go5900 .*NVIDIA .*GeForce FX Go59.* 1 1 0 0
NVIDIA GeForce FX Go5xxx .*NVIDIA .*GeForce FX Go.* 0 1 0 0
NVIDIA GeForce Go 6100 .*NVIDIA .*GeForce Go 61.* 0 1 1 2.1
NVIDIA GeForce Go 6200 .*NVIDIA .*GeForce Go 62.* 0 1 0 1.5
NVIDIA GeForce Go 6400 .*NVIDIA .*GeForce Go 64.* 1 1 1 2.1
NVIDIA GeForce Go 6500 .*NVIDIA .*GeForce Go 65.* 1 1 0 0
NVIDIA GeForce Go 6600 .*NVIDIA .*GeForce Go 66.* 0 1 1 2.1
NVIDIA GeForce Go 6700 .*NVIDIA .*GeForce Go 67.* 1 1 0 0
NVIDIA GeForce Go 6800 .*NVIDIA .*GeForce Go 68.* 0 1 1 2.1
NVIDIA GeForce Go 7200 .*NVIDIA .*GeForce Go 72.* 1 1 0 2.1
NVIDIA GeForce Go 7300 LE .*NVIDIA .*GeForce Go 73.*LE.* 1 1 0 0
NVIDIA GeForce Go 7300 .*NVIDIA .*GeForce Go 73.* 1 1 1 2.1
NVIDIA GeForce Go 7400 .*NVIDIA .*GeForce Go 74.* 1 1 1 2.1
NVIDIA GeForce Go 7600 .*NVIDIA .*GeForce Go 76.* 1 1 1 2.1
NVIDIA GeForce Go 7700 .*NVIDIA .*GeForce Go 77.* 0 1 1 2.1
NVIDIA GeForce Go 7800 .*NVIDIA .*GeForce Go 78.* 2 1 0 0
NVIDIA GeForce Go 7900 .*NVIDIA .*GeForce Go 79.* 1 1 1 2.1
NVIDIA D9M .*NVIDIA .*D9M.* 1 1 0 0
NVIDIA G94 .*NVIDIA .*G94.* 3 1 0 0
NVIDIA GeForce Go 6 .*GeForce Go 6.* 1 1 0 0
NVIDIA NB8M .*NVIDIA .*NB8M.* 1 1 0 0
NVIDIA NB8P .*NVIDIA .*NB8P.* 2 1 0 0
NVIDIA NB9E .*NVIDIA .*NB9E.* 3 1 0 0
NVIDIA NB9M .*NVIDIA .*NB9M.* 1 1 0 0
NVIDIA NB9P .*NVIDIA .*NB9P.* 2 1 0 0
NVIDIA N10 .*NVIDIA .*N10.* 1 1 0 2.1
NVIDIA GeForce PCX .*GeForce PCX.* 0 1 0 1.5
NVIDIA PCI .*NVIDIA PCI[ ]* 0 0 0 2.1
NVIDIA Generic .*NVIDIA Generic.* 0 0 0 2.1
NVIDIA Generic Unknown .*NVIDIA .*Unknown.* 0 0 0 2.1
NVIDIA NV17 .*NVIDIA .*NV17.* 0 1 0 0
NVIDIA NV34 .*NVIDIA .*NV34.* 0 1 0 0
NVIDIA NV35 .*NVIDIA .*NV35.* 0 1 0 0
NVIDIA NV36 .*NVIDIA .*NV36.* 1 1 0 0
NVIDIA NV41 .*NVIDIA .*NV41.* 1 1 0 0
NVIDIA NV43 .*NVIDIA .*NV43.* 1 1 0 0
NVIDIA NV44 .*NVIDIA .*NV44.* 1 1 0 0
NVIDIA nForce .*NVIDIA .*nForce.* 0 0 0 3.3
NVIDIA MCP51 .*NVIDIA .*MCP51.* 1 1 0 0
NVIDIA MCP61 .*NVIDIA .*MCP61.* 1 1 0 2.1
NVIDIA MCP67 .*NVIDIA .*MCP67.* 1 1 0 0
NVIDIA MCP68 .*NVIDIA .*MCP68.* 1 1 0 0
NVIDIA MCP73 .*NVIDIA .*MCP73.* 1 1 0 0
NVIDIA MCP77 .*NVIDIA .*MCP77.* 1 1 0 0
NVIDIA MCP78 .*NVIDIA .*MCP78.* 1 1 0 0
NVIDIA MCP79 .*NVIDIA .*MCP79.* 1 1 0 0
NVIDIA MCP7A .*NVIDIA .*MCP7A.* 1 1 0 0
NVIDIA Corporation N12P .*NVIDIA .*N12P.* 1 1 1 4.1
NVIDIA Corporation N11M .*NVIDIA .*N11M.* 2 1 0 3.1
NVIDIA RIVA TNT .*RIVA TNT.* 0 0 0 1.5
NVIDIA GRID .*NVIDIA .*GRID.* 0 0 0 1.5
NVIDIA ION 2 .*NVIDIA .* *[I][O][N] 2.* 2 1 0 0
NVIDIA ION a .*NVIDIA .*[I][O][N]$ 2 1 1 3.3
NVIDIA ION b .*NVIDIA .*(Corporation) [I][O][N].* 2 1 1 3.3
S3 .*S3 *(Graphics)*.* 0 0 1 1.4
SiS SiS.* 0 0 1 1.5
Trident Trident.* 0 0 0 0
Tungsten Graphics Tungsten.* 0 0 0 0
XGI XGI.* 0 0 0 0
VIA VIA.* 0 0 0 0
Apple Generic Apple.*Generic.* 0 0 0 0
Apple Software Renderer Apple.*Software Renderer.* 0 0 0 0
Oracle VirtualBox.* 0 1 1 2.1
Humper Humper.* 0 1 1 2.1
PowerVR SGX545 .*PowerVR SGX.* 1 1 1 3
ATI GeForce Lulz .*ATI.*GeForce.* 0 0 0 0

View File

@ -275,9 +275,24 @@ bool LLAgent::isActionAllowed(const LLSD& sdname)
if (param == "speak")
{
if ( gAgent.isVoiceConnected() &&
LLViewerParcelMgr::getInstance()->allowAgentVoice() &&
! LLVoiceClient::getInstance()->inTuningMode() )
bool allow_agent_voice = false;
LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel();
if (channel != NULL)
{
if (channel->getSessionName().empty() && channel->getSessionID().isNull())
{
// default channel
allow_agent_voice = LLViewerParcelMgr::getInstance()->allowAgentVoice();
}
else
{
allow_agent_voice = channel->isActive() && channel->callStarted();
}
}
if (gAgent.isVoiceConnected() &&
allow_agent_voice &&
!LLVoiceClient::getInstance()->inTuningMode())
{
retval = true;
}

View File

@ -1043,7 +1043,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
if (mismatched == 0 && !update_inventory)
{
LL_DEBUGS("Avatar") << "no changes, bailing out" << LL_ENDL;
mCOFChangeInProgress = false;
notifyLoadingFinished();
return;
}
@ -1100,7 +1100,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
if (mismatched == 0)
{
LL_DEBUGS("Avatar") << "inventory updated, wearable assets not changed, bailing out" << LL_ENDL;
mCOFChangeInProgress = false;
notifyLoadingFinished();
return;
}

View File

@ -1869,7 +1869,7 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
{
++n_clothes;
}
else if (item->getType() == LLAssetType::AT_BODYPART)
else if (item->getType() == LLAssetType::AT_BODYPART || item->getType() == LLAssetType::AT_GESTURE)
{
return isAgentAvatarValid();
}
@ -3825,6 +3825,10 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
{
LL_DEBUGS("Avatar") << "ATT removing attachment " << item->getName() << " id " << item->getUUID() << LL_ENDL;
}
if (item && item->getType() == LLAssetType::AT_BODYPART)
{
continue;
}
removeCOFItemLinks(linked_item_id, cb);
addDoomedTempAttachment(linked_item_id);
}

View File

@ -124,6 +124,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>
@ -131,7 +134,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in processMarkerFiles
#else
@ -327,7 +329,10 @@ BOOL gDisconnected = FALSE;
// used to restore texture state after a mode switch
LLFrameTimer gRestoreGLTimer;
BOOL gRestoreGL = FALSE;
BOOL gUseWireframe = FALSE;
BOOL gUseWireframe = FALSE;
//use for remember deferred mode in wireframe switch
BOOL gInitialDeferredModeForWireframe = FALSE;
// VFS globals - see llappviewer.h
LLVFS* gStaticVFS = NULL;
@ -1728,6 +1733,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();
@ -2784,11 +2792,11 @@ bool LLAppViewer::initConfiguration()
//
gWindowTitle = LLTrans::getString("APP_NAME");
#if LL_DEBUG
gWindowTitle += std::string(" [DEBUG]")
gWindowTitle += std::string(" [DEBUG]");
#endif
if (!gArgs.empty())
{
gWindowTitle += std::string(" ") + gArgs;
gWindowTitle += std::string(" ") + gArgs;
}
LLStringUtil::truncate(gWindowTitle, 255);
@ -3370,8 +3378,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

@ -390,6 +390,7 @@ extern BOOL gDisconnected;
extern LLFrameTimer gRestoreGLTimer;
extern BOOL gRestoreGL;
extern BOOL gUseWireframe;
extern BOOL gInitialDeferredModeForWireframe;
// VFS globals - gVFS is for general use
// gStaticVFS is read-only and is shipped w/ the viewer

View File

@ -618,7 +618,10 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
case LLAssetType::AT_NOTECARD:
{
// Update the UI with the new asset.
LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
LLSD floater_key;
floater_key["taskid"] = task_id;
floater_key["itemid"] = item_id;
LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", floater_key);
if(nc)
{
// *HACK: we have to delete the asset in the VFS so

View File

@ -526,7 +526,7 @@ protected:
showSystemContextMenu(x,y);
if(mAvatarID.notNull() && mSourceType == CHAT_SOURCE_AGENT)
showAvatarContextMenu(x,y);
if(mAvatarID.notNull() && mSourceType == CHAT_SOURCE_OBJECT && SYSTEM_FROM != mFrom)
if(mAvatarID.notNull() && mSourceType == CHAT_SOURCE_OBJECT)
showObjectContextMenu(x,y);
}

View File

@ -483,7 +483,7 @@ void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel
const LLAssetType::EType item_type = item->getType();
if (item_type == LLAssetType::AT_CLOTHING) continue;
LLPanelInventoryListItemBase* item_panel = NULL;
if (item_type == LLAssetType::AT_OBJECT)
if (item_type == LLAssetType::AT_OBJECT || item_type == LLAssetType::AT_GESTURE)
{
item_panel = buildAttachemntListItem(item);
mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);

View File

@ -220,24 +220,7 @@ void LLDrawPoolTerrain::render(S32 pass)
// Special-case for land ownership feedback
if (gSavedSettings.getBOOL("ShowParcelOwners"))
{
if (mVertexShaderLevel > 1)
{ //use fullbright shader for highlighting
LLGLSLShader* old_shader = sShader;
sShader->unbind();
sShader = &gHighlightProgram;
sShader->bind();
gGL.diffuseColor4f(1,1,1,1);
LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
renderOwnership();
sShader = old_shader;
sShader->bind();
}
else
{
gPipeline.disableLights();
renderOwnership();
}
hilightParcelOwners();
}
}
@ -265,7 +248,15 @@ void LLDrawPoolTerrain::renderDeferred(S32 pass)
{
return;
}
renderFullShader();
// Special-case for land ownership feedback
if (gSavedSettings.getBOOL("ShowParcelOwners"))
{
hilightParcelOwners();
}
}
void LLDrawPoolTerrain::beginShadowPass(S32 pass)
@ -454,6 +445,28 @@ void LLDrawPoolTerrain::renderFullShader()
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
void LLDrawPoolTerrain::hilightParcelOwners()
{
if (mVertexShaderLevel > 1)
{ //use fullbright shader for highlighting
LLGLSLShader* old_shader = sShader;
sShader->unbind();
sShader = &gHighlightProgram;
sShader->bind();
gGL.diffuseColor4f(1, 1, 1, 1);
LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
renderOwnership();
sShader = old_shader;
sShader->bind();
}
else
{
gPipeline.disableLights();
renderOwnership();
}
}
void LLDrawPoolTerrain::renderFull4TU()
{
// Hack! Get the region that this draw pool is rendering from!

View File

@ -76,6 +76,7 @@ public:
static S32 sDetailMode;
static F32 sDetailScale; // meters per texture
protected:
void renderSimple();
void renderOwnership();
@ -84,6 +85,9 @@ protected:
void renderFull4TU();
void renderFullShader();
void drawLoop();
private:
void hilightParcelOwners();
};
#endif // LL_LLDRAWPOOLSIMPLE_H

View File

@ -237,6 +237,7 @@ LLExpandableTextBox::LLExpandableTextBox(const Params& p)
LLTextBoxEx::Params textbox_params = p.textbox;
textbox_params.rect(rc);
mTextBox = LLUICtrlFactory::create<LLTextBoxEx>(textbox_params);
mTextBox->setContentTrusted(false);
mScroll->addChild(mTextBox);
updateTextBoxRect();
@ -260,6 +261,11 @@ void LLExpandableTextBox::draw()
LLUICtrl::draw();
}
void LLExpandableTextBox::setContentTrusted(bool trusted_content)
{
mTextBox->setContentTrusted(trusted_content);
}
void LLExpandableTextBox::collapseIfPosChanged()
{
if(mExpanded)

View File

@ -194,6 +194,8 @@ protected:
*/
virtual S32 recalculateTextDelta(S32 text_delta);
void setContentTrusted(bool trusted_content);
protected:
std::string mText;

View File

@ -51,10 +51,18 @@ void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, ca
LLViewerObject* object = gObjectList.findObject(request["object-id"]);
if (!object)
{
LL_WARNS() << "Failed to find object with ID " << request["object-id"] << " in fetchAssociatedExperience" << LL_ENDL;
return;
LL_DEBUGS() << "Object with ID " << request["object-id"] << " not found via gObjectList.findObject() in fetchAssociatedExperience" << LL_ENDL;
LL_DEBUGS() << "Using gAgent.getRegion() instead of object->getRegion()" << LL_ENDL;
}
LLViewerRegion* region = NULL;
if (object)
{
region = object->getRegion();
}
else
{
region = gAgent.getRegion();
}
LLViewerRegion* region = object->getRegion();
if (region)
{
std::string lookup_url=region->getCapability("GetMetadata");
@ -66,6 +74,10 @@ void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, ca
LLHTTPClient::post(lookup_url, request, new ExperienceAssociationResponder(callback));
}
}
else
{
LL_WARNS() << "Failed to lookup region in fetchAssociatedExperience. Fetch request not sent." << LL_ENDL;
}
}
void ExperienceAssociationResponder::httpFailure()

View File

@ -112,6 +112,7 @@ void LLExperienceLog::handleExperienceMessage(LLSD& message)
}
message["Time"] = time_of_day;
mEvents[day].append(message);
mEventsToSave[day].append(message);
mSignals(message);
}
@ -180,9 +181,8 @@ void LLExperienceLog::notify( LLSD& message )
void LLExperienceLog::saveEvents()
{
eraseExpired();
std::string filename = getFilename();
LLSD settings = LLSD::emptyMap().with("Events", mEvents);
LLSD settings = LLSD::emptyMap().with("Events", mEventsToSave);
settings["MaxDays"] = (int)mMaxDays;
settings["Notify"] = mNotifyNewEvent;
@ -217,9 +217,8 @@ void LLExperienceLog::loadEvents()
if(mMaxDays > 0 && settings.has("Events"))
{
mEvents = settings["Events"];
mEventsToSave = mEvents;
}
eraseExpired();
}
LLExperienceLog::~LLExperienceLog()
@ -235,6 +234,26 @@ void LLExperienceLog::eraseExpired()
}
}
bool LLExperienceLog::isNotExpired(std::string& date)
{
LLDate event_date;
S32 month, day, year;
S32 matched = sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day);
if (matched != 3) return false;
event_date.fromYMDHMS(year, month, day);
const U32 seconds_in_day = 24 * 60 * 60;
S32 curr_year = 0, curr_month = 0, curr_day = 0;
LLDate curr_date = LLDate::now();
curr_date.split(&curr_year, &curr_month, &curr_day);
curr_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
LLDate boundary_date = LLDate(curr_date.secondsSinceEpoch() - seconds_in_day*getMaxDays());
return event_date >= boundary_date;
}
const LLSD& LLExperienceLog::getEvents() const
{
return mEvents;
@ -248,10 +267,6 @@ void LLExperienceLog::clear()
void LLExperienceLog::setMaxDays( U32 val )
{
mMaxDays = val;
if(mMaxDays > 0)
{
eraseExpired();
}
}
LLExperienceLog::callback_connection_t LLExperienceLog::addUpdateSignal( const callback_slot_t& cb )

View File

@ -59,6 +59,8 @@ public:
static void notify(LLSD& message);
static std::string getFilename();
static std::string getPermissionString(const LLSD& message, const std::string& base);
void setEventsToSave(LLSD new_events){mEventsToSave = new_events; }
bool isNotExpired(std::string& date);
protected:
LLExperienceLog();
void handleExperienceMessage(LLSD& message);
@ -68,7 +70,10 @@ protected:
void saveEvents();
void eraseExpired();
LLSD mEvents;
LLSD mEventsToSave;
callback_signal_t mSignals;
callback_connection_t mNotifyConnection;
U32 mMaxDays;

View File

@ -655,11 +655,12 @@ void LLFavoritesBarCtrl::changed(U32 mask)
LLInventoryModel::cat_array_t cats;
LLIsType is_type(LLAssetType::AT_LANDMARK);
gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
{
LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());
}
updateButtons();
if (!mItemsChangedTimer.getStarted())
{
@ -751,7 +752,11 @@ void LLFavoritesBarCtrl::updateButtons()
if(mGetPrevItems)
{
LLFavoritesOrderStorage::instance().mPrevFavorites = mItems;
for (LLInventoryModel::item_array_t::iterator it = mItems.begin(); it != mItems.end(); it++)
{
LLFavoritesOrderStorage::instance().mFavoriteNames[(*it)->getUUID()]= (*it)->getName();
}
LLFavoritesOrderStorage::instance().mPrevFavorites = mItems;
mGetPrevItems = false;
}
@ -778,7 +783,7 @@ void LLFavoritesBarCtrl::updateButtons()
const LLViewerInventoryItem *item = mItems[first_changed_item_index].get();
if (item)
{
// an child's order and mItems should be same
// an child's order and mItems should be same
if (button->getLandmarkId() != item->getUUID() // sort order has been changed
|| button->getLabelSelected() != item->getName() // favorite's name has been changed
|| button->getRect().mRight < rightest_point) // favbar's width has been changed
@ -1617,7 +1622,7 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
{
LLSD user_llsd = fav_llsd[av_name.getUserName()];
if (user_llsd.beginArray()->has("id"))
if ((user_llsd.beginArray()!= user_llsd.endArray()) && user_llsd.beginArray()->has("id"))
{
for (LLSD::array_iterator iter = user_llsd.beginArray();iter != user_llsd.endArray(); ++iter)
{
@ -1783,10 +1788,20 @@ BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed)
gInventory.collectDescendentsIf(favorite_folder, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
std::sort(items.begin(), items.end(), LLFavoritesSort());
bool name_changed = false;
if((items != mPrevFavorites) || pref_changed)
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
{
std::string filename = getStoredFavoritesFilename();
if(mFavoriteNames[(*it)->getUUID()] != ((*it)->getName()))
{
mFavoriteNames[(*it)->getUUID()] = (*it)->getName();
name_changed = true;
}
}
if((items != mPrevFavorites) || name_changed || pref_changed)
{
std::string filename = getStoredFavoritesFilename();
if (!filename.empty())
{
llifstream in_file;

View File

@ -218,6 +218,7 @@ public:
const static S32 NO_INDEX;
static bool mSaveOnExit;
bool mUpdateRequired;
std::map<LLUUID,std::string> mFavoriteNames;
private:
friend class LLSingleton<LLFavoritesOrderStorage>;

View File

@ -60,8 +60,6 @@
#include "lldxhardware.h"
#endif
#define LL_EXPORT_GPU_TABLE 0
#if LL_DARWIN
const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt";
const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_mac.%s.txt";

View File

@ -117,12 +117,20 @@ LLExperienceHandler gExperienceHandler;
LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data)
: LLFloater(data)
, mExperienceId(data.asUUID())
, mSaveCompleteAction(NOTHING)
, mDirty(false)
, mForceClose(false)
{
if (data.has("experience_id"))
{
mExperienceId = data["experience_id"].asUUID();
mPostEdit = data.has("edit_experience") && data["edit_experience"].asBoolean();
}
else
{
mExperienceId = data.asUUID();
mPostEdit = false;
}
}
@ -329,7 +337,13 @@ BOOL LLFloaterExperienceProfile::postBuild()
LLEventPumps::instance().obtain("experience_permission").listen(mExperienceId.asString()+"-profile",
boost::bind(&LLFloaterExperienceProfile::experiencePermission, getDerivedHandle<LLFloaterExperienceProfile>(this), _1));
if (mPostEdit && mExperienceId.notNull())
{
mPostEdit = false;
changeToEdit();
}
return TRUE;
}
@ -356,9 +370,7 @@ bool LLFloaterExperienceProfile::experiencePermission( LLHandle<LLFloaterExperie
void LLFloaterExperienceProfile::onClickEdit()
{
LLTabContainer* tabs = getChild<LLTabContainer>("tab_container");
tabs->selectTabByName("edit_panel_experience_info");
changeToEdit();
}
@ -829,6 +841,13 @@ void LLFloaterExperienceProfile::changeToView()
}
}
void LLFloaterExperienceProfile::changeToEdit()
{
LLTabContainer* tabs = getChild<LLTabContainer>("tab_container");
tabs->selectTabByName("edit_panel_experience_info");
}
void LLFloaterExperienceProfile::onClickLocation()
{
LLViewerRegion* region = gAgent.getRegion();

View File

@ -76,6 +76,7 @@ protected:
void setEditGroup(LLUUID group_id);
void changeToView();
void changeToEdit();
void experienceForgotten();
void experienceBlocked();
@ -99,6 +100,7 @@ protected:
int mSaveCompleteAction;
bool mDirty;
bool mForceClose;
bool mPostEdit; // edit experience after opening and updating it
};
#endif // LL_LLFLOATEREXPERIENCEPROFILE_H

View File

@ -303,6 +303,32 @@ void LLFloaterExperiences::checkPurchaseInfo(LLPanelExperiences* panel, const LL
LLFloaterExperiences::findInstance()->updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
}
void LLFloaterExperiences::checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const
{
checkPurchaseInfo(panel, content);
// determine new item
const LLSD& response_ids = content["experience_ids"];
if (mPrepurchaseIds.size() + 1 == response_ids.size())
{
// we have a new element
for (LLSD::array_const_iterator it = response_ids.beginArray(); it != response_ids.endArray(); ++it)
{
LLUUID experience_id = it->asUUID();
if (std::find(mPrepurchaseIds.begin(), mPrepurchaseIds.end(), experience_id) == mPrepurchaseIds.end())
{
// new element found, open it
LLSD args;
args["experience_id"] = experience_id;
args["edit_experience"] = true;
LLFloaterReg::showInstance("experience_profile", args, true);
break;
}
}
}
}
void LLFloaterExperiences::updateInfo(std::string experiences, std::string tab)
{
LLViewerRegion* region = gAgent.getRegion();
@ -318,18 +344,28 @@ void LLFloaterExperiences::updateInfo(std::string experiences, std::string tab)
}
}
void LLFloaterExperiences::sendPurchaseRequest() const
void LLFloaterExperiences::sendPurchaseRequest()
{
LLViewerRegion* region = gAgent.getRegion();
std::string url = region->getCapability("AgentExperiences");
if(!url.empty())
{
LLSD content;
const std::string tab_owned_name = "Owned_Experiences_Tab";
// extract ids for experiences that we already have
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
LLPanelExperiences* tab_owned = (LLPanelExperiences*)tabs->getPanelByName(tab_owned_name);
mPrepurchaseIds.clear();
if (tab_owned)
{
tab_owned->getExperienceIdsList(mPrepurchaseIds);
}
LLExperienceListResponder::NameMap nameMap;
nameMap["experience_ids"]="Owned_Experiences_Tab";
nameMap["experience_ids"] = tab_owned_name;
LLExperienceListResponder* responder = new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap, "ExperienceAcquireFailed");
responder->mCallback = boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2);
responder->mCallback = boost::bind(&LLFloaterExperiences::checkAndOpen, this, _1, _2);
LLHTTPClient::post(url, content, responder);
}
}

View File

@ -49,12 +49,14 @@ protected:
LLPanelExperiences* addTab(const std::string& name, bool select);
bool updatePermissions(const LLSD& permission);
void sendPurchaseRequest() const;
void sendPurchaseRequest();
void checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content)const;
void checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const;
void updateInfo(std::string experiences, std::string tab);
private:
std::vector<LLUUID> mPrepurchaseIds;
};
#endif //LL_LLFLOATEREXPERIENCES_H

View File

@ -1916,19 +1916,17 @@ bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid)
if (gdatap->isRoleMemberDataComplete())
{
if (!gdatap->mMembers.size())
{
return false;
}
LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
if (mi != gdatap->mMembers.end())
{
LLGroupMemberData* member_data = (*mi).second;
// Is the member an owner?
if (member_data && member_data->isInRole(gdatap->mOwnerRole))
if (gdatap->mMembers.size())
{
LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
if (mi != gdatap->mMembers.end())
{
return false;
LLGroupMemberData* member_data = (*mi).second;
// Is the member an owner?
if (member_data && member_data->isInRole(gdatap->mOwnerRole))
{
return false;
}
}
}
}

View File

@ -2573,6 +2573,112 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
shader->bind();
}
}
void LLModelPreview::genModelBBox()
{
LLVector3 min, max;
min = this->mModelLoader->mExtents[0];
max = this->mModelLoader->mExtents[1];
std::vector<LLVector3> v_list;
v_list.resize(4);
std::map<U8, std::vector<LLVector3> > face_list;
// Face 0
v_list[0] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]);
v_list[1] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]);
v_list[2] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]);
v_list[3] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]);
face_list.insert(std::pair<U8, std::vector<LLVector3> >(0, v_list));
// Face 1
v_list[0] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]);
v_list[1] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]);
v_list[2] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]);
v_list[3] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]);
face_list.insert(std::pair<U8, std::vector<LLVector3> >(1, v_list));
// Face 2
v_list[0] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]);
v_list[1] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]);
v_list[2] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]);
v_list[3] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]);
face_list.insert(std::pair<U8, std::vector<LLVector3> >(2, v_list));
// Face 3
v_list[0] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]);
v_list[1] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]);
v_list[2] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]);
v_list[3] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]);
face_list.insert(std::pair<U8, std::vector<LLVector3> >(3, v_list));
// Face 4
v_list[0] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]);
v_list[1] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]);
v_list[2] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]);
v_list[3] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]);
face_list.insert(std::pair<U8, std::vector<LLVector3> >(4, v_list));
// Face 5
v_list[0] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]);
v_list[1] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]);
v_list[2] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]);
v_list[3] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]);
face_list.insert(std::pair<U8, std::vector<LLVector3> >(5, v_list));
U16 Idx[] = { 0, 1, 2, 3, 0, 2, };
U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
buff->allocateBuffer(4, 6, true);
LLStrider<LLVector3> pos;
LLStrider<U16> idx;
LLStrider<LLVector3> norm;
LLStrider<LLVector2> tc;
buff->getVertexStrider(pos);
buff->getIndexStrider(idx);
buff->getNormalStrider(norm);
buff->getTexCoord0Strider(tc);
for (U32 i = 0; i < 6; ++i)
{
idx[i] = Idx[i];
}
LLVolumeParams volume_params;
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
LLModel* mdl = new LLModel(volume_params, 0.f);
mdl->mLabel = "BBOX"; // please adopt name from high LOD (mBaseModel) or from original model otherwise it breaks search mechanics which is name based
mdl->setNumVolumeFaces(6);
for (U8 i = 0; i < 6; ++i)
{
for (U8 j = 0; j < 4; ++j)
{
pos[j] = face_list[i][j];
}
mdl->setVolumeFaceData(i, pos, norm, tc, idx, buff->getNumVerts(), buff->getNumIndices());
}
if (validate_model(mdl))
{
LLMatrix4 mat;
std::map<std::string, LLImportMaterial> materials;
std::vector<LLModelInstance> instance_list;
instance_list.push_back(LLModelInstance(mdl, mdl->mLabel, mat, materials));
for (S32 i = LLModel::LOD_HIGH - 1; i >= 0; i--)
{
mModel[i].clear();
mModel[i].push_back(mdl);
mScene[i].clear();
mScene[i].insert(std::pair<LLMatrix4, std::vector<LLModelInstance> >(mat, instance_list));
}
}
}
void LLModelPreview::updateStatusMessages()
{
@ -3563,6 +3669,7 @@ BOOL LLModelPreview::render()
fmp->enableViewOption("show_skin_weight");
fmp->setViewOptionEnabled("show_joint_positions", skin_weight);
mFMP->childEnable("upload_skin");
mFMP->childSetValue("show_skin_weight", skin_weight);
}
}
else
@ -3683,7 +3790,7 @@ BOOL LLModelPreview::render()
}
else
{
LL_INFOS(" ") << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
regen = TRUE;
}
}

View File

@ -262,6 +262,7 @@ public:
void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
void loadModelCallback(S32 lod);
void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
void genModelBBox(); // Generate just a model BBox if we can't generate proper LOD
void generateNormals();
void restoreNormals();
U32 calcResourceCost();

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"
@ -1942,6 +1943,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

@ -370,6 +370,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mLandImpactsObserver(NULL),
mDirty(TRUE),
mHasSelection(TRUE),
mNeedMediaTitle(TRUE)
{
gFloaterTools = this;
@ -541,7 +542,14 @@ void LLFloaterTools::refresh()
void LLFloaterTools::draw()
{
if (mDirty)
BOOL has_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty();
if(!has_selection && (mHasSelection != has_selection))
{
mDirty = TRUE;
}
mHasSelection = has_selection;
if (mDirty)
{
refresh();
mDirty = FALSE;

View File

@ -198,6 +198,7 @@ public:
private:
BOOL mDirty;
BOOL mHasSelection;
std::map<std::string, std::string> mStatusText;

View File

@ -118,25 +118,32 @@ void LLFloaterTopObjects::setMode(U32 mode)
// static
void LLFloaterTopObjects::handle_land_reply(LLMessageSystem* msg, void** data)
{
LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
if(!instance) return;
// Make sure dialog is on screen
LLFloaterReg::showInstance("top_objects");
instance->handleReply(msg, data);
//HACK: for some reason sometimes top scripts originally comes back
//with no results even though they're there
if (!instance->mObjectListIDs.size() && !instance->mInitialized)
LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
if(instance && instance->isInVisibleChain())
{
instance->handleReply(msg, data);
//HACK: for some reason sometimes top scripts originally comes back
//with no results even though they're there
if (!instance->mObjectListIDs.size() && !instance->mInitialized)
{
instance->onRefresh();
instance->mInitialized = TRUE;
}
}
else
{
instance->onRefresh();
instance->mInitialized = TRUE;
LLFloaterRegionInfo* region_info_floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
if(region_info_floater)
{
region_info_floater->enableTopButtons();
}
}
}
void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
{
U32 request_flags;
U32 request_flags;
U32 total_count;
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_RequestFlags, request_flags);

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

Some files were not shown because too many files have changed in this diff Show More