summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/CMakeLists.txt2
-rw-r--r--indra/cmake/LLWindow.cmake2
-rw-r--r--indra/cmake/LibVLCPlugin.cmake27
-rw-r--r--indra/edit-me-to-trigger-new-build.txt1
-rw-r--r--indra/llcommon/CMakeLists.txt8
-rw-r--r--indra/llcommon/llcoros.cpp29
-rw-r--r--indra/llcommon/lldependencies.cpp4
-rw-r--r--indra/llcommon/llerror.h87
-rw-r--r--indra/llcommon/lleventcoro.cpp4
-rw-r--r--indra/llcommon/llevents.cpp18
-rw-r--r--indra/llcommon/llevents.h32
-rw-r--r--indra/llcommon/llexception.cpp55
-rw-r--r--indra/llcommon/llexception.h46
-rw-r--r--indra/llcommon/llfasttimer.h11
-rw-r--r--indra/llcommon/llleap.cpp6
-rw-r--r--indra/llcommon/llmemory.h10
-rw-r--r--indra/llcommon/llprocess.cpp20
-rw-r--r--indra/llcommon/llthreadsafequeue.cpp14
-rw-r--r--indra/llcommon/lluuid.cpp2
-rw-r--r--indra/llcommon/tests/llerror_test.cpp17
-rw-r--r--indra/llcommon/tests/llexception_test.cpp308
-rw-r--r--indra/llcommon/tests/wrapllerrs.h3
-rw-r--r--indra/llimage/llimage.cpp93
-rw-r--r--indra/llimage/llpngwrapper.cpp14
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp147
-rw-r--r--indra/llmessage/llavatarnamecache.cpp11
-rw-r--r--indra/llmessage/llcoproceduremanager.cpp14
-rw-r--r--indra/llmessage/llhttpnode.cpp9
-rw-r--r--indra/llmessage/tests/commtest.h3
-rw-r--r--indra/llmessage/tests/networkio.h5
-rw-r--r--indra/llrender/llglslshader.cpp4
-rw-r--r--indra/llrender/llshadermgr.cpp2
-rw-r--r--indra/llui/llview.cpp2
-rw-r--r--indra/media_plugins/CMakeLists.txt7
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp60
-rw-r--r--indra/media_plugins/libvlc/CMakeLists.txt86
-rw-r--r--indra/media_plugins/libvlc/media_plugin_libvlc.cpp618
-rwxr-xr-x[-rw-r--r--]indra/media_plugins/quicktime/CMakeLists.txt10
-rwxr-xr-x[-rw-r--r--]indra/media_plugins/quicktime/media_plugin_quicktime.cpp7
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/llaccountingcostmanager.cpp10
-rw-r--r--indra/newview/llappcorehttp.cpp3
-rw-r--r--indra/newview/llappviewer.cpp48
-rw-r--r--indra/newview/llappviewerwin32.cpp46
-rw-r--r--indra/newview/llcommandlineparser.cpp17
-rw-r--r--indra/newview/llfloaterwebcontent.cpp45
-rw-r--r--indra/newview/llfloaterwebcontent.h5
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp46
-rw-r--r--indra/newview/llpanelprimmediacontrols.h8
-rw-r--r--indra/newview/llsecapi.cpp12
-rw-r--r--indra/newview/llsechandler_basic.cpp91
-rw-r--r--indra/newview/llsurfacepatch.cpp4
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llweb.cpp4
-rw-r--r--indra/newview/llweb.h2
-rw-r--r--indra/newview/llworld.cpp8
-rw-r--r--indra/newview/skins/default/textures/icons/Video_URL_Off.pngbin0 -> 282 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_web_content.xml130
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml25
-rw-r--r--indra/newview/skins/default/xui/en/mime_types.xml56
-rw-r--r--indra/newview/skins/default/xui/en/mime_types_linux.xml30
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml3
-rwxr-xr-xindra/newview/viewer_manifest.py23
-rw-r--r--indra/viewer_components/login/lllogin.cpp102
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.cpp11
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.cpp3
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp12
71 files changed, 2088 insertions, 481 deletions
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 6dc8e3dfbf..13a31cbce7 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -24,7 +24,6 @@ set(cmake_SOURCE_FILES
DirectX.cmake
DragDrop.cmake
EXPAT.cmake
-## ExamplePlugin.cmake
FindAPR.cmake
FindAutobuild.cmake
FindBerkeleyDB.cmake
@@ -100,6 +99,7 @@ set(cmake_SOURCE_FILES
Variables.cmake
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
+ LibVLCPlugin.cmake
XmlRpcEpi.cmake
ZLIB.cmake
)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index ba07a80f05..80af7ff2ab 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -18,7 +18,7 @@ else (USESYSTEMLIBS)
use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
- set (SDL_LIBRARY SDL directfb fusion direct)
+ set (SDL_LIBRARY SDL directfb fusion direct X11)
endif (LINUX)
endif (USESYSTEMLIBS)
diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake
new file mode 100644
index 0000000000..4472676fb4
--- /dev/null
+++ b/indra/cmake/LibVLCPlugin.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (USESYSTEMLIBS)
+ set(LIBVLCPLUGIN OFF CACHE BOOL
+ "LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
+else (USESYSTEMLIBS)
+ use_prebuilt_binary(vlc-bin)
+ set(LIBVLCPLUGIN ON CACHE BOOL
+ "LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
+ set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc)
+endif (USESYSTEMLIBS)
+
+if (WINDOWS)
+ set(VLC_PLUGIN_LIBRARIES
+ libvlc.lib
+ libvlccore.lib
+ )
+elseif (DARWIN)
+elseif (LINUX)
+ # Specify a full path to make sure we get a static link
+ set(VLC_PLUGIN_LIBRARIES
+ ${LIBS_PREBUILT_DIR}/lib/libvlc.a
+ ${LIBS_PREBUILT_DIR}/lib/libvlccore.a
+ )
+endif (WINDOWS)
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index 32aa08a2b7..9f9ca6c39c 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1,3 +1,4 @@
2014-02-25 10:34
+
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 44f45144e5..410a5819b3 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES
lleventfilter.cpp
llevents.cpp
lleventtimer.cpp
+ llexception.cpp
llfasttimer.cpp
llfile.cpp
llfindlocale.cpp
@@ -316,7 +317,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
- LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
@@ -329,6 +330,11 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
+## llexception_test.cpp isn't a regression test, and doesn't need to be run
+## every build. It's to help a developer make implementation choices about
+## throwing and catching exceptions.
+##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}")
+
# *TODO - reenable these once tcmalloc libs no longer break the build.
#ADD_BUILD_TEST(llallocator llcommon)
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index d16bf0160b..8e516d8beb 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -38,6 +38,7 @@
#include "llevents.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
// do nothing, when we need nothing done
void LLCoros::no_cleanup(CoroData*) {}
@@ -131,9 +132,9 @@ bool LLCoros::cleanup(const LLSD&)
if ((previousCount < 5) || !(previousCount % 50))
{
if (previousCount < 5)
- LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
else
- LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
}
// The erase() call will invalidate its passed iterator value --
@@ -185,9 +186,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
if ((previousCount < 5) || !(previousCount % 50))
{
if (previousCount < 5)
- LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
else
- LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
}
@@ -223,7 +224,7 @@ std::string LLCoros::getName() const
void LLCoros::setStackSize(S32 stacksize)
{
- LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
mStackSize = stacksize;
}
@@ -235,7 +236,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
// capture the 'self' param in CoroData
data->mSelf = &self;
// run the code the caller actually wants in the coroutine
- callable();
+ try
+ {
+ callable();
+ }
+ catch (const LLContinueError&)
+ {
+ // Any uncaught exception derived from LLContinueError will be caught
+ // here and logged. This coroutine will terminate but the rest of the
+ // viewer will carry on.
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
+ catch (...)
+ {
+ // Any OTHER kind of uncaught exception will cause the viewer to
+ // crash, hopefully informatively.
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
// This cleanup isn't perfectly symmetrical with the way we initially set
// data->mPrev, but this is our last chance to reset mCurrentCoro.
sCurrentCoro.reset(data->mPrev);
diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp
index 87a699ff14..0d5757effd 100644
--- a/indra/llcommon/lldependencies.cpp
+++ b/indra/llcommon/lldependencies.cpp
@@ -39,8 +39,8 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/graph/exception.hpp>
-#include <boost/throw_exception.hpp>
// other Linden headers
+#include "llexception.h"
LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
{
@@ -77,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const
// Omit independent nodes: display only those that might contribute to
// the cycle.
describe(out, false);
- BOOST_THROW_EXCEPTION(Cycle(out.str()));
+ LLTHROW(Cycle(out.str()));
}
// A peculiarity of boost::topological_sort() is that it emits results in
// REVERSE topological order: to get the result you want, you must
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 3beef65723..7cbe4334b3 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -174,7 +174,8 @@ namespace LLError
// not really a level
// used to indicate that no messages should be logged
};
-
+ // If you change ELevel, please update llvlog() macro below.
+
/* Macro support
The classes CallSite and Log are used by the logging macros below.
They are not intended for general use.
@@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
/////////////////////////////////
// Error Logging Macros
-// See top of file for common usage.
+// See top of file for common usage.
/////////////////////////////////
-// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements
-// without braces:
-// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL
-
-#define lllog(level, once, ...) \
- do { \
- const char* tags[] = {"", ##__VA_ARGS__}; \
- ::size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \
- static LLError::CallSite _site( \
- level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
- if (LL_UNLIKELY(_site.shouldLog())) \
- { \
- std::ostringstream* _out = LLError::Log::out(); \
+// Instead of using LL_DEBUGS(), LL_INFOS() et al., it may be tempting to
+// directly code the lllog() macro so you can pass in the LLError::ELevel as a
+// variable. DON'T DO IT! The reason is that the first time control passes
+// through lllog(), it initializes a local static LLError::CallSite with that
+// *first* ELevel value. All subsequent visits will decide whether or not to
+// emit output based on the *first* ELevel value bound into that static
+// CallSite instance. Use LL_VLOGS() instead. lllog() assumes its ELevel
+// argument never varies.
+
+// this macro uses a one-shot do statement to avoid parsing errors when
+// writing control flow statements without braces:
+// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL;
+
+#define lllog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
+ lllog_test_()
+
+#define lllog_test_() \
+ if (LL_UNLIKELY(_site.shouldLog())) \
+ { \
+ std::ostringstream* _out = LLError::Log::out(); \
(*_out)
+#define lllog_site_args_(level, once, tags) \
+ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
+ __FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
+
//Use this construct if you need to do computation in the middle of a
//message:
//
@@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
+// Use this if you need to pass LLError::ELevel as a variable.
+#define LL_VLOGS(level, ...) llvlog(level, false, ##__VA_ARGS__)
+#define LL_VLOGS_ONCE(level, ...) llvlog(level, true, ##__VA_ARGS__)
+
+// The problem with using lllog() with a variable level is that the first time
+// through, it initializes a static CallSite instance with whatever level you
+// pass. That first level is bound into the CallSite; the level parameter is
+// never again examined. One approach to variable level would be to
+// dynamically construct a CallSite instance every call -- which could get
+// expensive, depending on context. So instead, initialize a static CallSite
+// for each level value we support, then dynamically select the CallSite
+// instance for the passed level value.
+// Compare implementation to lllog() above.
+#define llvlog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ /* Need a static CallSite instance per expected ELevel value. */ \
+ /* Since we intend to index this array with the ELevel, */ \
+ /* _sites[0] should be ELevel(0), and so on -- avoid using */ \
+ /* ELevel symbolic names when initializing -- except for */ \
+ /* the last entry, which handles anything beyond the end. */ \
+ /* (Commented ELevel value names are from 2016-09-01.) */ \
+ /* Passing an ELevel past the end of this array is itself */ \
+ /* a fatal error, so ensure the last is LEVEL_ERROR. */ \
+ static LLError::CallSite _sites[] = \
+ { \
+ /* LEVEL_DEBUG */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
+ /* LEVEL_INFO */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
+ /* LEVEL_WARN */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
+ /* LEVEL_ERROR */ \
+ LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
+ }; \
+ /* Clamp the passed 'level' to at most last entry */ \
+ std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
+ (LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
+ /* selected CallSite *must* be named _site for LL_ENDL */ \
+ LLError::CallSite& _site(_sites[which]); \
+ lllog_test_()
+
#endif // LL_LLERROR_H
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index f444530a17..56367b8f54 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -34,12 +34,12 @@
#include <map>
// std headers
// external library headers
-#include <boost/throw_exception.hpp>
// other Linden headers
#include "llsdserialize.h"
#include "llerror.h"
#include "llcoros.h"
#include "llmake.h"
+#include "llexception.h"
#include "lleventfilter.h"
@@ -352,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)
// returning it, deliver it via exception.
if (result.second)
{
- BOOST_THROW_EXCEPTION(LLErrorEvent(desc, result.first));
+ LLTHROW(LLErrorEvent(desc, result.first));
}
// That way, our caller knows a simple return must be from the reply
// pump (pump 0).
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 50919edb8e..19d700a3b0 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -45,7 +45,6 @@
#include <cctype>
// external library headers
#include <boost/range/iterator_range.hpp>
-#include <boost/throw_exception.hpp>
#if LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no
@@ -58,6 +57,7 @@
#include "stringize.h"
#include "llerror.h"
#include "llsdutil.h"
+#include "llexception.h"
#if LL_MSVC
#pragma warning (disable : 4702)
#endif
@@ -175,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string
// Unless we're permitted to tweak it, that's Bad.
if (! tweak)
{
- BOOST_THROW_EXCEPTION(LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'"));
+ LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'"));
}
// The passed name isn't unique, but we're permitted to tweak it. Find the
// first decimal-integer suffix not already taken. The insert() attempt
@@ -327,9 +327,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// is only when the existing connection object is still connected.
if (found != mConnections.end() && found->second.connected())
{
- BOOST_THROW_EXCEPTION(
- DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
- "' on " + typeid(*this).name() + " '" + getName() + "'"));
+ LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name +
+ "' on " + typeid(*this).name() + " '" + getName() + "'"));
}
// Okay, name is unique, try to reconcile its dependencies. Specify a new
// "node" value that we never use for an mSignal placement; we'll fix it
@@ -355,9 +354,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// unsortable. If we leave the new node in mDeps, it will continue
// to screw up all future attempts to sort()! Pull it out.
mDeps.remove(name);
- BOOST_THROW_EXCEPTION(
- Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
- " '" + getName() + "' would cause cycle: " + e.what()));
+ LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() +
+ " '" + getName() + "' would cause cycle: " + e.what()));
}
// Walk the list to verify that we haven't changed the order.
float previous = 0.0, myprev = 0.0;
@@ -421,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// NOW remove the offending listener node.
mDeps.remove(name);
// Having constructed a description of the order change, inform caller.
- BOOST_THROW_EXCEPTION(OrderChange(out.str()));
+ LLTHROW(OrderChange(out.str()));
}
// This node becomes the previous one.
previous = dmi->second;
@@ -611,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
{
if (! mListener)
{
- BOOST_THROW_EXCEPTION(Empty("attempting to call uninitialized"));
+ LLTHROW(Empty("attempting to call uninitialized"));
}
return (*mListener)(event);
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 8ff337911d..1526128725 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -95,12 +95,32 @@ struct LLStopWhenHandled
result_type operator()(InputIterator first, InputIterator last) const
{
for (InputIterator si = first; si != last; ++si)
- {
- if (*si)
- {
- return true;
- }
- }
+ {
+ try
+ {
+ if (*si)
+ {
+ return true;
+ }
+ }
+ catch (const LLContinueError&)
+ {
+ // We catch LLContinueError here because an LLContinueError-
+ // based exception means the viewer as a whole should carry on
+ // to the best of our ability. Therefore subsequent listeners
+ // on the same LLEventPump should still receive this event.
+
+ // The iterator passed to a boost::signals2 Combiner is very
+ // clever, but provides no contextual information. We would
+ // very much like to be able to log the name of the LLEventPump
+ // plus the name of this particular listener, but alas.
+ LOG_UNHANDLED_EXCEPTION("LLEventPump");
+ }
+ // We do NOT catch (...) here because we might as well let it
+ // propagate out to the generic handler. If we were able to log
+ // context information here, that would be great, but we can't, so
+ // there's no point.
+ }
return false;
}
};
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
new file mode 100644
index 0000000000..b32ec2c9c9
--- /dev/null
+++ b/indra/llcommon/llexception.cpp
@@ -0,0 +1,55 @@
+/**
+ * @file llexception.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-12
+ * @brief Implementation for llexception.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llexception.h"
+// STL headers
+// std headers
+#include <typeinfo>
+// external library headers
+#include <boost/exception/diagnostic_information.hpp>
+// other Linden headers
+#include "llerror.h"
+#include "llerrorcontrol.h"
+
+namespace {
+// used by crash_on_unhandled_exception_() and log_unhandled_exception_()
+void log_unhandled_exception_(LLError::ELevel level,
+ const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // log same message but allow caller-specified severity level
+ LL_VLOGS(level, "LLException") << LLError::abbreviateFile(file)
+ << "(" << line << "): Unhandled exception caught in " << pretty_function;
+ if (! context.empty())
+ {
+ LL_CONT << ": " << context;
+ }
+ LL_CONT << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL;
+}
+}
+
+void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // LL_ERRS() terminates and propagates message into crash dump.
+ log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context);
+}
+
+void log_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // Use LL_WARNS() because we seriously do not expect this to happen
+ // routinely, but we DO expect to return from this function.
+ log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function, context);
+}
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index 3ac2f4762f..dfcb7c192f 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -14,22 +14,24 @@
#include <stdexcept>
#include <boost/exception/exception.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/current_function.hpp>
+
+// "Found someone who can comfort me
+// But there are always exceptions..."
+// - Empty Pages, Traffic, from John Barleycorn (1970)
+// https://www.youtube.com/watch?v=dRH0CGVK7ic
/**
* LLException is intended as the common base class from which all
- * viewer-specific exceptions are derived. It is itself a subclass of
- * boost::exception; use catch (const boost::exception& e) clause to log the
- * string from boost::diagnostic_information(e).
- *
- * Since it is also derived from std::exception, a generic catch (const
- * std::exception&) should also work, though what() is unlikely to be as
- * informative as boost::diagnostic_information().
+ * viewer-specific exceptions are derived. Rationale for why it's derived from
+ * both std::exception and boost::exception is explained in
+ * tests/llexception_test.cpp.
*
- * Please use BOOST_THROW_EXCEPTION()
- * http://www.boost.org/doc/libs/release/libs/exception/doc/BOOST_THROW_EXCEPTION.html
- * to throw viewer exceptions whenever possible. This enriches the exception's
- * diagnostic_information() with the source file, line and containing function
- * of the BOOST_THROW_EXCEPTION() macro.
+ * boost::current_exception_diagnostic_information() is quite wonderful: if
+ * all we need to do with an exception is log it, in most places we should
+ * catch (...) and log boost::current_exception_diagnostic_information().
+ * See CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() below.
*
* There may be circumstances in which it would be valuable to distinguish an
* exception explicitly thrown by viewer code from an exception thrown by
@@ -60,4 +62,24 @@ struct LLContinueError: public LLException
{}
};
+/**
+ * Please use LLTHROW() to throw viewer exceptions whenever possible. This
+ * enriches the exception's diagnostic_information() with the source file,
+ * line and containing function of the LLTHROW() macro.
+ */
+// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in
+// LLTHROW() in case we ever want to revisit that implementation decision.
+#define LLTHROW(x) BOOST_THROW_EXCEPTION(x)
+
+/// Call this macro from a catch (...) clause
+#define CRASH_ON_UNHANDLED_EXCEPTION(CONTEXT) \
+ crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void crash_on_unhandled_exception_(const char*, int, const char*, const std::string&);
+
+/// Call this from a catch (const LLContinueError&) clause, or from a catch
+/// (...) clause in which you do NOT want the viewer to crash.
+#define LOG_UNHANDLED_EXCEPTION(CONTEXT) \
+ log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void log_unhandled_exception_(const char*, int, const char*, const std::string&);
+
#endif /* ! defined(LL_LLEXCEPTION_H) */
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 2370253078..f56e5596f5 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -296,7 +296,16 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
{
#if LL_FAST_TIMER_ON
BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- if (!cur_timer_data) return;
+ if (!cur_timer_data)
+ {
+ // How likely is it that
+ // LLThreadLocalSingletonPointer<T>::getInstance() will return NULL?
+ // Even without researching, what we can say is that if we exit
+ // without setting mStartTime at all, gcc 4.7 produces (fatal)
+ // warnings about a possibly-uninitialized data member.
+ mStartTime = 0;
+ return;
+ }
TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
accumulator.mActiveCount++;
// keep current parent as long as it is active when we are
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index a8bb9bc53a..c87d2a3e58 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -21,7 +21,6 @@
#include <boost/bind.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/tokenizer.hpp>
-#include <boost/throw_exception.hpp>
// other Linden headers
#include "llerror.h"
#include "llstring.h"
@@ -34,6 +33,7 @@
#include "lltimer.h"
#include "lluuid.h"
#include "llleaplistener.h"
+#include "llexception.h"
#if LL_MSVC
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
@@ -70,7 +70,7 @@ public:
// Rule out empty vector
if (plugin.empty())
{
- BOOST_THROW_EXCEPTION(Error("no plugin command"));
+ LLTHROW(Error("no plugin command"));
}
// Don't leave desc empty either, but in this case, if we weren't
@@ -113,7 +113,7 @@ public:
// If that didn't work, no point in keeping this LLLeap object.
if (! mChild)
{
- BOOST_THROW_EXCEPTION(Error(STRINGIZE("failed to run " << mDesc)));
+ LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));
}
// Okay, launch apparently worked. Change our mDonePump listener.
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 0fb257aab1..575edddc43 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -110,11 +110,15 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
#else
+ char* aligned = NULL;
void* mem = malloc( size + (align - 1) + sizeof(void*) );
- char* aligned = ((char*)mem) + sizeof(void*);
- aligned += align - ((uintptr_t)aligned & (align - 1));
+ if (mem)
+ {
+ aligned = ((char*)mem) + sizeof(void*);
+ aligned += align - ((uintptr_t)aligned & (align - 1));
- ((void**)aligned)[-1] = mem;
+ ((void**)aligned)[-1] = mem;
+ }
return aligned;
#endif
}
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index ca19c94736..8c321d06b9 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -34,12 +34,12 @@
#include "llapr.h"
#include "apr_signal.h"
#include "llevents.h"
+#include "llexception.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/buffers_iterator.hpp>
-#include <boost/throw_exception.hpp>
#include <iostream>
#include <stdexcept>
#include <limits>
@@ -531,9 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
if (! params.validateBlock(true))
{
- BOOST_THROW_EXCEPTION(
- LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
- << LLSDNotationStreamer(params))));
+ LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
+ << LLSDNotationStreamer(params))));
}
mPostend = params.postend;
@@ -598,11 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):
}
else
{
- BOOST_THROW_EXCEPTION(
- LLProcessError(STRINGIZE("For " << params.executable()
- << ": unsupported FileParam for " << which
- << ": type='" << fparam.type()
- << "', name='" << fparam.name() << "'")));
+ LLTHROW(LLProcessError(STRINGIZE("For " << params.executable()
+ << ": unsupported FileParam for " << which
+ << ": type='" << fparam.type()
+ << "', name='" << fparam.name() << "'")));
}
}
// By default, pass APR_NO_PIPE for unspecified slots.
@@ -681,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
gAPRPoolp)))
{
- BOOST_THROW_EXCEPTION(LLProcessError(STRINGIZE(params << " failed")));
+ LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
}
// arrange to call status_callback()
@@ -1066,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)
PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
if (! wp)
{
- BOOST_THROW_EXCEPTION(NoPipe(error));
+ LLTHROW(NoPipe(error));
}
return *wp;
}
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
index a004618e96..491f920c0f 100644
--- a/indra/llcommon/llthreadsafequeue.cpp
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -26,8 +26,8 @@
#include "linden_common.h"
#include <apr_pools.h>
#include <apr_queue.h>
-#include <boost/throw_exception.hpp>
#include "llthreadsafequeue.h"
+#include "llexception.h"
@@ -42,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
{
if(mOwnsPool) {
apr_status_t status = apr_pool_create(&mPool, 0);
- if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate pool"));
+ if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));
} else {
; // No op.
}
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
- if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate queue"));
+ if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
}
@@ -69,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)
apr_status_t status = apr_queue_push(mQueue, element);
if(status == APR_EINTR) {
- BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt());
+ LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
- BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("push failed"));
+ LLTHROW(LLThreadSafeQueueError("push failed"));
} else {
; // Success.
}
@@ -89,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)
apr_status_t status = apr_queue_pop(mQueue, &element);
if(status == APR_EINTR) {
- BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt());
+ LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
- BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("pop failed"));
+ LLTHROW(LLThreadSafeQueueError("pop failed"));
} else {
return element;
}
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 785cf47926..d4af2c6b01 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data )
unsigned int ret = 0;
for( int ix = 0; ix < 5; ++ix ) {
char * s = strchr( encodeTable, fiveChars[ ix ] );
-if( s == 0 ) BOOST_THROW_EXCEPTION(bad_input_data());
+if( s == 0 ) LLTHROW(bad_input_data());
ret = ret * 85 + (s-encodeTable);
}
return ret;
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index f51279e817..8bace8ac41 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -237,8 +237,21 @@ namespace tut
void ErrorTestObject::test<4>()
// file abbreviation
{
- std::string thisFile = __FILE__;
- std::string abbreviateFile = LLError::abbreviateFile(thisFile);
+ std::string prev, abbreviateFile = __FILE__;
+ do
+ {
+ prev = abbreviateFile;
+ abbreviateFile = LLError::abbreviateFile(abbreviateFile);
+ // __FILE__ is assumed to end with
+ // indra/llcommon/tests/llerror_test.cpp. This test used to call
+ // abbreviateFile() exactly once, then check below whether it
+ // still contained the string 'indra'. That fails if the FIRST
+ // part of the pathname also contains indra! Certain developer
+ // machine images put local directory trees under
+ // /ngi-persist/indra, which is where we observe the problem. So
+ // now, keep calling abbreviateFile() until it returns its
+ // argument unchanged, THEN check.
+ } while (abbreviateFile != prev);
ensure_ends_with("file name abbreviation",
abbreviateFile,
diff --git a/indra/llcommon/tests/llexception_test.cpp b/indra/llcommon/tests/llexception_test.cpp
new file mode 100644
index 0000000000..6bee1943c2
--- /dev/null
+++ b/indra/llcommon/tests/llexception_test.cpp
@@ -0,0 +1,308 @@
+/**
+ * @file llexception_test.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-12
+ * @brief Tests for throwing exceptions.
+ *
+ * This isn't a regression test: it doesn't need to be run every build, which
+ * is why the corresponding line in llcommon/CMakeLists.txt is commented out.
+ * Rather it's a head-to-head test of what kind of exception information we
+ * can collect from various combinations of exception base classes, type of
+ * throw verb and sequences of catch clauses.
+ *
+ * This "test" makes no ensure() calls: its output goes to stdout for human
+ * examination.
+ *
+ * As of 2016-08-12 with Boost 1.57, we come to the following conclusions.
+ * These should probably be re-examined from time to time as we update Boost.
+ *
+ * - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than
+ * plain throw. The macro annotates the exception object with the filename,
+ * line number and function name from which the exception was thrown.
+ *
+ * - That being the case, deriving only from boost::exception isn't an option.
+ * Every exception object passed to BOOST_THROW_EXCEPTION() must be derived
+ * directly or indirectly from std::exception. The only question is whether
+ * to also derive from boost::exception. We decided to derive LLException
+ * from both, as it makes message output slightly cleaner, but this is a
+ * trivial reason: if a strong reason emerges to prefer single inheritance,
+ * dropping the boost::exception base class shouldn't be a problem.
+ *
+ * - (As you will have guessed, ridiculous things like a char* or int or a
+ * class derived from neither boost::exception nor std::exception can only
+ * be caught by that specific type or (...), and
+ * boost::current_exception_diagnostic_information() simply throws up its
+ * hands and confesses utter ignorance. Stay away from such nonsense.)
+ *
+ * - But if you derive from std::exception, to nat's surprise,
+ * boost::current_exception_diagnostic_information() gives as much
+ * information about exceptions in a catch (...) clause as you can get from
+ * a specific catch (const std::exception&) clause, notably the concrete
+ * exception class and the what() string. So instead of a sequence like
+ *
+ * try { ... }
+ * catch (const boost::exception& e) { ... boost-flavored logging ... }
+ * catch (const std::exception& e) { ... std::exception logging ... }
+ * catch (...) { ... generic logging ... }
+ *
+ * we should be able to get away with only a catch (...) clause that logs
+ * boost::current_exception_diagnostic_information().
+ *
+ * - Going further: boost::current_exception_diagnostic_information() provides
+ * just as much information even within a std::set_terminate() handler. So
+ * it might not even be strictly necessary to include a catch (...) clause
+ * since the viewer does use std::set_terminate().
+ *
+ * - (We might consider adding a catch (int) clause because Kakadu internally
+ * throws ints, and who knows if one of those might leak out. If it does,
+ * boost::current_exception_diagnostic_information() can do nothing with it.
+ * A catch (int) clause could at least log the value and rethrow.)
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llexception.h"
+// STL headers
+// std headers
+#include <typeinfo>
+// external library headers
+#include <boost/throw_exception.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+// helper for display output
+// usage: std::cout << center(some string value, fill char, width) << std::endl;
+// (assumes it's the only thing on that particular line)
+struct center
+{
+ center(const std::string& label, char fill, std::size_t width):
+ mLabel(label),
+ mFill(fill),
+ mWidth(width)
+ {}
+
+ // Use friend declaration not because we need to grant access, but because
+ // it lets us declare a free operator like a member function.
+ friend std::ostream& operator<<(std::ostream& out, const center& ctr)
+ {
+ std::size_t padded = ctr.mLabel.length() + 2;
+ std::size_t left = (ctr.mWidth - padded) / 2;
+ std::size_t right = ctr.mWidth - left - padded;
+ return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' '
+ << std::string(right, ctr.mFill);
+ }
+
+ std::string mLabel;
+ char mFill;
+ std::size_t mWidth;
+};
+
+/*****************************************************************************
+* Four kinds of exceptions: derived from boost::exception, from
+* std::exception, from both, from neither
+*****************************************************************************/
+// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION()
+// (which we want) -- we reach a failure topped by this comment:
+// //All boost exceptions are required to derive from std::exception,
+// //to ensure compatibility with BOOST_NO_EXCEPTIONS.
+struct FromBoost: public boost::exception
+{
+ FromBoost(const std::string& what): mWhat(what) {}
+ ~FromBoost() throw() {}
+ std::string what() const { return mWhat; }
+ std::string mWhat;
+};
+
+struct FromStd: public std::runtime_error
+{
+ FromStd(const std::string& what): std::runtime_error(what) {}
+};
+
+struct FromBoth: public boost::exception, public std::runtime_error
+{
+ FromBoth(const std::string& what): std::runtime_error(what) {}
+};
+
+// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION().
+struct FromNeither
+{
+ FromNeither(const std::string& what): mWhat(what) {}
+ std::string what() const { return mWhat; }
+ std::string mWhat;
+};
+
+/*****************************************************************************
+* Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION()
+*****************************************************************************/
+template <typename EXC>
+void plain_throw(const std::string& what)
+{
+ throw EXC(what);
+}
+
+template <typename EXC>
+void boost_throw(const std::string& what)
+{
+ BOOST_THROW_EXCEPTION(EXC(what));
+}
+
+// Okay, for completeness, functions that throw non-class values. We wouldn't
+// even deign to consider these if we hadn't found examples in our own source
+// code! (Note that Kakadu's internal exception support is still based on
+// throwing ints.)
+void throw_char_ptr(const std::string& what)
+{
+ throw what.c_str(); // umm...
+}
+
+void throw_int(const std::string& what)
+{
+ throw int(what.length());
+}
+
+/*****************************************************************************
+* Three sequences of catch clauses:
+* boost::exception then ...,
+* std::exception then ...,
+* or just ...
+*****************************************************************************/
+void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (const boost::exception& e)
+ {
+ std::cout << "catch (const boost::exception& e)" << std::endl;
+ std::cout << "e is " << typeid(e).name() << std::endl;
+ std::cout << "boost::diagnostic_information(e):\n'"
+ << boost::diagnostic_information(e) << "'" << std::endl;
+ // no way to report e.what()
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "catch (const std::exception& e)" << std::endl;
+ std::cout << "e is " << typeid(e).name() << std::endl;
+ std::cout << "boost::diagnostic_information(e):\n'"
+ << boost::diagnostic_information(e) << "'" << std::endl;
+ std::cout << "e.what: '"
+ << e.what() << "'" << std::endl;
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+/*****************************************************************************
+* Try a particular kind of throw against each of three catch sequences
+*****************************************************************************/
+void catch_several(void (*thrower)(const std::string&), const std::string& what)
+{
+ std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl;
+ catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")");
+
+ std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl;
+ catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")");
+
+ std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl;
+ catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")");
+}
+
+/*****************************************************************************
+* For a particular kind of exception, try both kinds of throw against all
+* three catch sequences
+*****************************************************************************/
+template <typename EXC>
+void catch_both_several(const std::string& what)
+{
+ std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl;
+ catch_several(plain_throw<EXC>, "plain_throw<" + what + ">");
+
+ std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl;
+ catch_several(boost_throw<EXC>, "boost_throw<" + what + ">");
+}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llexception_data
+ {
+ };
+ typedef test_group<llexception_data> llexception_group;
+ typedef llexception_group::object object;
+ llexception_group llexceptiongrp("llexception");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("throwing exceptions");
+
+ // For each kind of exception, try both kinds of throw against all
+ // three catch sequences
+ std::size_t margin = 72;
+ std::cout << center("FromStd", '=', margin) << std::endl;
+ catch_both_several<FromStd>("FromStd");
+
+ std::cout << center("FromBoth", '=', margin) << std::endl;
+ catch_both_several<FromBoth>("FromBoth");
+
+ std::cout << center("FromBoost", '=', margin) << std::endl;
+ // can't throw with BOOST_THROW_EXCEPTION(), just use catch_several()
+ catch_several(plain_throw<FromBoost>, "plain_throw<FromBoost>");
+
+ std::cout << center("FromNeither", '=', margin) << std::endl;
+ // can't throw this with BOOST_THROW_EXCEPTION() either
+ catch_several(plain_throw<FromNeither>, "plain_throw<FromNeither>");
+
+ std::cout << center("const char*", '=', margin) << std::endl;
+ // We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft
+ // as a const char* or an int, so don't bother with
+ // catch_both_several() -- just catch_several().
+ catch_several(throw_char_ptr, "throw_char_ptr");
+
+ std::cout << center("int", '=', margin) << std::endl;
+ catch_several(throw_int, "throw_int");
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index fa16fd6915..9a4bbbd630 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -40,7 +40,6 @@
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/throw_exception.hpp>
#include <list>
#include <string>
@@ -79,7 +78,7 @@ struct WrapLLErrs
error = message;
// Also throw an appropriate exception since calling code is likely to
// assume that control won't continue beyond LL_ERRS.
- BOOST_THROW_EXCEPTION(FatalException(message));
+ LLTHROW(FatalException(message));
}
std::string error;
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 91fa8c6ad1..f331c533fd 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1401,7 +1401,12 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
{
- llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
+ S32 components = getComponents();
+ if (! ((1 == components) || (3 == components) || (4 == components) ))
+ {
+ LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
+ return false;
+ }
S32 old_width = getWidth();
S32 old_height = getHeight();
@@ -1415,67 +1420,53 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
if (scale_image_data)
{
- /*
- S32 temp_data_size = old_width * new_height * getComponents();
- llassert_always(temp_data_size > 0);
- std::vector<U8> temp_buffer(temp_data_size);
-
- // Vertical
- for( S32 col = 0; col < old_width; col++ )
- {
- copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width );
- }
-
- deleteData();
+ S32 new_data_size = new_width * new_height * components;
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
+ if (new_data_size > 0)
+ {
+ U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
+ if(NULL == new_data)
+ {
+ return false;
+ }
- // Horizontal
- for( S32 row = 0; row < new_height; row++ )
- {
- copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
- }
- */
-
- S32 new_data_size = new_width * new_height * getComponents();
- llassert_always(new_data_size > 0);
-
- U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
- if(NULL == new_data)
- {
- return false;
+ bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components);
+ setDataAndSize(new_data, new_width, new_height, components);
}
-
- bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents());
- setDataAndSize(new_data, new_width, new_height, getComponents());
}
else
{
// copy out existing image data
- S32 temp_data_size = old_width * old_height * getComponents();
+ S32 temp_data_size = old_width * old_height * components;
std::vector<U8> temp_buffer(temp_data_size);
memcpy(&temp_buffer[0], getData(), temp_data_size);
// allocate new image data, will delete old data
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
-
- for( S32 row = 0; row < new_height; row++ )
- {
- if (row < old_height)
- {
- memcpy(new_buffer + (new_width * row * getComponents()), &temp_buffer[0] + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width));
- if (old_width < new_width)
- {
- // pad out rest of row with black
- memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
- }
- }
- else
- {
- // pad remaining rows with black
- memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
- }
- }
+ U8* new_buffer = allocateDataSize(new_width, new_height, components);
+
+ if (!new_buffer)
+ {
+ LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL;
+ return false;
+ }
+
+ for( S32 row = 0; row < new_height; row++ )
+ {
+ if (row < old_height)
+ {
+ memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width));
+ if (old_width < new_width)
+ {
+ // pad out rest of row with black
+ memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width));
+ }
+ }
+ else
+ {
+ // pad remaining rows with black
+ memset(new_buffer + (new_width * row * components), 0, new_width * components);
+ }
+ }
}
return true ;
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index 0b7d4c717f..da289ea889 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -32,12 +32,12 @@
#include "llpngwrapper.h"
#include "llexception.h"
-#include <boost/throw_exception.hpp>
namespace {
-struct PngError: public LLException
+// Failure to load an image shouldn't crash the whole viewer.
+struct PngError: public LLContinueError
{
- PngError(png_const_charp msg): LLException(msg) {}
+ PngError(png_const_charp msg): LLContinueError(msg) {}
};
} // anonymous namespace
@@ -88,7 +88,7 @@ BOOL LLPngWrapper::isValidPng(U8* src)
// occurs. We throw PngError and let our try/catch block clean up.
void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)
{
- BOOST_THROW_EXCEPTION(PngError(msg));
+ LLTHROW(PngError(msg));
}
// Called by the libpng library when reading (decoding) the PNG file. We
@@ -138,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
this, &errorHandler, NULL);
if (mReadPngPtr == NULL)
{
- BOOST_THROW_EXCEPTION(PngError("Problem creating png read structure"));
+ LLTHROW(PngError("Problem creating png read structure"));
}
// Allocate/initialize the memory for image information.
@@ -297,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
if (mColorType == -1)
{
- BOOST_THROW_EXCEPTION(PngError("Unsupported image: unexpected number of channels"));
+ LLTHROW(PngError("Unsupported image: unexpected number of channels"));
}
mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, &errorHandler, NULL);
if (!mWritePngPtr)
{
- BOOST_THROW_EXCEPTION(PngError("Problem creating png write structure"));
+ LLTHROW(PngError("Problem creating png write structure"));
}
mWriteInfoPtr = png_create_info_struct(mWritePngPtr);
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 2847f347c2..aa405362e8 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -1,4 +1,4 @@
- /**
+/**
* @file llimagej2ckdu.cpp
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
*
@@ -31,19 +31,66 @@
#include "llpointer.h"
#include "llmath.h"
#include "llkdumem.h"
+#include "stringize.h"
#include "kdu_block_coding.h"
#include "llexception.h"
-#include <boost/throw_exception.hpp>
+#include <boost/exception/diagnostic_information.hpp>
+#include <sstream>
+#include <iomanip>
namespace {
-struct KDUError: public LLException
+// Failure to load an image shouldn't crash the whole viewer.
+struct KDUError: public LLContinueError
{
- KDUError(const std::string& msg): LLException(msg) {}
+ KDUError(const std::string& msg): LLContinueError(msg) {}
};
+
+// KDU defines int error codes as hex values, so we should log them in hex
+// so we can grep KDU headers for the hex. However those hex values
+// generally "happen" to encode big-endian multibyte character sequences,
+// e.g. KDU_ERROR_EXCEPTION is 0x6b647545: 'kduE'
+// But beware because KDU_NULL_EXCEPTION is simply 0 -- which doesn't
+// preclude somebody from throwing it.
+std::string report_kdu_exception(kdu_exception mb)
+{
+ std::ostringstream out;
+ // always report mb in hex
+ out << "kdu_exception " << std::hex << mb;
+
+ // Also display as many chars as are encoded in the kdu_exception
+ // value. Make a char array; reserve 1 extra byte for nul terminator.
+ char bytes[sizeof(kdu_exception) + 1];
+ // Back up through 'bytes'
+ char *bptr = bytes + sizeof(bytes);
+ *(--bptr) = '\0';
+ while (mb)
+ {
+ // store low-order byte of mb in next-left char
+ *(--bptr) = char(mb & 0xFF);
+ // then shift mb right by one byte
+ mb >>= 8;
+ }
+ // did that produce any characters?
+ if (*bptr)
+ {
+ out << " (" << bptr << ')';
+ }
+
+ return out.str();
+}
} // anonymous namespace
+// stream kdu_dims to std::ostream
+// Turns out this must NOT be in the anonymous namespace!
+inline
+std::ostream& operator<<(std::ostream& out, const kdu_dims& dims)
+{
+ return out << "(" << dims.pos.x << "," << dims.pos.y << "),"
+ "[" << dims.size.x << "x" << dims.size.y << "]";
+}
+
class kdc_flow_control {
public:
@@ -175,9 +222,15 @@ struct LLKDUMessageError : public LLKDUMessage
// terminating handler→flush call."
// So throwing an exception here isn't arbitrary: we MUST throw an
// exception if we want to recover from a KDU error.
+ // Because this confused me: the above quote specifically refers to
+ // the kdu_error class, which is constructed internally within KDU at
+ // the point where a fatal error is discovered and reported. It is NOT
+ // talking about the kdu_message subclass passed to
+ // kdu_customize_errors(). Destroying this static object at program
+ // shutdown will NOT engage the behavior described above.
if (end_of_message)
{
- BOOST_THROW_EXCEPTION(KDUError("LLKDUMessageError::flush()"));
+ LLTHROW(KDUError("LLKDUMessageError::flush()"));
}
}
};
@@ -206,6 +259,10 @@ LLImageJ2CKDU::~LLImageJ2CKDU()
// Stuff for new simple decode
void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision);
+// This is called by the real (private) initDecode() (keep_codestream true)
+// and getMetadata() methods (keep_codestream false). As far as nat can tell,
+// mode is always MODE_FAST. It was called by findDiscardLevelsBoundaries()
+// as well, when that still existed, with keep_codestream true and MODE_FAST.
void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)
{
S32 data_size = base.getDataSize();
@@ -216,6 +273,12 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
//
mCodeStreamp.reset();
+ // It's not clear to nat under what circumstances we would reuse a
+ // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
+ // two U32s and a pointer, so it's not as if it would be a huge overhead
+ // to allocate a new one every time.
+ // Also -- why is base.getData() tested specifically here? If that returns
+ // NULL, shouldn't we bail out of the whole method?
if (!mInputp && base.getData())
{
// The compressed data has been loaded
@@ -272,13 +335,19 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
S32 components = mCodeStreamp->get_num_components();
- if (components >= 3)
- { // Check that components have consistent dimensions (for PPM file)
- kdu_dims dims1; mCodeStreamp->get_dims(1,dims1);
- kdu_dims dims2; mCodeStreamp->get_dims(2,dims2);
- if ((dims1 != dims) || (dims2 != dims))
+ // Check that components have consistent dimensions (for PPM file)
+ for (int idx = 1; idx < components; ++idx)
+ {
+ kdu_dims other_dims;
+ mCodeStreamp->get_dims(idx, other_dims);
+ if (other_dims != dims)
{
- LL_ERRS() << "Components don't have matching dimensions!" << LL_ENDL;
+ // This method is only called from methods that catch KDUError.
+ // We want to fail the image load, not crash the viewer.
+ LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
+ << other_dims
+ << " do not match component 0 dimensions "
+ << dims << "!")));
}
}
@@ -305,6 +374,9 @@ void LLImageJ2CKDU::cleanupCodeStream()
mTileIndicesp.reset();
}
+// This is the protected virtual method called by LLImageJ2C::initDecode().
+// However, as far as nat can tell, LLImageJ2C::initDecode() is called only by
+// llimage_libtest.cpp's load_image() function. No detectable production use.
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
{
return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region);
@@ -337,6 +409,9 @@ bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc
return true;
}
+// This is the real (private) initDecode() called both by the protected
+// initDecode() method and by decodeImpl(). As far as nat can tell, only the
+// decodeImpl() usage matters for production.
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
{
base.resetLastError();
@@ -399,9 +474,19 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch (...)
{
- base.setLastError("Unknown J2C error");
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -497,9 +582,21 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
cleanupCodeStream();
return true; // done
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ base.decodeFailed();
+ cleanupCodeStream();
+ return true; // done
+ }
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
base.decodeFailed();
cleanupCodeStream();
return true; // done
@@ -688,9 +785,19 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch( ... )
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -712,9 +819,19 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
}
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 1ca5f58ae2..004db546b7 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -43,6 +43,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include "llexception.h"
+#include "stringize.h"
#include <map>
#include <set>
@@ -231,13 +233,12 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
}
- catch (std::exception e)
- {
- LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << url << "', " << agentIds.size()
+ << " Agent Ids)"));
+ throw;
}
}
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index d4c0788b7d..74cdff2b00 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -27,6 +27,8 @@
#include "linden_common.h"
#include "llcoproceduremanager.h"
+#include "llexception.h"
+#include "stringize.h"
#include <boost/assign.hpp>
//=========================================================================
@@ -388,14 +390,14 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap
{
coproc->mProc(httpAdapter, coproc->mId);
}
- catch (std::exception &e)
- {
- LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() <<
- " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("Coprocedure('" << coproc->mName
+ << "', id=" << coproc->mId.asString()
+ << ") in pool '" << mPoolName << "'"));
+ // must NOT omit this or we deplete the pool
+ mActiveCoprocs.erase(itActive);
+ throw;
}
LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL;
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index 48ce258ba2..04b34a296c 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -32,7 +32,6 @@
#include "llstl.h"
#include "llhttpconstants.h"
#include "llexception.h"
-#include <boost/throw_exception.hpp>
const std::string CONTEXT_HEADERS("headers");
const std::string CONTEXT_PATH("path");
@@ -103,19 +102,19 @@ namespace {
// virtual
LLSD LLHTTPNode::simpleGet() const
{
- BOOST_THROW_EXCEPTION(NotImplemented());
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePut(const LLSD& input) const
{
- BOOST_THROW_EXCEPTION(NotImplemented());
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePost(const LLSD& input) const
{
- BOOST_THROW_EXCEPTION(NotImplemented());
+ LLTHROW(NotImplemented());
}
@@ -175,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
// virtual
LLSD LLHTTPNode::simpleDel(const LLSD&) const
{
- BOOST_THROW_EXCEPTION(NotImplemented());
+ LLTHROW(NotImplemented());
}
// virtual
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h
index 5dff56b44f..7c8f27bbd2 100644
--- a/indra/llmessage/tests/commtest.h
+++ b/indra/llmessage/tests/commtest.h
@@ -38,7 +38,6 @@
#include <map>
#include <string>
#include <boost/lexical_cast.hpp>
-#include <boost/throw_exception.hpp>
struct CommtestError: public LLException
{
@@ -69,7 +68,7 @@ static int query_port(const std::string& var)
const char* cport = getenv(var.c_str());
if (! cport)
{
- BOOST_THROW_EXCEPTION(CommtestError(STRINGIZE("missing environment variable" << var)));
+ LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var)));
}
// This will throw, too, if the value of PORT isn't numeric.
int port(boost::lexical_cast<int>(cport));
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 6aaecf9bac..5eb739393f 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -35,7 +35,6 @@
#include "llpumpio.h"
#include "llhttpclient.h"
#include "llexception.h"
-#include <boost/throw_exception.hpp>
/*****************************************************************************
* NetworkIO
@@ -53,7 +52,7 @@ public:
ll_init_apr();
if (! gAPRPoolp)
{
- BOOST_THROW_EXCEPTION(LLException("Can't initialize APR"));
+ LLTHROW(LLException("Can't initialize APR"));
}
// Create IO Pump to use for HTTP Requests.
@@ -61,7 +60,7 @@ public:
LLHTTPClient::setPump(*mServicePump);
if (ll_init_ares() == NULL || !gAres->isInitialized())
{
- BOOST_THROW_EXCEPTION(LLException("Can't start DNS resolver"));
+ LLTHROW(LLException("Can't start DNS resolver"));
}
// You can interrupt pump() without waiting the full timeout duration
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index b30bc1aed6..58c1186a3e 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -349,8 +349,8 @@ void LLGLSLShader::unloadInternal()
for (GLsizei i = 0; i < count; i++)
{
glDetachObjectARB(mProgramObject, obj[i]);
- glDeleteObjectARB(obj[i]);
- }
+ glDeleteObjectARB(obj[i]);
+ }
glDeleteObjectARB(mProgramObject);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index b297223c2e..55f0791174 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -520,7 +520,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
if (!filename.empty())
{
LL_CONT << "From " << filename << ":\n";
- }
+ }
LL_CONT << log << LL_ENDL;
}
}
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 62c3f401bf..fd7406b653 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -812,7 +812,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
{
if (!getVisible())
- return false;
+ return NULL;
BOOST_FOREACH(LLView* viewp, mChildList)
{
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index 24eb3947b4..9055e0111a 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -4,15 +4,18 @@ add_subdirectory(base)
if (LINUX)
add_subdirectory(gstreamer010)
+ add_subdirectory(libvlc)
endif (LINUX)
-if (WINDOWS OR DARWIN)
+if (DARWIN)
add_subdirectory(quicktime)
add_subdirectory(cef)
-endif (WINDOWS OR DARWIN)
+endif (DARWIN)
if (WINDOWS)
+ add_subdirectory(cef)
add_subdirectory(winmmshim)
+ add_subdirectory(libvlc)
endif (WINDOWS)
### add_subdirectory(example)
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index 8d9d1dd975..28a8a5886a 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -100,6 +100,12 @@ private:
LLCEFLib* mLLCEFLib;
VolumeCatcher mVolumeCatcher;
+
+ U8 *mPopupBuffer;
+ U32 mPopupW;
+ U32 mPopupH;
+ U32 mPopupX;
+ U32 mPopupY;
};
////////////////////////////////////////////////////////////////////////////////
@@ -127,12 +133,19 @@ MediaPluginBase(host_send_func, host_user_data)
mCookiePath = "";
mPickedFile = "";
mLLCEFLib = new LLCEFLib();
+
+ mPopupBuffer = NULL;
+ mPopupW = 0;
+ mPopupH = 0;
+ mPopupX = 0;
+ mPopupY = 0;
}
////////////////////////////////////////////////////////////////////////////////
//
MediaPluginCEF::~MediaPluginCEF()
{
+ delete[] mPopupBuffer;
}
////////////////////////////////////////////////////////////////////////////////
@@ -155,20 +168,28 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg)
//
void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup)
{
- if (mPixels && pixels)
+ if( is_popup )
+ {
+ delete mPopupBuffer;
+ mPopupBuffer = NULL;
+ mPopupH = 0;
+ mPopupW = 0;
+ mPopupX = 0;
+ mPopupY = 0;
+ }
+
+ if( mPixels && pixels )
{
if (is_popup)
{
- for (int line = 0; line < height; ++line)
+ if( width > 0 && height> 0 )
{
- 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);
- }
+ mPopupBuffer = new U8[ width * height * mDepth ];
+ memcpy( mPopupBuffer, pixels, width * height * mDepth );
+ mPopupH = height;
+ mPopupW = width;
+ mPopupX = x;
+ mPopupY = mHeight - y - height;
}
}
else
@@ -177,6 +198,23 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y,
{
memcpy(mPixels, pixels, mWidth * mHeight * mDepth);
}
+ if( mPopupBuffer && mPopupH && mPopupW )
+ {
+ U32 bufferSize = mWidth * mHeight * mDepth;
+ U32 popupStride = mPopupW * mDepth;
+ U32 bufferStride = mWidth * mDepth;
+ int dstY = mPopupY;
+
+ int src = 0;
+ int dst = dstY * mWidth * mDepth + mPopupX * mDepth;
+
+ for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line )
+ {
+ memcpy( mPixels + dst, mPopupBuffer + src, popupStride );
+ src += popupStride;
+ dst += bufferStride;
+ }
+ }
}
setDirty(0, 0, mWidth, mHeight);
@@ -559,6 +597,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
S32 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
+ y = mHeight - 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
diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt
new file mode 100644
index 0000000000..535d29125b
--- /dev/null
+++ b/indra/media_plugins/libvlc/CMakeLists.txt
@@ -0,0 +1,86 @@
+# -*- cmake -*-
+
+project(media_plugin_libvlc)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(OpenGL)
+
+include(LibVLCPlugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ ${VLC_INCLUDE_DIR}
+)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ )
+
+
+### media_plugin_libvlc
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+set(media_plugin_libvlc_SOURCE_FILES
+ media_plugin_libvlc.cpp
+ )
+
+add_library(media_plugin_libvlc
+ SHARED
+ ${media_plugin_libvlc_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_libvlc
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${VLC_PLUGIN_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_libvlc
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ media_plugin_libvlc
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT"
+ )
+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_libvlc
+ PROPERTIES
+ PREFIX ""
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path"
+ LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+ )
+
+endif (DARWIN)
diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
new file mode 100644
index 0000000000..0bd323eb58
--- /dev/null
+++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
@@ -0,0 +1,618 @@
+/**
+* @file media_plugin_libvlc.cpp
+* @brief LibVLC plugin for LLMedia API plugin system
+*
+* @cond
+* $LicenseInfo:firstyear=2008&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+* @endcond
+*/
+
+#include "linden_common.h"
+
+#include "llgl.h"
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#include "vlc/vlc.h"
+#include "vlc/libvlc_version.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginLibVLC :
+ public MediaPluginBase
+{
+public:
+ MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginLibVLC();
+
+ /*virtual*/ void receiveMessage(const char* message_string);
+
+private:
+ bool init();
+
+ void initVLC();
+ void playMedia();
+ void resetVLC();
+ void setVolume(const F64 volume);
+ void updateTitle(const char* title);
+
+ static void* lock(void* data, void** p_pixels);
+ static void unlock(void* data, void* id, void* const* raw_pixels);
+ static void display(void* data, void* id);
+
+ /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */;
+
+ static void eventCallbacks(const libvlc_event_t* event, void* ptr);
+
+ libvlc_instance_t* mLibVLC;
+ libvlc_media_t* mLibVLCMedia;
+ libvlc_media_player_t* mLibVLCMediaPlayer;
+
+ struct mLibVLCContext
+ {
+ unsigned char* texture_pixels;
+ libvlc_media_player_t* mp;
+ MediaPluginLibVLC* parent;
+ };
+ struct mLibVLCContext mLibVLCCallbackContext;
+
+ std::string mURL;
+ F64 mCurVolume;
+
+ bool mIsLooping;
+
+ float mCurTime;
+ float mDuration;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
+MediaPluginBase(host_send_func, host_user_data)
+{
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mDepth = 4;
+ mPixels = 0;
+
+ mLibVLC = 0;
+ mLibVLCMedia = 0;
+ mLibVLCMediaPlayer = 0;
+
+ mCurVolume = 0.0;
+
+ mIsLooping = false;
+
+ mCurTime = 0.0;
+ mDuration = 0.0;
+
+ mURL = std::string();
+
+ setStatus(STATUS_NONE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginLibVLC::~MediaPluginLibVLC()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+void* MediaPluginLibVLC::lock(void* data, void** p_pixels)
+{
+ struct mLibVLCContext* context = (mLibVLCContext*)data;
+
+ *p_pixels = context->texture_pixels;
+
+ return NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels)
+{
+ // nothing to do here for the moment
+ // we *could* modify pixels here to, for example, Y flip, but this is done with
+ // a VLC video filter transform.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::display(void* data, void* id)
+{
+ struct mLibVLCContext* context = (mLibVLCContext*)data;
+
+ context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::initVLC()
+{
+ char const* vlc_argv[] =
+ {
+ "--no-xlib",
+ "--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client
+ };
+
+ int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
+ mLibVLC = libvlc_new(vlc_argc, vlc_argv);
+
+ if (!mLibVLC)
+ {
+ // for the moment, if this fails, the plugin will fail and
+ // the media sub-system will tell the viewer something went wrong.
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::resetVLC()
+{
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+ libvlc_release(mLibVLC);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// *virtual*
+void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
+
+ message.setValueS32("left", left);
+ message.setValueS32("top", top);
+ message.setValueS32("right", right);
+ message.setValueS32("bottom", bottom);
+
+ message.setValueReal("current_time", mCurTime);
+ message.setValueReal("duration", mDuration);
+ message.setValueReal("current_rate", 1.0f);
+
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
+{
+ MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr;
+ if (parent == 0)
+ {
+ return;
+ }
+
+ switch (event->type)
+ {
+ case libvlc_MediaPlayerOpening:
+ parent->setStatus(STATUS_LOADING);
+ break;
+
+ case libvlc_MediaPlayerPlaying:
+ parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f;
+ parent->setStatus(STATUS_PLAYING);
+ break;
+
+ case libvlc_MediaPlayerPaused:
+ parent->setStatus(STATUS_PAUSED);
+ break;
+
+ case libvlc_MediaPlayerStopped:
+ parent->setStatus(STATUS_DONE);
+ break;
+
+ case libvlc_MediaPlayerEndReached:
+ parent->setStatus(STATUS_DONE);
+ break;
+
+ case libvlc_MediaPlayerEncounteredError:
+ parent->setStatus(STATUS_ERROR);
+ break;
+
+ case libvlc_MediaPlayerTimeChanged:
+ parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f;
+ break;
+
+ case libvlc_MediaPlayerPositionChanged:
+ break;
+
+ case libvlc_MediaPlayerLengthChanged:
+ parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f;
+ break;
+
+ case libvlc_MediaPlayerTitleChanged:
+ {
+ char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title);
+ if (title)
+ {
+ parent->updateTitle(title);
+ }
+ }
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::playMedia()
+{
+ if (mURL.length() == 0)
+ {
+ return;
+ }
+
+ if (mLibVLCMediaPlayer)
+ {
+ // stop listening to events while we reset things
+ libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
+ if (em)
+ {
+ libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL);
+ };
+
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+
+ mLibVLCMediaPlayer = 0;
+ }
+
+ if (mLibVLCMedia)
+ {
+ libvlc_media_release(mLibVLCMedia);
+
+ mLibVLCMedia = 0;
+ }
+
+ mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
+ if (!mLibVLCMedia)
+ {
+ mLibVLCMediaPlayer = 0;
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia);
+ if (!mLibVLCMediaPlayer)
+ {
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ // listen to events
+ libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
+ if (em)
+ {
+ libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
+ }
+
+ mLibVLCCallbackContext.parent = this;
+ mLibVLCCallbackContext.texture_pixels = mPixels;
+ mLibVLCCallbackContext.mp = mLibVLCMediaPlayer;
+
+ // Send a "navigate begin" event.
+ // This is really a browser message but the QuickTime plugin did it and
+ // the media system relies on this message to update internal state so we must send it too
+ // Note: see "navigate_complete" message below too
+ // https://jira.secondlife.com/browse/MAINT-6528
+ LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ message_begin.setValue("uri", mURL);
+ message_begin.setValueBoolean("history_back_available", false);
+ message_begin.setValueBoolean("history_forward_available", false);
+ sendMessage(message_begin);
+
+ // volume level gets set before VLC is initialized (thanks media system) so we have to record
+ // it in mCurVolume and set it again here so that volume levels are correctly initialized
+ setVolume(mCurVolume);
+
+ setStatus(STATUS_LOADED);
+
+ libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
+ libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
+
+ // note this relies on the "set_loop" message arriving before the "start" (play) one
+ // but that appears to always be the case
+ if (mIsLooping)
+ {
+ libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1");
+ }
+
+ libvlc_media_player_play(mLibVLCMediaPlayer);
+
+ // send a "location_changed" message - this informs the media system
+ // that a new URL is the 'current' one and is used extensively.
+ // Again, this is really a browser message but we will use it here.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
+ message.setValue("uri", mURL);
+ sendMessage(message);
+
+ // Send a "navigate complete" event.
+ // This is really a browser message but the QuickTime plugin did it and
+ // the media system relies on this message to update internal state so we must send it too
+ // Note: see "navigate_begin" message above too
+ // https://jira.secondlife.com/browse/MAINT-6528
+ LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ message_complete.setValue("uri", mURL);
+ message_complete.setValueS32("result_code", 200);
+ message_complete.setValue("result_string", "OK");
+ sendMessage(message_complete);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::updateTitle(const char* title)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", title);
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::setVolume(const F64 volume)
+{
+ mCurVolume = volume;
+
+ if (mLibVLCMediaPlayer)
+ {
+ int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, (int)(volume * 100));
+ if (result != 0)
+ {
+ // volume wasn't set but not much to be done here
+ }
+ }
+ else
+ {
+ // volume change was requested but VLC wasn't ready.
+ // that's okay thought because we saved the value in mCurVolume and
+ // the next volume change after the VLC system is initilzied will set it
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::receiveMessage(const char* message_string)
+{
+ 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")
+ {
+ initVLC();
+
+ 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_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::ostringstream s;
+ s << "LibVLC plugin ";
+ s << LIBVLC_VERSION_MAJOR;
+ s << ".";
+ s << LIBVLC_VERSION_MINOR;
+ s << ".";
+ s << LIBVLC_VERSION_REVISION;
+
+ message.setValue("plugin_version", s.str());
+ sendMessage(message);
+ }
+ else if (message_name == "idle")
+ {
+ }
+ else if (message_name == "cleanup")
+ {
+ resetVLC();
+ }
+ 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)
+ {
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+ mLibVLCMediaPlayer = 0;
+
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+ //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if (message_name == "init")
+ {
+ 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_EXT);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else if (message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ if (!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if (iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ playMedia();
+ };
+ };
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+ }
+ else if (message_name == "load_uri")
+ {
+ mURL = message_in.getValue("uri");
+ playMedia();
+ }
+ }
+ else
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if (message_name == "stop")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "start")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_play(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "pause")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_pause(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "seek")
+ {
+ if (mDuration > 0)
+ {
+ F64 normalized_offset = message_in.getValueReal("time") / mDuration;
+ libvlc_media_player_set_position(mLibVLCMediaPlayer, normalized_offset);
+ }
+ }
+ else if (message_name == "set_loop")
+ {
+ mIsLooping = true;
+ }
+ else if (message_name == "set_volume")
+ {
+ // volume comes in 0 -> 1.0
+ F64 volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginLibVLC::init()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", "LibVLC 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)
+{
+ MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
index c5615145be..58391007ff 100644..100755
--- a/indra/media_plugins/quicktime/CMakeLists.txt
+++ b/indra/media_plugins/quicktime/CMakeLists.txt
@@ -14,7 +14,6 @@ include(PluginAPI)
include(MediaPluginBase)
include(OpenGL)
include(QuickTimePlugin)
-include(Boost)
include_directories(
${LLPLUGIN_INCLUDE_DIRS}
@@ -54,12 +53,17 @@ target_link_libraries(media_plugin_quicktime
${PLUGIN_API_WINDOWS_LIBRARIES}
)
+add_dependencies(media_plugin_quicktime
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
if (WINDOWS)
set_target_properties(
media_plugin_quicktime
PROPERTIES
- LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
- LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD"
+ LINK_FLAGS "/MANIFEST:NO"
)
endif (WINDOWS)
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index 7ef5a0fe44..b43598e4a5 100644..100755
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -837,9 +837,7 @@ 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;
@@ -921,6 +919,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
#endif
message.setValueS32("depth", mDepth);
message.setValueU32("internalformat", GL_RGB);
+
+ // note this apparently only has an effect when media is opened in 2D browser.
+ // see https://jira.secondlife.com/browse/BUG-18252 - media flipped in 2D so flipping it back.
message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
message.setValueBoolean("allow_downsample", true);
sendMessage(message);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index dce0ea73cd..b505bd3316 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1750,6 +1750,7 @@ if (WINDOWS)
SLPlugin
media_plugin_quicktime
media_plugin_cef
+ media_plugin_libvlc
winmm_shim
windows-crash-logger
)
@@ -1965,6 +1966,7 @@ if (LINUX)
linux-crash-logger
SLPlugin
media_plugin_gstreamer010
+ media_plugin_libvlc
llcommon
)
@@ -2072,7 +2074,7 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger)
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
if (ENABLE_SIGNING)
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index a2cec7aff4..627a3f43a6 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-4.0.8
+4.1.1
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index 92a5413adb..1dddf52961 100644
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -31,6 +31,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include "llexception.h"
+#include "stringize.h"
#include <algorithm>
#include <iterator>
@@ -154,13 +156,11 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
} while (false);
}
- catch (std::exception e)
- {
- LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << url << "')"));
+ throw;
}
mPendingObjectQuota.clear();
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index dbcae57de7..c1f898284a 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -30,6 +30,8 @@
#include "llappviewer.h"
#include "llviewercontrol.h"
+#include "llexception.h"
+#include "stringize.h"
#include <openssl/x509_vfy.h>
#include <openssl/ssl.h>
@@ -551,6 +553,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
}
catch (...)
{
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("('" << url << "')"));
// any other odd error, we just handle as a connect error.
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b8d511804d..d31008f1c4 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -125,7 +125,10 @@
#include "llexception.h"
#if !LL_LINUX
#include "cef/llceflib.h"
-#endif
+#if LL_WINDOWS
+#include "vlc/libvlc_version.h"
+#endif // LL_WINDOWS
+#endif // LL_LINUX
// Third party library includes
#include <boost/bind.hpp>
@@ -923,7 +926,7 @@ bool LLAppViewer::init()
// Provide the text fields with callbacks for opening Urls
LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
- LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
+ LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false));
LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
@@ -1538,10 +1541,14 @@ bool LLAppViewer::frame()
resumeMainloopTimeout();
pingMainloopTimeout("Main:End");
- }
+ }
+ }
+ catch (const LLContinueError&)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
}
catch(std::bad_alloc)
- {
+ {
LLMemory::logMemoryInfo(TRUE) ;
//stop memory leaking simulation
@@ -1549,7 +1556,7 @@ bool LLAppViewer::frame()
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
if(mem_leak_instance)
{
- mem_leak_instance->stop() ;
+ mem_leak_instance->stop() ;
LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
}
else
@@ -1560,6 +1567,10 @@ bool LLAppViewer::frame()
LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION("");
+ }
if (LLApp::isExiting())
{
@@ -1573,7 +1584,7 @@ bool LLAppViewer::frame()
catch(std::bad_alloc)
{
LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ;
-
+
//stop memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
@@ -1582,12 +1593,16 @@ bool LLAppViewer::frame()
mem_leak_instance->stop() ;
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()");
+ }
}
-
+
delete gServicePump;
-
+
destroyMainloopTimeout();
-
+
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
@@ -3315,6 +3330,19 @@ LLSD LLAppViewer::getViewerInfo() const
info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION;
#else
info["LLCEFLIB_VERSION"] = "Undefined";
+
+#endif
+
+#if LL_WINDOWS
+ std::ostringstream ver_codec;
+ ver_codec << LIBVLC_VERSION_MAJOR;
+ ver_codec << ".";
+ ver_codec << LIBVLC_VERSION_MINOR;
+ ver_codec << ".";
+ ver_codec << LIBVLC_VERSION_REVISION;
+ info["LIBVLC_VERSION"] = ver_codec.str();
+#else
+ info["LIBVLC_VERSION"] = "Undefined";
#endif
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
@@ -5519,7 +5547,7 @@ void LLAppViewer::forceErrorInfiniteLoop()
void LLAppViewer::forceErrorSoftwareException()
{
LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL;
- BOOST_THROW_EXCEPTION(LLException("User selected Force Software Exception"));
+ LLTHROW(LLException("User selected Force Software Exception"));
}
void LLAppViewer::forceErrorDriverCrash()
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index a7f248ab5a..af0cd27fd5 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -328,33 +328,33 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
// app cleanup if there was a problem.
//
#if WINDOWS_CRT_MEM_CHECKS
- LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
- if (!_CrtCheckMemory())
- {
- LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " No corruption detected." << LL_ENDL;
- }
+ LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
+ if (!_CrtCheckMemory())
+ {
+ LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " No corruption detected." << LL_ENDL;
+ }
#endif
-
- gGLActive = TRUE;
- viewer_app_ptr->cleanup();
-
+ gGLActive = TRUE;
+
+ viewer_app_ptr->cleanup();
+
#if WINDOWS_CRT_MEM_CHECKS
- LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
- if (!_CrtCheckMemory())
- {
- LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " No corruption detected." << LL_ENDL;
- }
+ LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
+ if (!_CrtCheckMemory())
+ {
+ LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " No corruption detected." << LL_ENDL;
+ }
#endif
-
+
}
delete viewer_app_ptr;
viewer_app_ptr = NULL;
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index 54f96b8872..90a5483dc9 100644
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -43,7 +43,6 @@
#include <boost/bind.hpp>
#include <boost/tokenizer.hpp>
#include <boost/assign/list_of.hpp>
-#include <boost/throw_exception.hpp>
#if _MSC_VER
# pragma warning(pop)
@@ -52,6 +51,7 @@
#include "llsdserialize.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
#include <string>
#include <set>
#include <iostream>
@@ -204,17 +204,17 @@ protected:
{
if(gPastLastOption)
{
- BOOST_THROW_EXCEPTION(LLCLPLastOption("Don't parse no more!"));
+ LLTHROW(LLCLPLastOption("Don't parse no more!"));
}
// Error checks. Needed?
if (!value_store.empty() && !is_composing())
{
- BOOST_THROW_EXCEPTION(LLCLPError("Non composing value with multiple occurences."));
+ LLTHROW(LLCLPError("Non composing value with multiple occurences."));
}
if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens())
{
- BOOST_THROW_EXCEPTION(LLCLPError("Illegal number of tokens specified."));
+ LLTHROW(LLCLPError("Illegal number of tokens specified."));
}
if(value_store.empty())
@@ -468,7 +468,7 @@ onevalue(const std::string& option,
{
// What does it mean when the user specifies a command-line switch
// that requires a value, but omits the value? Complain.
- BOOST_THROW_EXCEPTION(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));
+ LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));
}
else if (value.size() > 1)
{
@@ -486,10 +486,9 @@ void badvalue(const std::string& option,
// If the user passes an unusable value for a command-line switch, it
// seems like a really bad idea to just ignore it, even with a log
// warning.
- BOOST_THROW_EXCEPTION(
- LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
- << "' for variable '" << varname << "' of type " << type
- << ": '" << value << "'")));
+ LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
+ << "' for variable '" << varname << "' of type " << type
+ << ": '" << value << "'")));
}
template <typename T>
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 024e315632..dece3fc1ea 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -55,7 +55,8 @@ LLFloaterWebContent::_Params::_Params()
preferred_media_size("preferred_media_size"),
trusted_content("trusted_content", false),
show_page_title("show_page_title", true),
- clean_browser("clean_browser", false)
+ clean_browser("clean_browser", false),
+ dev_mode("dev_mode", false)
{}
LLFloaterWebContent::LLFloaterWebContent( const Params& params )
@@ -74,14 +75,16 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )
mShowPageTitle(params.show_page_title),
mAllowNavigation(true),
mCurrentURL(""),
- mDisplayURL("")
+ mDisplayURL(""),
+ mDevelopMode(params.dev_mode) // if called from "Develop" Menu, set a flag and change things to be more useful for devs
{
mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
- mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
+ mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind(&LLFloaterWebContent::onPopExternal, this));
+ mCommitCallbackRegistrar.add( "WebContent.TestURL", boost::bind(&LLFloaterWebContent::onTestURL, this, _2));
}
BOOL LLFloaterWebContent::postBuild()
@@ -195,8 +198,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
width + getRect().getWidth() - browser_rect.getWidth(),
height + getRect().getHeight() - browser_rect.getHeight());
- LL_DEBUGS() << "geometry change: " << geom << LL_ENDL;
-
LLRect new_rect;
getParent()->screenRectToLocal(geom, &new_rect);
setShape(new_rect);
@@ -205,8 +206,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
// static
void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
{
- LL_DEBUGS() << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << LL_ENDL;
-
if (!p.id.isProvided())
{
p.id = LLUUID::generateNewID().asString();
@@ -224,12 +223,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
// and close the least recently opened one if this will put us over the limit.
LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class);
- LL_DEBUGS() << "total instance count is " << instances.size() << LL_ENDL;
-
- for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
- {
- LL_DEBUGS() << " " << (*iter)->getKey()["target"] << LL_ENDL;
- }
if(instances.size() >= (size_t)browser_window_limit)
{
@@ -241,16 +234,19 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
void LLFloaterWebContent::open_media(const Params& p)
{
- // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
LLViewerMedia::proxyWindowOpened(p.target(), p.id());
- mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML);
+ mWebBrowser->setHomePageUrl(p.url);
mWebBrowser->setTarget(p.target);
- mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser);
+ mWebBrowser->navigateTo(p.url);
set_current_url(p.url);
getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);
getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome);
+
+ // turn additional debug controls on but only for Develop mode (Develop menu open)
+ getChild<LLLayoutPanel>("debug_controls")->setVisible(mDevelopMode);
+
bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;
mAllowNavigation = p.allow_back_forward_navigation;
getChildView("address")->setEnabled(address_entry_enabled);
@@ -499,7 +495,7 @@ void LLFloaterWebContent::onEnterAddress()
LLStringUtil::trim(url);
if ( url.length() > 0 )
{
- mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
+ mWebBrowser->navigateTo(url);
};
}
@@ -508,9 +504,18 @@ void LLFloaterWebContent::onPopExternal()
// make sure there is at least something there.
// (perhaps this test should be for minimum length of a URL)
std::string url = mAddressCombo->getValue().asString();
- LLStringUtil::trim(url);
- if ( url.length() > 0 )
+ LLStringUtil::trim(url);
+ if (url.length() > 0)
+ {
+ LLWeb::loadURLExternal(url);
+ };
+}
+
+void LLFloaterWebContent::onTestURL(std::string url)
+{
+ LLStringUtil::trim(url);
+ if (url.length() > 0)
{
- LLWeb::loadURLExternal( url );
+ mWebBrowser->navigateTo(url);
};
}
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index 4291fd9f2c..0bf93504c2 100644
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -58,7 +58,8 @@ public:
allow_back_forward_navigation,
trusted_content,
show_page_title,
- clean_browser;
+ clean_browser,
+ dev_mode;
Optional<LLRect> preferred_media_size;
_Params();
@@ -92,6 +93,7 @@ protected:
void onClickStop();
void onEnterAddress();
void onPopExternal();
+ void onTestURL(std::string url);
static void preCreate(Params& p);
void open_media(const Params& );
@@ -113,6 +115,7 @@ protected:
std::string mUUID;
bool mShowPageTitle;
bool mAllowNavigation;
+ bool mDevelopMode;
};
#endif // LL_LLFLOATERWEBCONTENT_H
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 763657ebad..0bcd8a9e63 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -95,7 +95,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mVolumeSliderVisible(0),
mWindowShade(NULL),
mHideImmediately(false),
- mSecureURL(false)
+ mSecureURL(false),
+ mMediaPlaySliderCtrlMouseDownValue(0.0)
{
mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
@@ -109,7 +110,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
- mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MouseDown", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MouseUp", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this));
@@ -1246,26 +1248,38 @@ void LLPanelPrimMediaControls::setCurrentURL()
#endif // USE_COMBO_BOX_FOR_MEDIA_URL
}
-void LLPanelPrimMediaControls::onCommitSlider()
+
+void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown()
{
- focusOnTarget();
+ mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal();
- LLViewerMediaImpl* media_impl = getTargetMediaImpl();
- if (media_impl)
+ mUpdateSlider = false;
+}
+
+void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp()
+{
+ F64 cur_value = mMediaPlaySliderCtrl->getValue().asReal();
+
+ if (mMediaPlaySliderCtrlMouseDownValue != cur_value)
{
- // get slider value
- F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal();
- if(slider_value <= 0.0)
- {
- media_impl->stop();
- }
- else
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
{
- media_impl->seek(slider_value*mMovieDuration);
- //mUpdateSlider= false;
+ if (cur_value <= 0.0)
+ {
+ media_impl->stop();
+ }
+ else
+ {
+ media_impl->seek(cur_value * mMovieDuration);
+ }
}
+
+ mUpdateSlider = true;
}
-}
+}
void LLPanelPrimMediaControls::onCommitVolumeUp()
{
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 6d2eb3430e..21d5236074 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -107,8 +107,10 @@ private:
void updateZoom();
void setCurrentURL();
- void onCommitSlider();
-
+
+ void onMediaPlaySliderCtrlMouseDown();
+ void onMediaPlaySliderCtrlMouseUp();
+
void onCommitVolumeUp();
void onCommitVolumeDown();
void onCommitVolumeSlider();
@@ -219,6 +221,8 @@ private:
S32 mVolumeSliderVisible;
LLNotificationPtr mActiveNotification;
+
+ F64 mMediaPlaySliderCtrlMouseDownValue;
};
#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index bcb9417820..72d7cf1e45 100644
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -29,7 +29,8 @@
#include "llviewerprecompiledheaders.h"
#include "llsecapi.h"
#include "llsechandler_basic.h"
-#include <boost/throw_exception.hpp>
+#include "llexception.h"
+#include "stringize.h"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <map>
@@ -70,7 +71,7 @@ void initializeSecHandler()
}
if (!exception_msg.empty()) // an exception was thrown.
{
- BOOST_THROW_EXCEPTION(LLProtectedDataException(exception_msg));
+ LLTHROW(LLProtectedDataException(exception_msg));
}
}
@@ -102,6 +103,7 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred)
LLSD LLCredential::getLoginParams()
{
LLSD result = LLSD::emptyMap();
+ std::string username;
try
{
if (mIdentifier["type"].asString() == "agent")
@@ -110,17 +112,19 @@ LLSD LLCredential::getLoginParams()
result["passwd"] = "$1$" + mAuthenticator["secret"].asString();
result["first"] = mIdentifier["first_name"];
result["last"] = mIdentifier["last_name"];
-
+ username = result["first"].asString() + " " + result["last"].asString();
}
else if (mIdentifier["type"].asString() == "account")
{
result["username"] = mIdentifier["account_name"];
result["passwd"] = mAuthenticator["secret"];
-
+ username = result["username"].asString();
}
}
catch (...)
{
+ // nat 2016-08-18: not clear what exceptions the above COULD throw?!
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("for '" << username << "'"));
// we could have corrupt data, so simply return a null login param if so
LL_WARNS("AppInit") << "Invalid credential" << LL_ENDL;
}
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 39ce64ad0e..d6fb801cc0 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -35,7 +35,8 @@
#include "llfile.h"
#include "lldir.h"
#include "llviewercontrol.h"
-#include <boost/throw_exception.hpp>
+#include "llexception.h"
+#include "stringize.h"
#include <vector>
#include <ios>
#include <openssl/ossl_typ.h>
@@ -73,14 +74,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert)
if(pem_bio == NULL)
{
LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
- BOOST_THROW_EXCEPTION(LLInvalidCertificate(this));
+ LLTHROW(LLInvalidCertificate(this));
}
mCert = NULL;
PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
BIO_free(pem_bio);
if (!mCert)
{
- BOOST_THROW_EXCEPTION(LLInvalidCertificate(this));
+ LLTHROW(LLInvalidCertificate(this));
}
}
@@ -89,7 +90,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert)
{
if (!pCert || !pCert->cert_info)
{
- BOOST_THROW_EXCEPTION(LLInvalidCertificate(this));
+ LLTHROW(LLInvalidCertificate(this));
}
mCert = X509_dup(pCert);
}
@@ -618,7 +619,7 @@ void LLBasicCertificateStore::load_from_file(const std::string& filename)
}
catch (...)
{
- LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file");
}
X509_free(cert_x509);
cert_x509 = NULL;
@@ -874,22 +875,22 @@ void _validateCert(int validation_policy,
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))
{
- BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have a Subject Name"));
+ LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name"));
}
if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))
{
- BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an Issuer Name"));
+ LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name"));
}
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))
{
- BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an expiration period"));
+ LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period"));
}
if (!current_cert_info.has(CERT_SHA1_DIGEST))
{
- BOOST_THROW_EXCEPTION(LLCertException(cert, "No SHA1 digest"));
+ LLTHROW(LLCertException(cert, "No SHA1 digest"));
}
if (validation_policy & VALIDATION_POLICY_TIME)
@@ -904,7 +905,7 @@ void _validateCert(int validation_policy,
if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||
(validation_date > current_cert_info[CERT_VALID_TO].asDate()))
{
- BOOST_THROW_EXCEPTION(LLCertValidationExpirationException(cert, validation_date));
+ LLTHROW(LLCertValidationExpirationException(cert, validation_date));
}
}
if (validation_policy & VALIDATION_POLICY_SSL_KU)
@@ -915,14 +916,14 @@ void _validateCert(int validation_policy,
!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
{
- BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert));
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
// only validate EKU if the cert has it
if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&
(!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
LLSD((std::string)CERT_EKU_SERVER_AUTH))))
{
- BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert));
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
}
if (validation_policy & VALIDATION_POLICY_CA_KU)
@@ -931,7 +932,7 @@ void _validateCert(int validation_policy,
(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
(std::string)CERT_KU_CERT_SIGN)))
{
- BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert));
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
}
@@ -943,13 +944,13 @@ void _validateCert(int validation_policy,
if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||
!current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])
{
- BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert));
+ LLTHROW(LLCertBasicConstraintsValidationException(cert));
}
if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&
((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&
(depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))
{
- BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert));
+ LLTHROW(LLCertBasicConstraintsValidationException(cert));
}
}
}
@@ -1019,7 +1020,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(cert_chain->size() < 1)
{
- BOOST_THROW_EXCEPTION(LLCertException(NULL, "No certs in chain"));
+ LLTHROW(LLCertException(NULL, "No certs in chain"));
}
iterator current_cert = cert_chain->begin();
LLSD current_cert_info;
@@ -1034,11 +1035,11 @@ void LLBasicCertificateStore::validate(int validation_policy,
(*current_cert)->getLLSD(current_cert_info);
if(!validation_params.has(CERT_HOSTNAME))
{
- BOOST_THROW_EXCEPTION(LLCertException((*current_cert), "No hostname passed in for validation"));
+ LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation"));
}
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))
{
- BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert)));
+ LLTHROW(LLInvalidCertificate((*current_cert)));
}
LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<
@@ -1055,7 +1056,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
X509* cert_x509 = (*current_cert)->getOpenSSLX509();
if(!cert_x509)
{
- BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert)));
+ LLTHROW(LLInvalidCertificate((*current_cert)));
}
std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
X509_free( cert_x509 );
@@ -1076,7 +1077,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if((validation_date < cache_entry->second.first) ||
(validation_date > cache_entry->second.second))
{
- BOOST_THROW_EXCEPTION(LLCertValidationExpirationException((*current_cert), validation_date));
+ LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));
}
}
// successfully found in cache
@@ -1108,7 +1109,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*current_cert),
previous_cert))
{
- BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(previous_cert));
+ LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));
}
}
_validateCert(local_validation_policy,
@@ -1157,7 +1158,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*found_store_cert),
(*current_cert)))
{
- BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(*current_cert));
+ LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));
}
// successfully validated.
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
@@ -1174,7 +1175,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if (validation_policy & VALIDATION_POLICY_TRUSTED)
{
// we reached the end without finding a trusted cert.
- BOOST_THROW_EXCEPTION(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));
+ LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));
}
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
@@ -1262,7 +1263,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
if (protected_data_stream.gcount() < STORE_SALT_SIZE)
{
- BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file too short."));
+ LLTHROW(LLProtectedDataException("Config file too short."));
}
cipher.decrypt(salt, STORE_SALT_SIZE);
@@ -1302,7 +1303,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
if (parser->parse(parse_stream, mProtectedDataMap,
LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
{
- BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file cannot be decrypted."));
+ LLTHROW(LLProtectedDataException("Config file cannot be decrypted."));
}
}
}
@@ -1365,7 +1366,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()
}
catch (...)
{
- LL_WARNS() << "LLProtectedDataException(Error writing Protected Data Store)" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION("LLProtectedDataException(Error writing Protected Data Store)");
// it's good practice to clean up any secure information on error
// (even though this file isn't really secure. Perhaps in the future
// it may be, however.
@@ -1373,39 +1374,39 @@ void LLSecAPIBasicHandler::_writeProtectedData()
// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
// Decided throwing an exception here was overkill until we figure out why this happens
- //BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store"));
+ //LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));
}
- try
- {
- // move the temporary file to the specified file location.
- if((( (LLFile::isfile(mProtectedDataFilename) != 0)
- && (LLFile::remove(mProtectedDataFilename) != 0)))
- || (LLFile::rename(tmp_filename, mProtectedDataFilename)))
- {
- LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL;
- LLFile::remove(tmp_filename);
+ try
+ {
+ // move the temporary file to the specified file location.
+ if((( (LLFile::isfile(mProtectedDataFilename) != 0)
+ && (LLFile::remove(mProtectedDataFilename) != 0)))
+ || (LLFile::rename(tmp_filename, mProtectedDataFilename)))
+ {
+ LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL;
+ LLFile::remove(tmp_filename);
- // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
- // Decided throwing an exception here was overkill until we figure out why this happens
- //BOOST_THROW_EXCEPTION(LLProtectedDataException("Could not overwrite protected data store"));
- }
+ // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
+ // Decided throwing an exception here was overkill until we figure out why this happens
+ //LLTHROW(LLProtectedDataException("Could not overwrite protected data store"));
+ }
}
catch (...)
{
- LL_WARNS() << "LLProtectedDataException(Error renaming '" << tmp_filename
- << "' to '" << mProtectedDataFilename << "')" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("renaming '" << tmp_filename << "' to '"
+ << mProtectedDataFilename << "'"));
// it's good practice to clean up any secure information on error
// (even though this file isn't really secure. Perhaps in the future
- // it may be, however.
+ // it may be, however).
LLFile::remove(tmp_filename);
//crash in LLSecAPIBasicHandler::_writeProtectedData()
// Decided throwing an exception here was overkill until we figure out why this happens
- //BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store"));
+ //LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));
}
}
-
+
// instantiate a certificate from a pem string
LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert)
{
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 2d06b8599c..d28a7cc048 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -230,8 +230,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f);
F32 vec[3] = {
- fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
- fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
+ (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
+ (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
0.f
};
F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index f5b06fbd19..697199df6b 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7906,7 +7906,7 @@ void handle_web_browser_test(const LLSD& param)
void handle_web_content_test(const LLSD& param)
{
std::string url = param.asString();
- LLWeb::loadURLInternal(url);
+ LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true);
}
void handle_show_url(const LLSD& param)
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index b37e41fb85..8026dc3ea8 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -104,10 +104,10 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std
// static
// Explicitly open a Web URL using the Web content floater
-void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
+void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode)
{
LLFloaterWebContent::Params p;
- p.url(url).target(target).id(uuid);
+ p.url(url).target(target).id(uuid).dev_mode(dev_mode);
LLFloaterReg::showInstance("web_content", p);
}
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 7c90badbfe..7149ce9baf 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -57,7 +57,7 @@ public:
static void loadURL(const std::string& url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);
// load content using built-in browser
- static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);
+ static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null, bool dev_mode = false);
/// Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 11d3706821..cee47a591e 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -957,10 +957,10 @@ void LLWorld::updateWaterObjects()
center_y = min_y + (wy >> 1);
S32 add_boundary[4] = {
- 512 - (max_x - region_x),
- 512 - (max_y - region_y),
- 512 - (region_x - min_x),
- 512 - (region_y - min_y) };
+ (S32)(512 - (max_x - region_x)),
+ (S32)(512 - (max_y - region_y)),
+ (S32)(512 - (region_x - min_x)),
+ (S32)(512 - (region_y - min_y)) };
S32 dir;
for (dir = 0; dir < 8; dir++)
diff --git a/indra/newview/skins/default/textures/icons/Video_URL_Off.png b/indra/newview/skins/default/textures/icons/Video_URL_Off.png
new file mode 100644
index 0000000000..40e5df7d81
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Video_URL_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 72037a84b3..01e8c16937 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -676,7 +676,10 @@ with the same filename but different name
<texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" />
<texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" />
- <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
+
+ <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" />
+
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
<texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
index a80440e844..4473ce0cda 100644
--- a/indra/newview/skins/default/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -154,6 +154,136 @@
</button>
</layout_panel>
<layout_panel
+ height="22"
+ layout="topleft"
+ left_delta="0"
+ name="debug_controls"
+ top_delta="0"
+ auto_resize="false"
+ width="585">
+ <button
+ image_overlay="Home_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Web tests home page"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="1"
+ name="web_test_home_page"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ </button>
+
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MPEG4 Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="27"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MKV Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="WebM Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="75"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MP3 audio Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="99"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="FLV Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="123"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/>
+ </button>
+ </layout_panel>
+ <layout_panel
height="40"
layout="topleft"
left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index dcf2da52f1..a39ee5fddd 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -225,11 +225,11 @@
parameter="message_critical" />
</menu_item_call>
<menu_item_call
- label="Web Content Floater Debug Test"
- name="Web Content Floater Debug Test">
+ label="Media Browser"
+ name="Media Browser">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ parameter="http://google.com"/>
</menu_item_call>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b189d1038f..8a649a57d1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3141,30 +3141,13 @@
label="UI"
name="UI"
tear_off="true">
- <!-- <menu_item_check
- label="New Bottom Bar"
- name="New Bottom Bar">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="BottomPanelNew" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="BottomPanelNew" />
- </menu_item_check>-->
- <menu_item_call
- label="Media Browser Test"
- name="Web Browser Test">
- <menu_item_call.on_click
- function="Advanced.WebBrowserTest"
- parameter="http://secondlife.com/app/search/slurls.html"/>
- </menu_item_call>
<menu_item_call
- label="Web Content Browser"
- name="Web Content Browser"
- shortcut="control|shift|Z">
+ label="Media Browser"
+ name="Media Browser"
+ shortcut="control|alt|shift|Z">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ parameter="http://google.com"/>
</menu_item_call>
<menu_item_call
label="FB Connect Test"
diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml
index 7cb4a6e53b..c27fac6731 100644
--- a/indra/newview/skins/default/xui/en/mime_types.xml
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -130,10 +130,21 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</scheme>
- <mimetype name="blank">
+ <scheme name="libvlc">
+ <label name="libvlc_label">
+ LibVLC supported media
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_libvlc
+ </impl>
+ </scheme>
+ <mimetype name="blank">
<label name="blank_label">
- None -
</label>
@@ -163,7 +174,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/*">
@@ -174,7 +185,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="image/*">
@@ -196,7 +207,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/javascript">
@@ -218,7 +229,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/pdf">
@@ -295,7 +306,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@@ -306,7 +317,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@@ -317,7 +328,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@@ -328,7 +339,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@@ -438,7 +449,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/mp4">
@@ -449,10 +460,21 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
- <mimetype menu="1" name="video/quicktime">
+ <mimetype name="application/octet-stream">
+ <label name="video/octet-stream">
+ Movie
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_libvlc
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/quicktime">
<label name="video/quicktime_label">
Movie (QuickTime)
</label>
@@ -460,7 +482,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@@ -471,7 +493,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@@ -482,7 +504,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +515,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml
index 84aeaf3b54..7188b1e699 100644
--- a/indra/newview/skins/default/xui/en/mime_types_linux.xml
+++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml
@@ -130,7 +130,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</scheme>
<mimetype name="blank">
@@ -163,7 +163,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/*">
@@ -174,7 +174,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="image/*">
@@ -196,7 +196,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/javascript">
@@ -218,7 +218,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/pdf">
@@ -295,7 +295,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@@ -306,7 +306,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@@ -317,7 +317,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@@ -328,7 +328,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@@ -438,7 +438,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/mp4">
@@ -449,7 +449,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="video/quicktime">
@@ -460,7 +460,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@@ -471,7 +471,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@@ -482,7 +482,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +493,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
index eb67d07601..068e4420bc 100644
--- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -374,9 +374,11 @@
layout="topleft"
tool_tip="Movie play progress"
width="200">
- <slider_bar.commit_callback
- function="MediaCtrl.JumpProgress" />
- </slider_bar>
+ <slider_bar.mouse_down_callback
+ function="MediaCtrl.MouseDown" />
+ <slider_bar.mouse_up_callback
+ function="MediaCtrl.MouseUp" />
+ </slider_bar>
</layout_panel>
<layout_panel
name="skip_back"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b19c6756bc..0a17c202c3 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -51,13 +51,14 @@ OpenGL Version: [OPENGL_VERSION]
J2C Decoder Version: [J2C_VERSION]
Audio Driver Version: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF Version: [LLCEFLIB_VERSION]
+LibVLC Version: [LIBVLC_VERSION]
Voice Server Version: [VOICE_VERSION]
</string>
<string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string>
<string name="AboutTime">[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second,datetime,slt]</string>
<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>
<string name="BuildConfiguration">Build Configuration</string>
-
+
<!-- progress -->
<string name="ProgressRestoring">Restoring...</string>
<string name="ProgressChangingResolution">Changing resolution...</string>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f3d89bb866..66d730d1ac 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -444,6 +444,11 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("media_plugin_cef.dll")
self.end_prefix()
+ # Media plugins - LibVLC
+ if self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"):
+ self.path("media_plugin_libvlc.dll")
+ self.end_prefix()
+
# winmm.dll shim
if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
self.path("winmm.dll")
@@ -550,6 +555,12 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("zh-TW.pak")
self.end_prefix()
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"):
+ self.path("libvlc.dll")
+ self.path("libvlccore.dll")
+ self.path("plugins/")
+ self.end_prefix()
+
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
@@ -1089,8 +1100,18 @@ class LinuxManifest(ViewerManifest):
# plugins
if self.prefix(src="", dst="bin/llplugin"):
self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
+ self.path("../media_plugins/libvlc/libmedia_plugin_libvlc.so", "libmedia_plugin_libvlc.so")
self.end_prefix("bin/llplugin")
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"):
+ self.path( "plugins.dat" )
+ self.path( "*/*.so" )
+ self.end_prefix()
+
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib' ), dst="lib"):
+ self.path( "libvlc*.so*" )
+ self.end_prefix()
+
# llcommon
if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"):
print "Skipping llcommon.so (assuming llcommon was linked statically)"
@@ -1144,7 +1165,7 @@ class LinuxManifest(ViewerManifest):
def strip_binaries(self):
if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
- self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
+ self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
class Linux_i686_Manifest(LinuxManifest):
def construct(self):
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 53d4acc9e0..c767d52c7b 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -42,6 +42,8 @@
#include "llevents.h"
#include "lleventfilter.h"
#include "lleventcoro.h"
+#include "llexception.h"
+#include "stringize.h"
//*********************
// LLLogin
@@ -128,30 +130,23 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
{
- try
- {
- LLSD printable_params = login_params;
- //if(printable_params.has("params")
- // && printable_params["params"].has("passwd"))
- //{
- // printable_params["params"]["passwd"] = "*******";
- //}
- LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
+ LLSD printable_params = login_params;
+ if (printable_params.has("params")
+ && printable_params["params"].has("passwd"))
+ {
+ printable_params["params"]["passwd"] = "*******";
+ }
+ try
+ {
+ LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
<< " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
- // Arriving in SRVRequest state
- LLEventStream replyPump("SRVreply", true);
- // Should be an array of one or more uri strings.
-
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
// EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
// to share them -- but the EXT-3934 fix made it possible for an abandoned
// SRV response to arrive just as we were expecting the XMLRPC response.
LLEventStream loginReplyPump("loginreply", true);
- // Loop through the rewrittenURIs, counting attempts along the way.
- // Because of possible redirect responses, we may make more than one
- // attempt per rewrittenURIs entry.
LLSD::Integer attempts = 0;
LLSD request(login_params);
@@ -167,11 +162,11 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
LLSD progress_data;
progress_data["attempt"] = attempts;
progress_data["request"] = request;
- if(progress_data["request"].has("params")
- && progress_data["request"]["params"].has("passwd"))
- {
- progress_data["request"]["params"]["passwd"] = "*******";
- }
+ if (progress_data["request"].has("params")
+ && progress_data["request"]["params"].has("passwd"))
+ {
+ progress_data["request"]["params"]["passwd"] = "*******";
+ }
sendProgressEvent("offline", "authenticating", progress_data);
// We expect zero or more "Downloading" status events, followed by
@@ -189,8 +184,8 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
// Still Downloading -- send progress update.
sendProgressEvent("offline", "downloading");
}
-
- LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
+
+ LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
status = mAuthResponse["status"].asString();
// Okay, we've received our final status event for this
@@ -202,7 +197,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
break;
}
- sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
+ sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
// Here the login service at the current URI is redirecting us
// to some other URI ("indeterminate" -- why not "redirect"?).
@@ -212,8 +207,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
request["method"] = mAuthResponse["responses"]["next_method"].asString();
} // loop back to try the redirected URI
- // Here we're done with redirects for the current rewrittenURIs
- // entry.
+ // Here we're done with redirects.
if (status == "Complete")
{
// StatusComplete does not imply auth success. Check the
@@ -230,14 +224,14 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
return; // Done!
}
-// /* Sometimes we end with "Started" here. Slightly slow server?
-// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
-// */
-// if( status == "Started")
-// {
-// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
-// continue;
-// }
+// /* Sometimes we end with "Started" here. Slightly slow server?
+// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
+// */
+// if( status == "Started")
+// {
+// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
+// continue;
+// }
// If we don't recognize status at all, trouble
if (! (status == "CURLError"
@@ -250,27 +244,25 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
}
// Here status IS one of the errors tested above.
-
- // Here we got through all the rewrittenURIs without succeeding. Tell
- // caller this didn't work out so well. Of course, the only failure data
- // we can reasonably show are from the last of the rewrittenURIs.
-
- // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
- // llsd with no "responses" node. To make the output from an incomplete login symmetrical
- // to success, add a data/message and data/reason fields.
- LLSD error_response;
- error_response["reason"] = mAuthResponse["status"];
- error_response["errorcode"] = mAuthResponse["errorcode"];
- error_response["message"] = mAuthResponse["error"];
- if(mAuthResponse.has("certificate"))
- {
- error_response["certificate"] = mAuthResponse["certificate"];
- }
- sendProgressEvent("offline", "fail.login", error_response);
- }
- catch (...) {
- LL_ERRS() << "login exception caught" << LL_ENDL;
- }
+ // Tell caller this didn't work out so well.
+
+ // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
+ // llsd with no "responses" node. To make the output from an incomplete login symmetrical
+ // to success, add a data/message and data/reason fields.
+ LLSD error_response;
+ error_response["reason"] = mAuthResponse["status"];
+ error_response["errorcode"] = mAuthResponse["errorcode"];
+ error_response["message"] = mAuthResponse["error"];
+ if(mAuthResponse.has("certificate"))
+ {
+ error_response["certificate"] = mAuthResponse["certificate"];
+ }
+ sendProgressEvent("offline", "fail.login", error_response);
+ }
+ catch (...) {
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << uri << "', " << printable_params << ")"));
+ }
}
void LLLogin::Impl::disconnect()
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index cd4b108c1a..04e0395c50 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -30,7 +30,6 @@
#include "llexception.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/throw_exception.hpp>
#include <curl/curl.h>
#include "lldir.h"
#include "llevents.h"
@@ -468,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
if(!mCurl)
{
- BOOST_THROW_EXCEPTION(DownloadError("failed to initialize curl"));
+ LLTHROW(DownloadError("failed to initialize curl"));
}
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true));
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true));
@@ -509,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
if(mHeaderList == 0)
{
- BOOST_THROW_EXCEPTION(DownloadError("cannot add Range header"));
+ LLTHROW(DownloadError("cannot add Range header"));
}
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList));
@@ -525,7 +524,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std
mDownloadData["hash"] = hash;
mDownloadData["current_version"] = ll_get_version();
LLSD path = uri.pathArray();
- if(path.size() == 0) BOOST_THROW_EXCEPTION(DownloadError("no file path"));
+ if(path.size() == 0) LLTHROW(DownloadError("no file path"));
std::string fileName = path[path.size() - 1].asString();
std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);
mDownloadData["path"] = filePath;
@@ -548,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
if(code != CURLE_OK) {
const char * errorString = curl_easy_strerror(code);
if(errorString != 0) {
- BOOST_THROW_EXCEPTION(DownloadError(curl_easy_strerror(code)));
+ LLTHROW(DownloadError(curl_easy_strerror(code)));
} else {
- BOOST_THROW_EXCEPTION(DownloadError("unknown curl error"));
+ LLTHROW(DownloadError("unknown curl error"));
}
} else {
; // No op.
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index 9f9a08f590..1c7629da23 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -36,7 +36,6 @@
#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!).
#endif
#include <boost/lexical_cast.hpp>
-#include <boost/throw_exception.hpp>
namespace {
struct RelocateError: public LLException
@@ -49,7 +48,7 @@ namespace {
std::string scriptFile = gDirUtilp->getBaseFileName(path);
std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
- if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(RelocateError());
+ if(status != APR_SUCCESS) LLTHROW(RelocateError());
return newPath;
}
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 0bdd1ede43..1665e41e70 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -32,10 +32,10 @@
#include "lltimer.h"
#include "llupdatechecker.h"
#include "llupdateinstaller.h"
+#include "llexception.h"
#include <boost/scoped_ptr.hpp>
#include <boost/weak_ptr.hpp>
-#include <boost/throw_exception.hpp>
#include "lldir.h"
#include "llsdserialize.h"
#include "llfile.h"
@@ -191,9 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string& channel,
{
if(mIsChecking || mIsDownloading)
{
- BOOST_THROW_EXCEPTION(
- LLUpdaterService::UsageError("LLUpdaterService::initialize call "
- "while updater is running."));
+ LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call "
+ "while updater is running."));
}
mChannel = channel;
@@ -224,9 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
{
if(mChannel.empty() || mVersion.empty())
{
- BOOST_THROW_EXCEPTION(
- LLUpdaterService::UsageError("Set params before call to "
- "LLUpdaterService::startCheck()."));
+ LLTHROW(LLUpdaterService::UsageError("Set params before call to "
+ "LLUpdaterService::startCheck()."));
}
mIsChecking = true;