merge
commit
0200135224
1
.hgtags
1
.hgtags
|
|
@ -519,3 +519,4 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
|
|||
4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release
|
||||
33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
|
||||
45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release
|
||||
b280a1c797a3891e68dbc237e73de9cf19f426e9 4.1.1-release
|
||||
|
|
|
|||
|
|
@ -1454,9 +1454,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>faa1e5b7cf70c143caabe190fa5588ce</string>
|
||||
<string>fddd634dec5ec03924d62cc774f7f8ea</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/304432/arch/Linux/installer/llappearance_utility-0.0.1-linux-304432.tar.bz2</string>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_viewer-llappearance-utility/rev/317266/arch/Linux/installer/llappearance_utility-0.0.1-linux-317266.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
|
|
@ -1484,11 +1484,11 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>29a1f64df46094eda0d681821a98d17e</string>
|
||||
<string>db992d58c46c80df7d4d31f8a4784b98</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/Darwin/installer/llceflib-1.5.3.311349-darwin-311349.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/Darwin/installer/llceflib-1.5.3.317959-darwin-317959.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin</string>
|
||||
|
|
@ -1498,18 +1498,18 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>827b7c339a2cd401d9d23f9ee02cb83f</string>
|
||||
<string>bb3818628131a99cd789febfad9dc2c2</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/CYGWIN/installer/llceflib-1.5.3.311349-windows-311349.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/CYGWIN/installer/llceflib-1.5.3.317959-windows-317959.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.5.3.311349</string>
|
||||
<string>1.5.3.317959</string>
|
||||
</map>
|
||||
<key>llphysicsextensions_source</key>
|
||||
<map>
|
||||
|
|
@ -2135,6 +2135,46 @@
|
|||
<key>version</key>
|
||||
<string>0.8.0.1</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string>
|
||||
<key>license</key>
|
||||
<string>GPL2</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/vlc.txt</string>
|
||||
<key>name</key>
|
||||
<string>vlc-bin</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2f410640df3f9812d1abff02a414cfa8</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>04cff37070a5f65f3652b4ddcec7183f</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/317935/arch/CYGWIN/installer/vlc_bin-2.2.4.317935-windows-317935.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.2.4.317935</string>
|
||||
</map>
|
||||
<key>xmlrpc-epi</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
2014-02-25 10:34
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
app.mainLoop();
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
|
|||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerLinux::mainLoop()
|
||||
bool LLCrashLoggerLinux::frame()
|
||||
{
|
||||
bool send_logs = true;
|
||||
if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger
|
|||
public:
|
||||
LLCrashLoggerLinux(void);
|
||||
~LLCrashLoggerLinux(void);
|
||||
virtual bool mainLoop();
|
||||
virtual bool frame();
|
||||
virtual void updateApplication(const std::string& = LLStringUtil::null);
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
virtual bool cleanup();
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ set(llcommon_SOURCE_FILES
|
|||
lleventfilter.cpp
|
||||
llevents.cpp
|
||||
lleventtimer.cpp
|
||||
llexception.cpp
|
||||
llfasttimer.cpp
|
||||
llfile.cpp
|
||||
llfindlocale.cpp
|
||||
|
|
@ -160,6 +161,7 @@ set(llcommon_HEADER_FILES
|
|||
lleventfilter.h
|
||||
llevents.h
|
||||
lleventemitter.h
|
||||
llexception.h
|
||||
llfasttimer.h
|
||||
llfile.h
|
||||
llfindlocale.h
|
||||
|
|
@ -319,7 +321,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}")
|
||||
|
|
@ -332,6 +334,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)
|
||||
|
|
|
|||
|
|
@ -172,12 +172,12 @@ public:
|
|||
virtual bool cleanup() = 0; // Override to do application cleanup
|
||||
|
||||
//
|
||||
// mainLoop()
|
||||
// frame()
|
||||
//
|
||||
// Runs the application main loop. It's assumed that when you exit
|
||||
// this method, the application is in one of the cleanup states, either QUITTING or ERROR
|
||||
// Pass control to the application for a single frame. Returns 'done'
|
||||
// flag: if frame() returns false, it expects to be called again.
|
||||
//
|
||||
virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
|
||||
virtual bool frame() = 0; // Override for application body logic
|
||||
|
||||
//
|
||||
// Crash logging
|
||||
|
|
|
|||
|
|
@ -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*) {}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <boost/graph/topological_sort.hpp>
|
||||
#include <boost/graph/exception.hpp>
|
||||
// other Linden headers
|
||||
#include "llexception.h"
|
||||
|
||||
LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
|
||||
{
|
||||
|
|
@ -76,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);
|
||||
throw 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
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@
|
|||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <iosfwd>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include "llexception.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Utilities
|
||||
|
|
@ -106,9 +106,9 @@ public:
|
|||
/**
|
||||
* Exception thrown by sort() if there's a cycle
|
||||
*/
|
||||
struct Cycle: public std::runtime_error
|
||||
struct Cycle: public LLException
|
||||
{
|
||||
Cycle(const std::string& what): std::runtime_error(what) {}
|
||||
Cycle(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// 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.
|
||||
|
||||
#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(); \
|
||||
// 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,6 +378,48 @@ 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_()
|
||||
|
||||
// Check at run-time whether logging is enabled, without generating output
|
||||
bool debugLoggingEnabled(const std::string& tag);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "llerror.h"
|
||||
#include "llcoros.h"
|
||||
#include "llmake.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include "lleventfilter.h"
|
||||
|
||||
|
|
@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)
|
|||
// returning it, deliver it via exception.
|
||||
if (result.second)
|
||||
{
|
||||
throw 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).
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@
|
|||
|
||||
#include <boost/optional.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <utility> // std::pair
|
||||
#include "llevents.h"
|
||||
#include "llerror.h"
|
||||
#include "llexception.h"
|
||||
|
||||
/**
|
||||
* Like LLListenerOrPumpName, this is a class intended for parameter lists:
|
||||
|
|
@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc);
|
|||
* because it's not an error in event processing: rather, this exception
|
||||
* announces an event that bears error information (for some other API).
|
||||
*/
|
||||
class LL_COMMON_API LLErrorEvent: public std::runtime_error
|
||||
class LL_COMMON_API LLErrorEvent: public LLException
|
||||
{
|
||||
public:
|
||||
LLErrorEvent(const std::string& what, const LLSD& data):
|
||||
std::runtime_error(what),
|
||||
LLException(what),
|
||||
mData(data)
|
||||
{}
|
||||
virtual ~LLErrorEvent() throw() {}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#include "stringize.h"
|
||||
#include "llerror.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llexception.h"
|
||||
#if LL_MSVC
|
||||
#pragma warning (disable : 4702)
|
||||
#endif
|
||||
|
|
@ -174,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)
|
||||
{
|
||||
throw 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
|
||||
|
|
@ -326,8 +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())
|
||||
{
|
||||
throw 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
|
||||
|
|
@ -353,8 +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);
|
||||
throw 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;
|
||||
|
|
@ -418,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.
|
||||
throw OrderChange(out.str());
|
||||
LLTHROW(OrderChange(out.str()));
|
||||
}
|
||||
// This node becomes the previous one.
|
||||
previous = dmi->second;
|
||||
|
|
@ -608,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
|
|||
{
|
||||
if (! mListener)
|
||||
{
|
||||
throw Empty("attempting to call uninitialized");
|
||||
LLTHROW(Empty("attempting to call uninitialized"));
|
||||
}
|
||||
return (*mListener)(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <set>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <stdexcept>
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
|
||||
|
|
@ -62,6 +61,7 @@
|
|||
#include "llsingleton.h"
|
||||
#include "lldependencies.h"
|
||||
#include "llstl.h"
|
||||
#include "llexception.h"
|
||||
|
||||
/*==========================================================================*|
|
||||
// override this to allow binding free functions with more parameters
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
@ -188,10 +208,10 @@ public:
|
|||
bool operator()(const LLSD& event) const;
|
||||
|
||||
/// exception if you try to call when empty
|
||||
struct Empty: public std::runtime_error
|
||||
struct Empty: public LLException
|
||||
{
|
||||
Empty(const std::string& what):
|
||||
std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
|
||||
LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -371,10 +391,10 @@ public:
|
|||
* you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
|
||||
* variant.
|
||||
*/
|
||||
struct DupPumpName: public std::runtime_error
|
||||
struct DupPumpName: public LLException
|
||||
{
|
||||
DupPumpName(const std::string& what):
|
||||
std::runtime_error(std::string("DupPumpName: ") + what) {}
|
||||
LLException(std::string("DupPumpName: ") + what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -399,9 +419,9 @@ public:
|
|||
/// group exceptions thrown by listen(). We use exceptions because these
|
||||
/// particular errors are likely to be coding errors, found and fixed by
|
||||
/// the developer even before preliminary checkin.
|
||||
struct ListenError: public std::runtime_error
|
||||
struct ListenError: public LLException
|
||||
{
|
||||
ListenError(const std::string& what): std::runtime_error(what) {}
|
||||
ListenError(const std::string& what): LLException(what) {}
|
||||
};
|
||||
/**
|
||||
* exception thrown by listen(). You are attempting to register a
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @file llexception.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2016-06-29
|
||||
* @brief Types needed for generic exception handling
|
||||
*
|
||||
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
* Copyright (c) 2016, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_LLEXCEPTION_H)
|
||||
#define LL_LLEXCEPTION_H
|
||||
|
||||
#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. Rationale for why it's derived from
|
||||
* both std::exception and boost::exception is explained in
|
||||
* tests/llexception_test.cpp.
|
||||
*
|
||||
* 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
|
||||
* (say) a third-party library. Catching (const LLException&) supports such
|
||||
* usage. However, most of the value of this base class is in the
|
||||
* diagnostic_information() available via Boost.Exception.
|
||||
*/
|
||||
struct LLException:
|
||||
public std::runtime_error,
|
||||
public boost::exception
|
||||
{
|
||||
LLException(const std::string& what):
|
||||
std::runtime_error(what)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* The point of LLContinueError is to distinguish exceptions that need not
|
||||
* terminate the whole viewer session. In general, an uncaught exception will
|
||||
* be logged and will crash the viewer. However, though an uncaught exception
|
||||
* derived from LLContinueError will still be logged, the viewer will attempt
|
||||
* to continue processing.
|
||||
*/
|
||||
struct LLContinueError: public LLException
|
||||
{
|
||||
LLContinueError(const std::string& what):
|
||||
LLException(what)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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) */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -28,8 +28,11 @@
|
|||
#define LLHANDLE_H
|
||||
|
||||
#include "llpointer.h"
|
||||
#include "llexception.h"
|
||||
#include <stdexcept>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
/**
|
||||
* Helper object for LLHandle. Don't instantiate these directly, used
|
||||
|
|
@ -213,4 +216,82 @@ private:
|
|||
mutable LLRootHandle<T> mHandle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class LLCheckedHandleBase
|
||||
{
|
||||
public:
|
||||
class Stale : public LLException
|
||||
{
|
||||
public:
|
||||
Stale() :
|
||||
LLException("Attempt to access stale handle.")
|
||||
{}
|
||||
};
|
||||
|
||||
protected:
|
||||
LLCheckedHandleBase() { }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a simple wrapper for Handles, allowing direct calls to the underlying
|
||||
* pointer. The checked handle will throw a Stale if an attempt
|
||||
* is made to access the object referenced by the handle and that object has
|
||||
* been destroyed.
|
||||
**/
|
||||
template <typename T>
|
||||
class LLCheckedHandle: public LLCheckedHandleBase
|
||||
{
|
||||
public:
|
||||
|
||||
LLCheckedHandle(LLHandle<T> handle):
|
||||
mHandle(handle)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Test the underlying handle. If it is no longer valid, throw a Stale exception.
|
||||
*/
|
||||
void check() const
|
||||
{
|
||||
T* ptr = mHandle.get();
|
||||
if (!ptr)
|
||||
BOOST_THROW_EXCEPTION(Stale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast back to an appropriate handle
|
||||
*/
|
||||
operator LLHandle<T>() const
|
||||
{
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the LLCheckedHandle to a bool. Allows for if (chkdHandle) {}
|
||||
* Does not throw.
|
||||
*/
|
||||
/*explicit*/ operator bool() const // explicit conversion operator not available with Linux compiler
|
||||
{
|
||||
return (mHandle.get() != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to call a method or access a member in the structure referenced
|
||||
* by the handle. If the handle no longer points to a valid structure
|
||||
* throw a Stale.
|
||||
*/
|
||||
T* operator ->() const
|
||||
{
|
||||
T* ptr = mHandle.get();
|
||||
if (!ptr)
|
||||
BOOST_THROW_EXCEPTION(Stale());
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
LLHandle<T> mHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,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
|
||||
|
|
@ -69,7 +70,7 @@ public:
|
|||
// Rule out empty vector
|
||||
if (plugin.empty())
|
||||
{
|
||||
throw Error("no plugin command");
|
||||
LLTHROW(Error("no plugin command"));
|
||||
}
|
||||
|
||||
// Don't leave desc empty either, but in this case, if we weren't
|
||||
|
|
@ -112,7 +113,7 @@ public:
|
|||
// If that didn't work, no point in keeping this LLLeap object.
|
||||
if (! mChild)
|
||||
{
|
||||
throw Error(STRINGIZE("failed to run " << mDesc));
|
||||
LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));
|
||||
}
|
||||
|
||||
// Okay, launch apparently worked. Change our mDonePump listener.
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
#define LL_LLLEAP_H
|
||||
|
||||
#include "llinstancetracker.h"
|
||||
#include "llexception.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
/**
|
||||
* LLSD Event API Plugin class. Because instances are managed by
|
||||
|
|
@ -67,9 +67,9 @@ public:
|
|||
* string(s) passed to create() might come from an external source. This
|
||||
* way the caller can catch LLLeap::Error and try to recover.
|
||||
*/
|
||||
struct Error: public std::runtime_error
|
||||
struct Error: public LLException
|
||||
{
|
||||
Error(const std::string& what): std::runtime_error(what) {}
|
||||
Error(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
virtual ~LLLeap();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llapr.h"
|
||||
#include "apr_signal.h"
|
||||
#include "llevents.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
|
@ -472,9 +473,9 @@ private:
|
|||
*****************************************************************************/
|
||||
/// Need an exception to avoid constructing an invalid LLProcess object, but
|
||||
/// internal use only
|
||||
struct LLProcessError: public std::runtime_error
|
||||
struct LLProcessError: public LLException
|
||||
{
|
||||
LLProcessError(const std::string& msg): std::runtime_error(msg) {}
|
||||
LLProcessError(const std::string& msg): LLException(msg) {}
|
||||
};
|
||||
|
||||
LLProcessPtr LLProcess::create(const LLSDOrParams& params)
|
||||
|
|
@ -530,8 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
|
||||
if (! params.validateBlock(true))
|
||||
{
|
||||
throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
|
||||
<< LLSDNotationStreamer(params)));
|
||||
LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
|
||||
<< LLSDNotationStreamer(params))));
|
||||
}
|
||||
|
||||
mPostend = params.postend;
|
||||
|
|
@ -596,10 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
}
|
||||
else
|
||||
{
|
||||
throw 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.
|
||||
|
|
@ -678,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
|
||||
gAPRPoolp)))
|
||||
{
|
||||
throw LLProcessError(STRINGIZE(params << " failed"));
|
||||
LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
|
||||
}
|
||||
|
||||
// arrange to call status_callback()
|
||||
|
|
@ -1063,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)
|
|||
PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
|
||||
if (! wp)
|
||||
{
|
||||
throw NoPipe(error);
|
||||
LLTHROW(NoPipe(error));
|
||||
}
|
||||
return *wp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@
|
|||
#include "llinitparam.h"
|
||||
#include "llsdparam.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llexception.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <iosfwd> // std::ostream
|
||||
#include <stdexcept>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h" // for HANDLE
|
||||
|
|
@ -479,9 +479,9 @@ public:
|
|||
|
||||
/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
|
||||
/// create a pipe at the corresponding FILESLOT.
|
||||
struct NoPipe: public std::runtime_error
|
||||
struct NoPipe: public LLException
|
||||
{
|
||||
NoPipe(const std::string& what): std::runtime_error(what) {}
|
||||
NoPipe(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <apr_pools.h>
|
||||
#include <apr_queue.h>
|
||||
#include "llthreadsafequeue.h"
|
||||
#include "llexception.h"
|
||||
|
||||
|
||||
|
||||
|
|
@ -41,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
|
|||
{
|
||||
if(mOwnsPool) {
|
||||
apr_status_t status = apr_pool_create(&mPool, 0);
|
||||
if(status != APR_SUCCESS) throw 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) throw LLThreadSafeQueueError("failed to allocate queue");
|
||||
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -68,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)
|
|||
apr_status_t status = apr_queue_push(mQueue, element);
|
||||
|
||||
if(status == APR_EINTR) {
|
||||
throw LLThreadSafeQueueInterrupt();
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
} else if(status != APR_SUCCESS) {
|
||||
throw LLThreadSafeQueueError("push failed");
|
||||
LLTHROW(LLThreadSafeQueueError("push failed"));
|
||||
} else {
|
||||
; // Success.
|
||||
}
|
||||
|
|
@ -88,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)
|
|||
apr_status_t status = apr_queue_pop(mQueue, &element);
|
||||
|
||||
if(status == APR_EINTR) {
|
||||
throw LLThreadSafeQueueInterrupt();
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
} else if(status != APR_SUCCESS) {
|
||||
throw LLThreadSafeQueueError("pop failed");
|
||||
LLTHROW(LLThreadSafeQueueError("pop failed"));
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,8 @@
|
|||
#ifndef LL_LLTHREADSAFEQUEUE_H
|
||||
#define LL_LLTHREADSAFEQUEUE_H
|
||||
|
||||
|
||||
#include "llexception.h"
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
struct apr_pool_t; // From apr_pools.h
|
||||
|
|
@ -40,11 +39,11 @@ class LLThreadSafeQueueImplementation; // See below.
|
|||
// A general queue exception.
|
||||
//
|
||||
class LL_COMMON_API LLThreadSafeQueueError:
|
||||
public std::runtime_error
|
||||
public LLException
|
||||
{
|
||||
public:
|
||||
LLThreadSafeQueueError(std::string const & message):
|
||||
std::runtime_error(message)
|
||||
LLException(message)
|
||||
{
|
||||
; // No op.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ) throw bad_input_data();
|
||||
if( s == 0 ) LLTHROW(bad_input_data());
|
||||
ret = ret * 85 + (s-encodeTable);
|
||||
}
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -35,13 +35,13 @@
|
|||
|
||||
#include <tut/tut.hpp>
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
// statically reference the function in test.cpp... it's short, we could
|
||||
// replicate, but better to reuse
|
||||
|
|
@ -67,9 +67,9 @@ struct WrapLLErrs
|
|||
LLError::restoreSettings(mPriorErrorSettings);
|
||||
}
|
||||
|
||||
struct FatalException: public std::runtime_error
|
||||
struct FatalException: public LLException
|
||||
{
|
||||
FatalException(const std::string& what): std::runtime_error(what) {}
|
||||
FatalException(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
void operator()(const std::string& message)
|
||||
|
|
@ -78,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.
|
||||
throw FatalException(message);
|
||||
LLTHROW(FatalException(message));
|
||||
}
|
||||
|
||||
std::string error;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
LLSD constructPostData();
|
||||
virtual void updateApplication(const std::string& message = LLStringUtil::null);
|
||||
virtual bool init();
|
||||
virtual bool mainLoop() = 0;
|
||||
virtual bool frame() = 0;
|
||||
virtual bool cleanup() = 0;
|
||||
void commonCleanup();
|
||||
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
|
||||
|
|
|
|||
|
|
@ -1426,7 +1426,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;
|
||||
}
|
||||
|
||||
if (isBufferInvalid())
|
||||
{
|
||||
|
|
@ -1446,67 +1451,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);
|
||||
S32 new_data_size = new_width * new_height * components;
|
||||
|
||||
// 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 );
|
||||
if (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);
|
||||
}
|
||||
|
||||
deleteData();
|
||||
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
|
||||
// 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, 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());
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, components);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
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 ;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,16 @@
|
|||
#include "llimage.h"
|
||||
#include "llpngwrapper.h"
|
||||
|
||||
#include "llexception.h"
|
||||
|
||||
namespace {
|
||||
// Failure to load an image shouldn't crash the whole viewer.
|
||||
struct PngError: public LLContinueError
|
||||
{
|
||||
PngError(png_const_charp msg): LLContinueError(msg) {}
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// LLPngWrapper
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -75,11 +85,10 @@ BOOL LLPngWrapper::isValidPng(U8* src)
|
|||
}
|
||||
|
||||
// Called by the libpng library when a fatal encoding or decoding error
|
||||
// occurs. We simply throw the error message and let our try/catch
|
||||
// block clean up.
|
||||
// occurs. We throw PngError and let our try/catch block clean up.
|
||||
void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
throw msg;
|
||||
LLTHROW(PngError(msg));
|
||||
}
|
||||
|
||||
// Called by the libpng library when reading (decoding) the PNG file. We
|
||||
|
|
@ -129,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
|
|||
this, &errorHandler, NULL);
|
||||
if (mReadPngPtr == NULL)
|
||||
{
|
||||
throw "Problem creating png read structure";
|
||||
LLTHROW(PngError("Problem creating png read structure"));
|
||||
}
|
||||
|
||||
// Allocate/initialize the memory for image information.
|
||||
|
|
@ -187,9 +196,9 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
|
|||
|
||||
mFinalSize = dataPtr.mOffset;
|
||||
}
|
||||
catch (png_const_charp msg)
|
||||
catch (const PngError& msg)
|
||||
{
|
||||
mErrorMessage = msg;
|
||||
mErrorMessage = msg.what();
|
||||
releaseResources();
|
||||
return (FALSE);
|
||||
}
|
||||
|
|
@ -288,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
|
|||
|
||||
if (mColorType == -1)
|
||||
{
|
||||
throw "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)
|
||||
{
|
||||
throw "Problem creating png write structure";
|
||||
LLTHROW(PngError("Problem creating png write structure"));
|
||||
}
|
||||
|
||||
mWriteInfoPtr = png_create_info_struct(mWritePngPtr);
|
||||
|
|
@ -339,9 +348,9 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
|
|||
png_write_end(mWritePngPtr, mWriteInfoPtr);
|
||||
mFinalSize = dataPtr.mOffset;
|
||||
}
|
||||
catch (png_const_charp msg)
|
||||
catch (const PngError& msg)
|
||||
{
|
||||
mErrorMessage = msg;
|
||||
mErrorMessage = msg.what();
|
||||
releaseResources();
|
||||
return (FALSE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file llimagej2ckdu.cpp
|
||||
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
|
||||
*
|
||||
|
|
@ -35,16 +35,51 @@
|
|||
|
||||
#include "kdu_block_coding.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include "llexception.h"
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace {
|
||||
// exception used to keep KDU from terminating entire program -- see comments
|
||||
// in LLKDUMessageError::flush()
|
||||
struct KDUError: public std::runtime_error
|
||||
// Failure to load an image shouldn't crash the whole viewer.
|
||||
struct KDUError: public LLContinueError
|
||||
{
|
||||
KDUError(const std::string& msg): std::runtime_error(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
|
||||
|
|
@ -195,7 +230,7 @@ struct LLKDUMessageError : public LLKDUMessage
|
|||
// shutdown will NOT engage the behavior described above.
|
||||
if (end_of_message)
|
||||
{
|
||||
throw KDUError("LLKDUMessageError::flush()");
|
||||
LLTHROW(KDUError("LLKDUMessageError::flush()"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -309,10 +344,10 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
|
|||
{
|
||||
// This method is only called from methods that catch KDUError.
|
||||
// We want to fail the image load, not crash the viewer.
|
||||
throw KDUError(STRINGIZE("Component " << idx << " dimensions "
|
||||
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
|
||||
<< other_dims
|
||||
<< " do not match component 0 dimensions "
|
||||
<< dims << "!"));
|
||||
<< dims << "!")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,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;
|
||||
}
|
||||
|
||||
|
|
@ -537,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
|
||||
|
|
@ -728,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;
|
||||
}
|
||||
|
||||
|
|
@ -752,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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "llstl.h"
|
||||
#include "llhttpconstants.h"
|
||||
#include "llexception.h"
|
||||
|
||||
const std::string CONTEXT_HEADERS("headers");
|
||||
const std::string CONTEXT_PATH("path");
|
||||
|
|
@ -92,27 +93,28 @@ LLHTTPNode::~LLHTTPNode()
|
|||
|
||||
|
||||
namespace {
|
||||
class NotImplemented
|
||||
struct NotImplemented: public LLException
|
||||
{
|
||||
NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}
|
||||
};
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSD LLHTTPNode::simpleGet() const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSD LLHTTPNode::simplePut(const LLSD& input) const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSD LLHTTPNode::simplePost(const LLSD& input) const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -172,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
|
|||
// virtual
|
||||
LLSD LLHTTPNode::simpleDel(const LLSD&) const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
|
|||
|
|
@ -33,15 +33,15 @@
|
|||
#include "llevents.h"
|
||||
#include "llsd.h"
|
||||
#include "llhost.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
struct CommtestError: public std::runtime_error
|
||||
struct CommtestError: public LLException
|
||||
{
|
||||
CommtestError(const std::string& what): std::runtime_error(what) {}
|
||||
CommtestError(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
static bool query_verbose()
|
||||
|
|
@ -68,7 +68,7 @@ static int query_port(const std::string& var)
|
|||
const char* cport = getenv(var.c_str());
|
||||
if (! cport)
|
||||
{
|
||||
throw 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));
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llares.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llexception.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* NetworkIO
|
||||
|
|
@ -51,7 +52,7 @@ public:
|
|||
ll_init_apr();
|
||||
if (! gAPRPoolp)
|
||||
{
|
||||
throw std::runtime_error("Can't initialize APR");
|
||||
LLTHROW(LLException("Can't initialize APR"));
|
||||
}
|
||||
|
||||
// Create IO Pump to use for HTTP Requests.
|
||||
|
|
@ -59,7 +60,7 @@ public:
|
|||
LLHTTPClient::setPump(*mServicePump);
|
||||
if (ll_init_ares() == NULL || !gAres->isInitialized())
|
||||
{
|
||||
throw std::runtime_error("Can't start DNS resolver");
|
||||
LLTHROW(LLException("Can't start DNS resolver"));
|
||||
}
|
||||
|
||||
// You can interrupt pump() without waiting the full timeout duration
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ void LLPluginClassMedia::reset()
|
|||
mMediaHeight = 0;
|
||||
mDirtyRect = LLRect::null;
|
||||
mAutoScaleMedia = false;
|
||||
mRequestedVolume = 1.0f;
|
||||
mRequestedVolume = 0.0f;
|
||||
mPriority = PRIORITY_NORMAL;
|
||||
mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
|
||||
mAllowDownsample = false;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
@property (retain) NSString *currentInputLanguage;
|
||||
|
||||
- (void) mainLoop;
|
||||
- (void) oneFrame;
|
||||
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
|
||||
- (void) languageUpdated;
|
||||
- (bool) romanScript;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ typedef const NativeKeyEventData * NSKeyEventRef;
|
|||
// These are defined in llappviewermacosx.cpp.
|
||||
bool initViewer();
|
||||
void handleQuit();
|
||||
bool runMainLoop();
|
||||
bool pumpMainLoop();
|
||||
void initMainLoop();
|
||||
void cleanupViewer();
|
||||
void handleUrl(const char* url);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()
|
|||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::mainLoop()
|
||||
bool LLCrashLoggerMac::frame()
|
||||
{
|
||||
|
||||
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
LLCrashLoggerMac(void);
|
||||
~LLCrashLoggerMac(void);
|
||||
virtual bool init();
|
||||
virtual bool mainLoop();
|
||||
virtual bool frame();
|
||||
virtual bool cleanup();
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
// return NSApplicationMain(argc, (const char **)argv);
|
||||
}
|
||||
app.mainLoop();
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1757,6 +1757,7 @@ if (WINDOWS)
|
|||
SLPlugin
|
||||
media_plugin_quicktime
|
||||
media_plugin_cef
|
||||
media_plugin_libvlc
|
||||
winmm_shim
|
||||
windows-crash-logger
|
||||
)
|
||||
|
|
@ -1972,6 +1973,7 @@ if (LINUX)
|
|||
linux-crash-logger
|
||||
SLPlugin
|
||||
media_plugin_gstreamer010
|
||||
media_plugin_libvlc
|
||||
llcommon
|
||||
)
|
||||
|
||||
|
|
@ -2079,7 +2081,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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -534,7 +536,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
|
|||
// somewhat clumsy, as we may run into errors that do not map directly to curl
|
||||
// error codes. Should be refactored with login refactoring, perhaps.
|
||||
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
|
||||
result.setMessage(cert_exception.getMessage());
|
||||
result.setMessage(cert_exception.what());
|
||||
LLPointer<LLCertificate> cert = cert_exception.getCert();
|
||||
cert->ref(); // adding an extra ref here
|
||||
result.setErrorData(cert.get());
|
||||
|
|
@ -544,13 +546,14 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
|
|||
catch (LLCertException &cert_exception)
|
||||
{
|
||||
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
|
||||
result.setMessage(cert_exception.getMessage());
|
||||
result.setMessage(cert_exception.what());
|
||||
LLPointer<LLCertificate> cert = cert_exception.getCert();
|
||||
cert->ref(); // adding an extra ref here
|
||||
result.setErrorData(cert.get());
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,16 +48,19 @@
|
|||
- (void) applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
frameTimer = nil;
|
||||
|
||||
|
||||
[self languageUpdated];
|
||||
|
||||
|
||||
if (initViewer())
|
||||
{
|
||||
frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
|
||||
// Set up recurring calls to oneFrame (repeating timer with timeout 0)
|
||||
// until applicationShouldTerminate.
|
||||
frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self
|
||||
selector:@selector(oneFrame) userInfo:nil repeats:YES];
|
||||
} else {
|
||||
handleQuit();
|
||||
}
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];
|
||||
|
||||
// [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
|
||||
|
|
@ -96,22 +99,29 @@
|
|||
|
||||
- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if (!runMainLoop())
|
||||
// run one frame to assess state
|
||||
if (!pumpMainLoop())
|
||||
{
|
||||
// pumpMainLoop() returns true when done, false if it wants to be
|
||||
// called again. Since it returned false, do not yet cancel
|
||||
// frameTimer.
|
||||
handleQuit();
|
||||
return NSTerminateCancel;
|
||||
} else {
|
||||
// pumpMainLoop() returned true: it's done. Okay, done with frameTimer.
|
||||
[frameTimer release];
|
||||
cleanupViewer();
|
||||
return NSTerminateNow;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) mainLoop
|
||||
- (void) oneFrame
|
||||
{
|
||||
bool appExiting = runMainLoop();
|
||||
bool appExiting = pumpMainLoop();
|
||||
if (appExiting)
|
||||
{
|
||||
// Once pumpMainLoop() reports that we're done, cancel frameTimer:
|
||||
// stop the repetitive calls.
|
||||
[frameTimer release];
|
||||
[[NSApplication sharedApplication] terminate:self];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,15 +123,20 @@
|
|||
#include "llleap.h"
|
||||
#include "stringize.h"
|
||||
#include "llcoros.h"
|
||||
#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>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#if LL_WINDOWS
|
||||
# include <share.h> // For _SH_DENYWR in processMarkerFiles
|
||||
|
|
@ -233,7 +238,6 @@
|
|||
#include "llcoproceduremanager.h"
|
||||
#include "llviewereventrecorder.h"
|
||||
|
||||
|
||||
// *FIX: These extern globals should be cleaned up.
|
||||
// The globals either represent state/config/resource-storage of either
|
||||
// this app, or another 'component' of the viewer. App globals should be
|
||||
|
|
@ -771,9 +775,6 @@ bool LLAppViewer::init()
|
|||
//
|
||||
// Start of the application
|
||||
//
|
||||
#ifdef LL_DARWIN
|
||||
mMainLoopInitialized = false;
|
||||
#endif
|
||||
|
||||
// initialize LLWearableType translation bridge.
|
||||
// Memory will be cleaned up in ::cleanupClass()
|
||||
|
|
@ -930,7 +931,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);
|
||||
|
||||
|
|
@ -1225,6 +1226,23 @@ bool LLAppViewer::init()
|
|||
boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),
|
||||
boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS));
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
// nat 2016-06-29 moved the following here from the former mainLoop().
|
||||
mMainloopTimeout = new LLWatchdogTimeout();
|
||||
|
||||
// Create IO Pump to use for HTTP Requests.
|
||||
gServicePump = new LLPumpIO(gAPRPoolp);
|
||||
|
||||
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
|
||||
|
||||
LLVoiceChannel::initClass();
|
||||
LLVoiceClient::getInstance()->init(gServicePump);
|
||||
LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
|
||||
|
||||
joystick = LLViewerJoystick::getInstance();
|
||||
joystick->setNeedsReset(true);
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1299,299 +1317,265 @@ static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");
|
|||
// externally visible timers
|
||||
LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
|
||||
|
||||
bool LLAppViewer::mainLoop()
|
||||
bool LLAppViewer::frame()
|
||||
{
|
||||
#ifdef LL_DARWIN
|
||||
if (!mMainLoopInitialized)
|
||||
#endif
|
||||
{
|
||||
LL_INFOS() << "Entering main_loop" << LL_ENDL;
|
||||
mMainloopTimeout = new LLWatchdogTimeout();
|
||||
|
||||
//-------------------------------------------
|
||||
// Run main loop until time to quit
|
||||
//-------------------------------------------
|
||||
|
||||
// Create IO Pump to use for HTTP Requests.
|
||||
gServicePump = new LLPumpIO(gAPRPoolp);
|
||||
|
||||
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
|
||||
|
||||
LLVoiceChannel::initClass();
|
||||
LLVoiceClient::getInstance()->init(gServicePump);
|
||||
LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
|
||||
|
||||
joystick = LLViewerJoystick::getInstance();
|
||||
joystick->setNeedsReset(true);
|
||||
|
||||
#ifdef LL_DARWIN
|
||||
// Ensure that this section of code never gets called again on OS X.
|
||||
mMainLoopInitialized = true;
|
||||
#endif
|
||||
}
|
||||
// As we do not (yet) send data on the mainloop LLEventPump that varies
|
||||
// with each frame, no need to instantiate a new LLSD event object each
|
||||
// time. Obviously, if that changes, just instantiate the LLSD at the
|
||||
// point of posting.
|
||||
|
||||
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
|
||||
|
||||
LLSD newFrame;
|
||||
|
||||
LLSD newFrame;
|
||||
|
||||
LLTimer frameTimer,idleTimer;
|
||||
LLTimer debugTime;
|
||||
|
||||
|
||||
//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
|
||||
//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
|
||||
//LLPrivateMemoryPoolTester::destroy() ;
|
||||
|
||||
// Handle messages
|
||||
#ifdef LL_DARWIN
|
||||
if (!LLApp::isExiting())
|
||||
#else
|
||||
while (!LLApp::isExiting())
|
||||
#endif
|
||||
LL_RECORD_BLOCK_TIME(FTM_FRAME);
|
||||
LLTrace::BlockTimer::processTimes();
|
||||
LLTrace::get_frame_recording().nextPeriod();
|
||||
LLTrace::BlockTimer::logStats();
|
||||
|
||||
LLTrace::get_thread_recorder()->pullFromChildren();
|
||||
|
||||
//clear call stack records
|
||||
LL_CLEAR_CALLSTACKS();
|
||||
|
||||
//check memory availability information
|
||||
checkMemory() ;
|
||||
|
||||
try
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_FRAME);
|
||||
LLTrace::BlockTimer::processTimes();
|
||||
LLTrace::get_frame_recording().nextPeriod();
|
||||
LLTrace::BlockTimer::logStats();
|
||||
pingMainloopTimeout("Main:MiscNativeWindowEvents");
|
||||
|
||||
LLTrace::get_thread_recorder()->pullFromChildren();
|
||||
|
||||
//clear call stack records
|
||||
LL_CLEAR_CALLSTACKS();
|
||||
|
||||
//check memory availability information
|
||||
checkMemory() ;
|
||||
|
||||
try
|
||||
if (gViewerWindow)
|
||||
{
|
||||
pingMainloopTimeout("Main:MiscNativeWindowEvents");
|
||||
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
|
||||
gViewerWindow->getWindow()->processMiscNativeEvents();
|
||||
}
|
||||
|
||||
if (gViewerWindow)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
|
||||
gViewerWindow->getWindow()->processMiscNativeEvents();
|
||||
}
|
||||
|
||||
pingMainloopTimeout("Main:GatherInput");
|
||||
|
||||
if (gViewerWindow)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
|
||||
if (!restoreErrorTrap())
|
||||
{
|
||||
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
|
||||
}
|
||||
pingMainloopTimeout("Main:GatherInput");
|
||||
|
||||
gViewerWindow->getWindow()->gatherInput();
|
||||
if (gViewerWindow)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
|
||||
if (!restoreErrorTrap())
|
||||
{
|
||||
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
|
||||
}
|
||||
|
||||
gViewerWindow->getWindow()->gatherInput();
|
||||
}
|
||||
|
||||
#if 1 && !LL_RELEASE_FOR_DOWNLOAD
|
||||
// once per second debug info
|
||||
if (debugTime.getElapsedTimeF32() > 1.f)
|
||||
{
|
||||
debugTime.reset();
|
||||
}
|
||||
|
||||
// once per second debug info
|
||||
if (debugTime.getElapsedTimeF32() > 1.f)
|
||||
{
|
||||
debugTime.reset();
|
||||
}
|
||||
|
||||
#endif
|
||||
//memory leaking simulation
|
||||
LLFloaterMemLeak* mem_leak_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
|
||||
if(mem_leak_instance)
|
||||
//memory leaking simulation
|
||||
LLFloaterMemLeak* mem_leak_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
|
||||
if(mem_leak_instance)
|
||||
{
|
||||
mem_leak_instance->idle() ;
|
||||
}
|
||||
|
||||
// canonical per-frame event
|
||||
mainloop.post(newFrame);
|
||||
|
||||
if (!LLApp::isExiting())
|
||||
{
|
||||
pingMainloopTimeout("Main:JoystickKeyboard");
|
||||
|
||||
// Scan keyboard for movement keys. Command keys and typing
|
||||
// are handled by windows callbacks. Don't do this until we're
|
||||
// done initializing. JC
|
||||
if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
|
||||
&& gViewerWindow->getActive()
|
||||
&& !gViewerWindow->getWindow()->getMinimized()
|
||||
&& LLStartUp::getStartupState() == STATE_STARTED
|
||||
&& (gHeadlessClient || !gViewerWindow->getShowProgress())
|
||||
&& !gFocusMgr.focusLocked())
|
||||
{
|
||||
mem_leak_instance->idle() ;
|
||||
}
|
||||
|
||||
// canonical per-frame event
|
||||
mainloop.post(newFrame);
|
||||
|
||||
if (!LLApp::isExiting())
|
||||
{
|
||||
pingMainloopTimeout("Main:JoystickKeyboard");
|
||||
|
||||
// Scan keyboard for movement keys. Command keys and typing
|
||||
// are handled by windows callbacks. Don't do this until we're
|
||||
// done initializing. JC
|
||||
if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
|
||||
&& gViewerWindow->getActive()
|
||||
&& !gViewerWindow->getWindow()->getMinimized()
|
||||
&& LLStartUp::getStartupState() == STATE_STARTED
|
||||
&& (gHeadlessClient || !gViewerWindow->getShowProgress())
|
||||
&& !gFocusMgr.focusLocked())
|
||||
{
|
||||
joystick->scanJoystick();
|
||||
gKeyboard->scanKeyboard();
|
||||
}
|
||||
|
||||
// Update state based on messages, user input, object idle.
|
||||
{
|
||||
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
|
||||
|
||||
LL_RECORD_BLOCK_TIME(FTM_IDLE);
|
||||
idle();
|
||||
|
||||
resumeMainloopTimeout();
|
||||
}
|
||||
|
||||
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
|
||||
{
|
||||
pauseMainloopTimeout();
|
||||
saveFinalSnapshot();
|
||||
disconnectViewer();
|
||||
resumeMainloopTimeout();
|
||||
}
|
||||
|
||||
// Render scene.
|
||||
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
|
||||
if (!LLApp::isExiting() && !gHeadlessClient)
|
||||
{
|
||||
pingMainloopTimeout("Main:Display");
|
||||
gGLActive = TRUE;
|
||||
display();
|
||||
pingMainloopTimeout("Main:Snapshot");
|
||||
LLFloaterSnapshot::update(); // take snapshots
|
||||
LLFloaterOutfitSnapshot::update();
|
||||
gGLActive = FALSE;
|
||||
}
|
||||
joystick->scanJoystick();
|
||||
gKeyboard->scanKeyboard();
|
||||
}
|
||||
|
||||
pingMainloopTimeout("Main:Sleep");
|
||||
|
||||
pauseMainloopTimeout();
|
||||
|
||||
// Sleep and run background threads
|
||||
// Update state based on messages, user input, object idle.
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_SLEEP);
|
||||
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
|
||||
|
||||
// yield some time to the os based on command line option
|
||||
if(mYieldTime >= 0)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_YIELD);
|
||||
ms_sleep(mYieldTime);
|
||||
}
|
||||
|
||||
// yield cooperatively when not running as foreground window
|
||||
if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
|
||||
|| !gFocusMgr.getAppHasFocus())
|
||||
{
|
||||
// Sleep if we're not rendering, or the window is minimized.
|
||||
S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
|
||||
// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
|
||||
// of equal priority on Windows
|
||||
if (milliseconds_to_sleep > 0)
|
||||
{
|
||||
ms_sleep(milliseconds_to_sleep);
|
||||
// also pause worker threads during this wait period
|
||||
LLAppViewer::getTextureCache()->pause();
|
||||
LLAppViewer::getImageDecodeThread()->pause();
|
||||
}
|
||||
}
|
||||
|
||||
if (mRandomizeFramerate)
|
||||
{
|
||||
ms_sleep(rand() % 200);
|
||||
}
|
||||
|
||||
if (mPeriodicSlowFrame
|
||||
&& (gFrameCount % 10 == 0))
|
||||
{
|
||||
LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
|
||||
ms_sleep(500);
|
||||
}
|
||||
|
||||
const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second
|
||||
idleTimer.reset();
|
||||
S32 total_work_pending = 0;
|
||||
S32 total_io_pending = 0;
|
||||
while(1)
|
||||
{
|
||||
S32 work_pending = 0;
|
||||
S32 io_pending = 0;
|
||||
F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
|
||||
|
||||
work_pending += updateTextureThreads(max_time);
|
||||
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_VFS);
|
||||
io_pending += LLVFSThread::updateClass(1);
|
||||
}
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_LFS);
|
||||
io_pending += LLLFSThread::updateClass(1);
|
||||
}
|
||||
|
||||
if (io_pending > 1000)
|
||||
{
|
||||
ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
|
||||
}
|
||||
|
||||
total_work_pending += work_pending ;
|
||||
total_io_pending += io_pending ;
|
||||
|
||||
if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
gMeshRepo.update() ;
|
||||
|
||||
if(!total_work_pending) //pause texture fetching threads if nothing to process.
|
||||
{
|
||||
LLAppViewer::getTextureCache()->pause();
|
||||
LLAppViewer::getImageDecodeThread()->pause();
|
||||
LLAppViewer::getTextureFetch()->pause();
|
||||
}
|
||||
if(!total_io_pending) //pause file threads if nothing to process.
|
||||
{
|
||||
LLVFSThread::sLocal->pause();
|
||||
LLLFSThread::sLocal->pause();
|
||||
}
|
||||
|
||||
//texture fetching debugger
|
||||
if(LLTextureFetchDebugger::isEnabled())
|
||||
{
|
||||
LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
|
||||
if(tex_fetch_debugger_instance)
|
||||
{
|
||||
tex_fetch_debugger_instance->idle() ;
|
||||
}
|
||||
}
|
||||
|
||||
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
|
||||
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
|
||||
{
|
||||
gFrameStalls++;
|
||||
}
|
||||
frameTimer.reset();
|
||||
LL_RECORD_BLOCK_TIME(FTM_IDLE);
|
||||
idle();
|
||||
|
||||
resumeMainloopTimeout();
|
||||
|
||||
pingMainloopTimeout("Main:End");
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
LLMemory::logMemoryInfo(TRUE) ;
|
||||
|
||||
//stop memory leaking simulation
|
||||
LLFloaterMemLeak* mem_leak_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
|
||||
if(mem_leak_instance)
|
||||
{
|
||||
mem_leak_instance->stop() ;
|
||||
LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
|
||||
}
|
||||
else
|
||||
{
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print() ;
|
||||
|
||||
LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
|
||||
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
|
||||
{
|
||||
pauseMainloopTimeout();
|
||||
saveFinalSnapshot();
|
||||
disconnectViewer();
|
||||
resumeMainloopTimeout();
|
||||
}
|
||||
|
||||
// Render scene.
|
||||
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
|
||||
if (!LLApp::isExiting() && !gHeadlessClient)
|
||||
{
|
||||
pingMainloopTimeout("Main:Display");
|
||||
gGLActive = TRUE;
|
||||
display();
|
||||
pingMainloopTimeout("Main:Snapshot");
|
||||
LLFloaterSnapshot::update(); // take snapshots
|
||||
LLFloaterOutfitSnapshot::update();
|
||||
gGLActive = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
pingMainloopTimeout("Main:Sleep");
|
||||
|
||||
pauseMainloopTimeout();
|
||||
|
||||
// Sleep and run background threads
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_SLEEP);
|
||||
|
||||
// yield some time to the os based on command line option
|
||||
if(mYieldTime >= 0)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_YIELD);
|
||||
ms_sleep(mYieldTime);
|
||||
}
|
||||
|
||||
// yield cooperatively when not running as foreground window
|
||||
if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
|
||||
|| !gFocusMgr.getAppHasFocus())
|
||||
{
|
||||
// Sleep if we're not rendering, or the window is minimized.
|
||||
S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
|
||||
// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
|
||||
// of equal priority on Windows
|
||||
if (milliseconds_to_sleep > 0)
|
||||
{
|
||||
ms_sleep(milliseconds_to_sleep);
|
||||
// also pause worker threads during this wait period
|
||||
LLAppViewer::getTextureCache()->pause();
|
||||
LLAppViewer::getImageDecodeThread()->pause();
|
||||
}
|
||||
}
|
||||
|
||||
if (mRandomizeFramerate)
|
||||
{
|
||||
ms_sleep(rand() % 200);
|
||||
}
|
||||
|
||||
if (mPeriodicSlowFrame
|
||||
&& (gFrameCount % 10 == 0))
|
||||
{
|
||||
LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
|
||||
ms_sleep(500);
|
||||
}
|
||||
|
||||
const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second
|
||||
idleTimer.reset();
|
||||
S32 total_work_pending = 0;
|
||||
S32 total_io_pending = 0;
|
||||
while(1)
|
||||
{
|
||||
S32 work_pending = 0;
|
||||
S32 io_pending = 0;
|
||||
F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
|
||||
|
||||
work_pending += updateTextureThreads(max_time);
|
||||
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_VFS);
|
||||
io_pending += LLVFSThread::updateClass(1);
|
||||
}
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_LFS);
|
||||
io_pending += LLLFSThread::updateClass(1);
|
||||
}
|
||||
|
||||
if (io_pending > 1000)
|
||||
{
|
||||
ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
|
||||
}
|
||||
|
||||
total_work_pending += work_pending ;
|
||||
total_io_pending += io_pending ;
|
||||
|
||||
if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
gMeshRepo.update() ;
|
||||
|
||||
if(!total_work_pending) //pause texture fetching threads if nothing to process.
|
||||
{
|
||||
LLAppViewer::getTextureCache()->pause();
|
||||
LLAppViewer::getImageDecodeThread()->pause();
|
||||
LLAppViewer::getTextureFetch()->pause();
|
||||
}
|
||||
if(!total_io_pending) //pause file threads if nothing to process.
|
||||
{
|
||||
LLVFSThread::sLocal->pause();
|
||||
LLLFSThread::sLocal->pause();
|
||||
}
|
||||
|
||||
//texture fetching debugger
|
||||
if(LLTextureFetchDebugger::isEnabled())
|
||||
{
|
||||
LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
|
||||
if(tex_fetch_debugger_instance)
|
||||
{
|
||||
tex_fetch_debugger_instance->idle() ;
|
||||
}
|
||||
}
|
||||
|
||||
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
|
||||
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
|
||||
{
|
||||
gFrameStalls++;
|
||||
}
|
||||
frameTimer.reset();
|
||||
|
||||
resumeMainloopTimeout();
|
||||
|
||||
pingMainloopTimeout("Main:End");
|
||||
}
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
LLMemory::logMemoryInfo(TRUE) ;
|
||||
|
||||
//stop memory leaking simulation
|
||||
LLFloaterMemLeak* mem_leak_instance =
|
||||
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
|
||||
if(mem_leak_instance)
|
||||
{
|
||||
mem_leak_instance->stop() ;
|
||||
LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
|
||||
}
|
||||
else
|
||||
{
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print() ;
|
||||
|
||||
LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CRASH_ON_UNHANDLED_EXCEPTION("");
|
||||
}
|
||||
|
||||
if (LLApp::isExiting())
|
||||
|
|
@ -1606,7 +1590,7 @@ bool LLAppViewer::mainLoop()
|
|||
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");
|
||||
|
|
@ -1615,16 +1599,20 @@ bool LLAppViewer::mainLoop()
|
|||
mem_leak_instance->stop() ;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete gServicePump;
|
||||
|
||||
|
||||
destroyMainloopTimeout();
|
||||
|
||||
|
||||
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
|
||||
}
|
||||
|
||||
return LLApp::isExiting();
|
||||
return ! LLApp::isRunning();
|
||||
}
|
||||
|
||||
S32 LLAppViewer::updateTextureThreads(F32 max_time)
|
||||
|
|
@ -3348,6 +3336,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);
|
||||
|
|
@ -5552,8 +5553,7 @@ void LLAppViewer::forceErrorInfiniteLoop()
|
|||
void LLAppViewer::forceErrorSoftwareException()
|
||||
{
|
||||
LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL;
|
||||
// *FIX: Any way to insure it won't be handled?
|
||||
throw;
|
||||
LLTHROW(LLException("User selected Force Software Exception"));
|
||||
}
|
||||
|
||||
void LLAppViewer::forceErrorDriverCrash()
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public:
|
|||
//
|
||||
virtual bool init(); // Override to do application initialization
|
||||
virtual bool cleanup(); // Override to do application cleanup
|
||||
virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
|
||||
virtual bool frame(); // Override for application body logic
|
||||
|
||||
// Application control
|
||||
void flushVFSIO(); // waits for vfs transfers to complete
|
||||
|
|
@ -283,7 +283,6 @@ private:
|
|||
std::string mSerialNumber;
|
||||
bool mPurgeCache;
|
||||
bool mPurgeOnExit;
|
||||
bool mMainLoopInitialized;
|
||||
LLViewerJoystick* joystick;
|
||||
|
||||
bool mSavedFinalSnapshot;
|
||||
|
|
|
|||
|
|
@ -95,10 +95,8 @@ int main( int argc, char **argv )
|
|||
}
|
||||
|
||||
// Run the application main loop
|
||||
if(!LLApp::isQuitting())
|
||||
{
|
||||
viewer_app_ptr->mainLoop();
|
||||
}
|
||||
while (! viewer_app_ptr->frame())
|
||||
{}
|
||||
|
||||
if (!LLApp::isError())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,12 +117,17 @@ void handleQuit()
|
|||
LLAppViewer::instance()->userQuit();
|
||||
}
|
||||
|
||||
bool runMainLoop()
|
||||
// This function is called pumpMainLoop() rather than runMainLoop() because
|
||||
// it passes control to the viewer's main-loop logic for a single frame. Like
|
||||
// LLAppViewer::frame(), it returns 'true' when it's done. Until then, it
|
||||
// expects to be called again by the timer in LLAppDelegate
|
||||
// (llappdelegate-objc.mm).
|
||||
bool pumpMainLoop()
|
||||
{
|
||||
bool ret = LLApp::isQuitting();
|
||||
if (!ret && gViewerAppPtr != NULL)
|
||||
{
|
||||
ret = gViewerAppPtr->mainLoop();
|
||||
ret = gViewerAppPtr->frame();
|
||||
} else {
|
||||
ret = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -317,10 +317,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
|
|||
}
|
||||
|
||||
// Run the application main loop
|
||||
if(!LLApp::isQuitting())
|
||||
{
|
||||
viewer_app_ptr->mainLoop();
|
||||
}
|
||||
while (! viewer_app_ptr->frame())
|
||||
{}
|
||||
|
||||
if (!LLApp::isError())
|
||||
{
|
||||
|
|
@ -330,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;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llcommandlineparser.h"
|
||||
#include "llexception.h"
|
||||
|
||||
// *NOTE: The boost::lexical_cast generates
|
||||
// the warning C4701(local used with out assignment) in VC7.1.
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
#include "llsdserialize.h"
|
||||
#include "llerror.h"
|
||||
#include "stringize.h"
|
||||
#include "llexception.h"
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
|
@ -98,14 +100,14 @@ namespace
|
|||
bool gPastLastOption = false;
|
||||
}
|
||||
|
||||
class LLCLPError : public std::logic_error {
|
||||
class LLCLPError : public LLException {
|
||||
public:
|
||||
LLCLPError(const std::string& what) : std::logic_error(what) {}
|
||||
LLCLPError(const std::string& what) : LLException(what) {}
|
||||
};
|
||||
|
||||
class LLCLPLastOption : public std::logic_error {
|
||||
class LLCLPLastOption : public LLException {
|
||||
public:
|
||||
LLCLPLastOption(const std::string& what) : std::logic_error(what) {}
|
||||
LLCLPLastOption(const std::string& what) : LLException(what) {}
|
||||
};
|
||||
|
||||
class LLCLPValue : public po::value_semantic_codecvt_helper<char>
|
||||
|
|
@ -202,17 +204,17 @@ protected:
|
|||
{
|
||||
if(gPastLastOption)
|
||||
{
|
||||
throw(LLCLPLastOption("Don't parse no more!"));
|
||||
LLTHROW(LLCLPLastOption("Don't parse no more!"));
|
||||
}
|
||||
|
||||
// Error checks. Needed?
|
||||
if (!value_store.empty() && !is_composing())
|
||||
{
|
||||
throw(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())
|
||||
{
|
||||
throw(LLCLPError("Illegal number of tokens specified."));
|
||||
LLTHROW(LLCLPError("Illegal number of tokens specified."));
|
||||
}
|
||||
|
||||
if(value_store.empty())
|
||||
|
|
@ -466,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.
|
||||
throw LLCLPError(STRINGIZE("No value specified for --" << option << "!"));
|
||||
LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));
|
||||
}
|
||||
else if (value.size() > 1)
|
||||
{
|
||||
|
|
@ -484,9 +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.
|
||||
throw 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>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,9 @@ namespace
|
|||
|
||||
const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue");
|
||||
|
||||
|
||||
// ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged
|
||||
// callback mechanism and the LLEventPump coroutine architecture allowing the
|
||||
// coroutine to wait for the inventory event.
|
||||
class ObjectInventoryFetcher: public LLVOInventoryListener
|
||||
{
|
||||
public:
|
||||
|
|
@ -144,7 +146,7 @@ public:
|
|||
queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
|
||||
}
|
||||
|
||||
return LLSD().with("success", LLSD::Boolean(true));
|
||||
return LLSDMap("success", LLSD::Boolean(true));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -254,7 +256,6 @@ LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key)
|
|||
setTitle(LLTrans::getString("CompileQueueTitle"));
|
||||
setStartString(LLTrans::getString("CompileQueueStart"));
|
||||
|
||||
// mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
|
||||
}
|
||||
|
||||
LLFloaterCompileQueue::~LLFloaterCompileQueue()
|
||||
|
|
@ -267,7 +268,6 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content )
|
|||
{
|
||||
mExperienceIds.insert(it->asUUID());
|
||||
}
|
||||
// nextObject();
|
||||
}
|
||||
|
||||
BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
|
||||
|
|
@ -277,11 +277,6 @@ BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
|
|||
|
||||
// //Attempt to record this asset ID. If it can not be inserted into the set
|
||||
// //then it has already been processed so return false.
|
||||
// bool LLFloaterCompileQueue::checkAssetId(const LLUUID &assetId)
|
||||
// {
|
||||
// std::pair<uuid_list_t::iterator, bool> result = mAssetIds.insert(assetId);
|
||||
// return result.second;
|
||||
// }
|
||||
|
||||
void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult)
|
||||
{
|
||||
|
|
@ -331,8 +326,10 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren
|
|||
|
||||
queue->experienceIdsReceived(result["experience_ids"]);
|
||||
|
||||
// getDerived handle gets a handle that can be resolved to a parent class of the derived object.
|
||||
LLHandle<LLFloaterScriptQueue> hFloater(queue->getDerivedHandle<LLFloaterScriptQueue>());
|
||||
|
||||
// note subtle difference here: getDerivedHandle in this case is for an LLFloaterCompileQueue
|
||||
fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript,
|
||||
queue->getDerivedHandle<LLFloaterCompileQueue>(), _1, _2, _3);
|
||||
|
||||
|
|
@ -345,37 +342,35 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren
|
|||
|
||||
}
|
||||
|
||||
/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
|
||||
/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
|
||||
bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,
|
||||
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
|
||||
{
|
||||
LLSD result;
|
||||
LLFloaterCompileQueue *that = hfloater.get();
|
||||
bool monocompile = that->mMono;
|
||||
LLCheckedHandle<LLFloaterCompileQueue> floater(hfloater);
|
||||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// which is caught in objectScriptProcessingQueueCoro
|
||||
bool monocompile = floater->mMono;
|
||||
F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
|
||||
|
||||
if (!that)
|
||||
return false;
|
||||
|
||||
// Initial test to see if we can (or should) attempt to compile the script.
|
||||
LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory);
|
||||
|
||||
if (!item)
|
||||
{
|
||||
|
||||
if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) ||
|
||||
!item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
|
||||
{
|
||||
std::string buffer = "Skipping: " + item->getName() + "(Permissions)";
|
||||
that->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if (!that->checkAssetId(item->getAssetUUID()))
|
||||
// {
|
||||
// std::string buffer = "Skipping: " + item->getName() + "(Repeat)";
|
||||
// that->addStringMessage(buffer);
|
||||
// return true;
|
||||
// }
|
||||
LL_WARNS("SCRIPTQ") << "item retrieved is not an LLInventoryItem." << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) ||
|
||||
!item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
|
||||
{
|
||||
std::string buffer = "Skipping: " + item->getName() + "(Permissions)";
|
||||
floater->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
that = NULL;
|
||||
|
||||
// Attempt to retrieve the experience
|
||||
LLUUID experienceId;
|
||||
|
|
@ -384,37 +379,30 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1));
|
||||
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
|
||||
LLSD().with("timeout", LLSD::Boolean(true)));
|
||||
LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
|
||||
that = hfloater.get();
|
||||
if (!that)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.has("timeout") && result["timeout"].asBoolean())
|
||||
{
|
||||
if (result.has("timeout"))
|
||||
{ // A timeout filed in the result will always be true if present.
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = inventory->getName();
|
||||
std::string buffer = that->getString("Timeout", args);
|
||||
that->addStringMessage(buffer);
|
||||
std::string buffer = floater->getString("Timeout", args);
|
||||
floater->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result.has(LLExperienceCache::EXPERIENCE_ID))
|
||||
{
|
||||
experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
if (!that->hasExperience(experienceId))
|
||||
if (!floater->hasExperience(experienceId))
|
||||
{
|
||||
that->addProcessingMessage("CompileNoExperiencePerm", LLSD()
|
||||
.with("SCRIPT", inventory->getName())
|
||||
.with("EXPERIENCE", result[LLExperienceCache::NAME].asString()));
|
||||
floater->addProcessingMessage("CompileNoExperiencePerm",
|
||||
LLSDMap("SCRIPT", inventory->getName())
|
||||
("EXPERIENCE", result[LLExperienceCache::NAME].asString()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
that = NULL;
|
||||
|
||||
{
|
||||
HandleScriptUserData userData(pump.getName());
|
||||
|
|
@ -433,32 +421,23 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
&userData);
|
||||
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
|
||||
LLSD().with("timeout", LLSD::Boolean(true)));
|
||||
}
|
||||
|
||||
that = hfloater.get();
|
||||
if (!that)
|
||||
{
|
||||
return false;
|
||||
LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
}
|
||||
|
||||
if (result.has("timeout"))
|
||||
{
|
||||
if (result.has("timeout") && result["timeout"].asBoolean())
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = inventory->getName();
|
||||
std::string buffer = that->getString("Timeout", args);
|
||||
that->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
{ // A timeout filed in the result will always be true if present.
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = inventory->getName();
|
||||
std::string buffer = floater->getString("Timeout", args);
|
||||
floater->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result.has("error"))
|
||||
{
|
||||
LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL;
|
||||
std::string buffer = result["message"].asString() + " " + inventory->getName();
|
||||
that->addStringMessage(buffer);
|
||||
floater->addStringMessage(buffer);
|
||||
|
||||
if (result.has("alert"))
|
||||
{
|
||||
|
|
@ -470,12 +449,9 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
}
|
||||
|
||||
LLUUID assetId = result["asset_id"];
|
||||
that = NULL;
|
||||
|
||||
|
||||
std::string url = object->getRegion()->getCapability("UpdateScriptTask");
|
||||
|
||||
|
||||
{
|
||||
LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(),
|
||||
inventory->getUUID(),
|
||||
|
|
@ -490,24 +466,15 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
|
||||
}
|
||||
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSD().with("timeout", LLSD::Boolean(true)));
|
||||
|
||||
that = hfloater.get();
|
||||
if (!that)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
|
||||
if (result.has("timeout"))
|
||||
{
|
||||
if (result.has("timeout") && result["timeout"].asBoolean())
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = inventory->getName();
|
||||
std::string buffer = that->getString("Timeout", args);
|
||||
that->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
{ // A timeout filed in the result will always be true if present.
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = inventory->getName();
|
||||
std::string buffer = floater->getString("Timeout", args);
|
||||
floater->addStringMessage(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bytecode save completed
|
||||
|
|
@ -515,21 +482,21 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
|
|||
{
|
||||
std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded");
|
||||
|
||||
that->addStringMessage(buffer);
|
||||
floater->addStringMessage(buffer);
|
||||
LL_INFOS() << buffer << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSD compile_errors = result["errors"];
|
||||
std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:");
|
||||
that->addStringMessage(buffer);
|
||||
floater->addStringMessage(buffer);
|
||||
for (LLSD::array_const_iterator line = compile_errors.beginArray();
|
||||
line < compile_errors.endArray(); line++)
|
||||
{
|
||||
std::string str = line->asString();
|
||||
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
|
||||
|
||||
that->addStringMessage(str);
|
||||
floater->addStringMessage(str);
|
||||
}
|
||||
LL_INFOS() << result["errors"] << LL_ENDL;
|
||||
}
|
||||
|
|
@ -576,16 +543,18 @@ LLFloaterResetQueue::~LLFloaterResetQueue()
|
|||
{
|
||||
}
|
||||
|
||||
bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
|
||||
/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
|
||||
/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
|
||||
bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
|
||||
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
|
||||
{
|
||||
LLFloaterScriptQueue *that = hfloater.get();
|
||||
if (that)
|
||||
{
|
||||
std::string buffer;
|
||||
buffer = that->getString("Resetting") + (": ") + inventory->getName();
|
||||
that->addStringMessage(buffer);
|
||||
}
|
||||
LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
|
||||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// which is caught in objectScriptProcessingQueueCoro
|
||||
|
||||
std::string buffer;
|
||||
buffer = floater->getString("Resetting") + (": ") + inventory->getName();
|
||||
floater->addStringMessage(buffer);
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_ScriptReset);
|
||||
|
|
@ -602,6 +571,8 @@ bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hflo
|
|||
|
||||
bool LLFloaterResetQueue::startQueue()
|
||||
{
|
||||
// Bind the resetObjectScripts method into a QueueAction function and pass it
|
||||
// into the object queue processing coroutine.
|
||||
fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts,
|
||||
getDerivedHandle<LLFloaterScriptQueue>(), _1, _2, _3);
|
||||
|
||||
|
|
@ -629,16 +600,18 @@ LLFloaterRunQueue::~LLFloaterRunQueue()
|
|||
{
|
||||
}
|
||||
|
||||
bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
|
||||
/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
|
||||
/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
|
||||
bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
|
||||
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
|
||||
{
|
||||
LLFloaterScriptQueue *that = hfloater.get();
|
||||
if (that)
|
||||
{
|
||||
std::string buffer;
|
||||
buffer = that->getString("Running") + (": ") + inventory->getName();
|
||||
that->addStringMessage(buffer);
|
||||
}
|
||||
LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
|
||||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// which is caught in objectScriptProcessingQueueCoro
|
||||
|
||||
std::string buffer;
|
||||
buffer = floater->getString("Running") + (": ") + inventory->getName();
|
||||
floater->addStringMessage(buffer);
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_SetScriptRunning);
|
||||
|
|
@ -684,16 +657,18 @@ LLFloaterNotRunQueue::~LLFloaterNotRunQueue()
|
|||
{
|
||||
}
|
||||
|
||||
/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
|
||||
/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
|
||||
bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
|
||||
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
|
||||
{
|
||||
LLFloaterScriptQueue *that = hfloater.get();
|
||||
if (that)
|
||||
{
|
||||
std::string buffer;
|
||||
buffer = that->getString("NotRunning") + (": ") + inventory->getName();
|
||||
that->addStringMessage(buffer);
|
||||
}
|
||||
LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
|
||||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// which is caught in objectScriptProcessingQueueCoro
|
||||
|
||||
std::string buffer;
|
||||
buffer = floater->getString("NotRunning") + (": ") + inventory->getName();
|
||||
floater->addStringMessage(buffer);
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_SetScriptRunning);
|
||||
|
|
@ -732,7 +707,7 @@ void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object,
|
|||
mInventoryList.clear();
|
||||
mInventoryList.assign(inventory->begin(), inventory->end());
|
||||
|
||||
mPump.post(LLSD().with("changed", LLSD::Boolean(true)));
|
||||
mPump.post(LLSDMap("changed", LLSD::Boolean(true)));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -740,115 +715,97 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L
|
|||
object_data_list_t objectList, fnQueueAction_t func)
|
||||
{
|
||||
LLCoros::set_consuming(true);
|
||||
LLFloaterScriptQueue * floater(NULL);
|
||||
LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
|
||||
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
|
||||
// This is expected if the dialog closes.
|
||||
LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true);
|
||||
F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
|
||||
|
||||
// floater = hfloater.get();
|
||||
// floater->addProcessingMessage("Starting",
|
||||
// LLSD()
|
||||
// .with("[START]", action)
|
||||
// .with("[COUNT]", LLSD::Integer(objectList.size())));
|
||||
// floater = NULL;
|
||||
|
||||
for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj)
|
||||
try
|
||||
{
|
||||
bool firstForObject = true;
|
||||
LLUUID object_id = (*itObj).mObjectId;
|
||||
LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL;
|
||||
|
||||
LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id);
|
||||
LLInventoryObject::object_list_t inventory;
|
||||
if (obj)
|
||||
for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj)
|
||||
{
|
||||
ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL));
|
||||
bool firstForObject = true;
|
||||
LLUUID object_id = (*itObj).mObjectId;
|
||||
LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL;
|
||||
|
||||
fetcher->fetchInventory();
|
||||
|
||||
floater = hfloater.get();
|
||||
if (floater)
|
||||
LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id);
|
||||
LLInventoryObject::object_list_t inventory;
|
||||
if (obj)
|
||||
{
|
||||
ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL));
|
||||
|
||||
fetcher->fetchInventory();
|
||||
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = (*itObj).mObjectName;
|
||||
floater->addStringMessage(floater->getString("LoadingObjInv", args));
|
||||
}
|
||||
|
||||
LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
|
||||
LLSD().with("timeout", LLSD::Boolean(true)));
|
||||
LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
|
||||
LLSDMap("timeout", LLSD::Boolean(true)));
|
||||
|
||||
if (result.has("timeout") && result["timeout"].asBoolean())
|
||||
{
|
||||
LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() <<
|
||||
". Skipping to next object." << LL_ENDL;
|
||||
if (result.has("timeout"))
|
||||
{ // A timeout filed in the result will always be true if present.
|
||||
LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() <<
|
||||
". Skipping to next object." << LL_ENDL;
|
||||
|
||||
// floater could have been closed
|
||||
floater = hfloater.get();
|
||||
if (floater)
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[OBJECT_NAME]"] = (*itObj).mObjectName;
|
||||
floater->addStringMessage(floater->getString("Timeout", args));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end());
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id <<
|
||||
". Skipping to next." << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|
||||
inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end());
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id <<
|
||||
". Skipping to next." << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
// TODO: Get the name of the object we are looking at here so that we can display it below.
|
||||
//std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName();
|
||||
LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL;
|
||||
|
||||
// TODO: Get the name of the object we are looking at here so that we can display it below.
|
||||
//std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName();
|
||||
LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL;
|
||||
|
||||
for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin();
|
||||
itInv != inventory.end(); ++itInv)
|
||||
{
|
||||
floater = hfloater.get();
|
||||
if (!floater)
|
||||
for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin();
|
||||
itInv != inventory.end(); ++itInv)
|
||||
{
|
||||
LL_WARNS("SCRIPTQ") << "Script Queue floater closed! Canceling remaining ops" << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
floater.check();
|
||||
|
||||
// note, we have a smart pointer to the obj above... but if we didn't we'd check that
|
||||
// it still exists here.
|
||||
// note, we have a smart pointer to the obj above... but if we didn't we'd check that
|
||||
// it still exists here.
|
||||
|
||||
if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT))
|
||||
{
|
||||
LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL;
|
||||
if (firstForObject)
|
||||
if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT))
|
||||
{
|
||||
//floater->addStringMessage(objName + ":");
|
||||
firstForObject = false;
|
||||
LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL;
|
||||
if (firstForObject)
|
||||
{
|
||||
//floater->addStringMessage(objName + ":");
|
||||
firstForObject = false;
|
||||
}
|
||||
|
||||
if (!func(obj, (*itInv), maildrop))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!func(obj, (*itInv), maildrop))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// no other explicit suspension point in this loop. func(...) MIGHT suspend
|
||||
// but offers no guarantee of doing so.
|
||||
llcoro::suspend();
|
||||
}
|
||||
|
||||
llcoro::suspend();
|
||||
}
|
||||
// Just test to be sure the floater is still present before calling the func
|
||||
if (!hfloater.get())
|
||||
{
|
||||
LL_WARNS("SCRIPTQ") << "Script Queue floater dismissed." << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
floater = hfloater.get();
|
||||
if (floater)
|
||||
{
|
||||
floater->addStringMessage("Done");
|
||||
floater->getChildView("close")->setEnabled(TRUE);
|
||||
}
|
||||
catch (LLCheckedHandleBase::Stale &)
|
||||
{
|
||||
// This is expected. It means that floater has been closed before
|
||||
// processing was completed.
|
||||
LL_DEBUGS("SCRIPTQ") << "LLExeceptionStaleHandle caught! Floater has most likely been closed." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
LLWeb::loadURLExternal(url);
|
||||
};
|
||||
}
|
||||
|
||||
void LLFloaterWebContent::onTestURL(std::string url)
|
||||
{
|
||||
LLStringUtil::trim(url);
|
||||
if (url.length() > 0)
|
||||
{
|
||||
mWebBrowser->navigateTo(url);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
focusOnTarget();
|
||||
|
||||
LLViewerMediaImpl* media_impl = getTargetMediaImpl();
|
||||
if (media_impl)
|
||||
void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown()
|
||||
{
|
||||
mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal();
|
||||
|
||||
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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llsecapi.h"
|
||||
#include "llsechandler_basic.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <map>
|
||||
|
|
@ -64,12 +66,12 @@ void initializeSecHandler()
|
|||
}
|
||||
catch (LLProtectedDataException e)
|
||||
{
|
||||
exception_msg = e.getMessage();
|
||||
exception_msg = e.what();
|
||||
}
|
||||
}
|
||||
if (!exception_msg.empty()) // an exception was thrown.
|
||||
{
|
||||
throw LLProtectedDataException(exception_msg.c_str());
|
||||
LLTHROW(LLProtectedDataException(exception_msg));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -101,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")
|
||||
|
|
@ -109,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <ostream>
|
||||
#include "llpointer.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#pragma warning(disable:4250)
|
||||
|
|
@ -116,17 +117,13 @@
|
|||
|
||||
|
||||
|
||||
class LLProtectedDataException
|
||||
struct LLProtectedDataException: public LLException
|
||||
{
|
||||
public:
|
||||
LLProtectedDataException(const char *msg)
|
||||
LLProtectedDataException(const std::string& msg):
|
||||
LLException(msg)
|
||||
{
|
||||
LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL;
|
||||
mMsg = (std::string)msg;
|
||||
LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL;
|
||||
}
|
||||
std::string getMessage() { return mMsg; }
|
||||
protected:
|
||||
std::string mMsg;
|
||||
};
|
||||
|
||||
// class LLCertificate
|
||||
|
|
@ -334,22 +331,21 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
|
|||
|
||||
// All error handling is via exceptions.
|
||||
|
||||
class LLCertException
|
||||
class LLCertException: public LLException
|
||||
{
|
||||
public:
|
||||
LLCertException(LLPointer<LLCertificate> cert, const char* msg)
|
||||
LLCertException(LLPointer<LLCertificate> cert, const std::string& msg):
|
||||
LLException(msg)
|
||||
{
|
||||
|
||||
mCert = cert;
|
||||
|
||||
LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL;
|
||||
mMsg = (std::string)msg;
|
||||
LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
|
||||
}
|
||||
LLPointer<LLCertificate> getCert() { return mCert; }
|
||||
std::string getMessage() { return mMsg; }
|
||||
virtual ~LLCertException() throw() {}
|
||||
LLPointer<LLCertificate> getCert() const { return mCert; }
|
||||
protected:
|
||||
LLPointer<LLCertificate> mCert;
|
||||
std::string mMsg;
|
||||
};
|
||||
|
||||
class LLInvalidCertificate : public LLCertException
|
||||
|
|
@ -358,6 +354,7 @@ public:
|
|||
LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")
|
||||
{
|
||||
}
|
||||
virtual ~LLInvalidCertificate() throw() {}
|
||||
protected:
|
||||
};
|
||||
|
||||
|
|
@ -367,6 +364,7 @@ public:
|
|||
LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")
|
||||
{
|
||||
}
|
||||
virtual ~LLCertValidationTrustException() throw() {}
|
||||
protected:
|
||||
};
|
||||
|
||||
|
|
@ -378,7 +376,7 @@ public:
|
|||
{
|
||||
mHostname = hostname;
|
||||
}
|
||||
|
||||
virtual ~LLCertValidationHostnameException() throw() {}
|
||||
std::string getHostname() { return mHostname; }
|
||||
protected:
|
||||
std::string mHostname;
|
||||
|
|
@ -392,6 +390,7 @@ public:
|
|||
{
|
||||
mTime = current_time;
|
||||
}
|
||||
virtual ~LLCertValidationExpirationException() throw() {}
|
||||
LLDate GetTime() { return mTime; }
|
||||
protected:
|
||||
LLDate mTime;
|
||||
|
|
@ -403,6 +402,7 @@ public:
|
|||
LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")
|
||||
{
|
||||
}
|
||||
virtual ~LLCertKeyUsageValidationException() throw() {}
|
||||
protected:
|
||||
};
|
||||
|
||||
|
|
@ -412,6 +412,7 @@ public:
|
|||
LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")
|
||||
{
|
||||
}
|
||||
virtual ~LLCertBasicConstraintsValidationException() throw() {}
|
||||
protected:
|
||||
};
|
||||
|
||||
|
|
@ -421,6 +422,7 @@ public:
|
|||
LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")
|
||||
{
|
||||
}
|
||||
virtual ~LLCertValidationInvalidSignatureException() throw() {}
|
||||
protected:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include "llfile.h"
|
||||
#include "lldir.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <vector>
|
||||
#include <ios>
|
||||
#include <openssl/ossl_typ.h>
|
||||
|
|
@ -72,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;
|
||||
throw LLInvalidCertificate(this);
|
||||
LLTHROW(LLInvalidCertificate(this));
|
||||
}
|
||||
mCert = NULL;
|
||||
PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
|
||||
BIO_free(pem_bio);
|
||||
if (!mCert)
|
||||
{
|
||||
throw LLInvalidCertificate(this);
|
||||
LLTHROW(LLInvalidCertificate(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +90,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert)
|
|||
{
|
||||
if (!pCert || !pCert->cert_info)
|
||||
{
|
||||
throw LLInvalidCertificate(this);
|
||||
LLTHROW(LLInvalidCertificate(this));
|
||||
}
|
||||
mCert = X509_dup(pCert);
|
||||
}
|
||||
|
|
@ -617,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;
|
||||
|
|
@ -873,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))
|
||||
{
|
||||
throw 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))
|
||||
{
|
||||
throw 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))
|
||||
{
|
||||
throw 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))
|
||||
{
|
||||
throw LLCertException(cert, "No SHA1 digest");
|
||||
LLTHROW(LLCertException(cert, "No SHA1 digest"));
|
||||
}
|
||||
|
||||
if (validation_policy & VALIDATION_POLICY_TIME)
|
||||
|
|
@ -903,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()))
|
||||
{
|
||||
throw LLCertValidationExpirationException(cert, validation_date);
|
||||
LLTHROW(LLCertValidationExpirationException(cert, validation_date));
|
||||
}
|
||||
}
|
||||
if (validation_policy & VALIDATION_POLICY_SSL_KU)
|
||||
|
|
@ -914,14 +916,14 @@ void _validateCert(int validation_policy,
|
|||
!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
|
||||
LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
|
||||
{
|
||||
throw 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))))
|
||||
{
|
||||
throw LLCertKeyUsageValidationException(cert);
|
||||
LLTHROW(LLCertKeyUsageValidationException(cert));
|
||||
}
|
||||
}
|
||||
if (validation_policy & VALIDATION_POLICY_CA_KU)
|
||||
|
|
@ -930,7 +932,7 @@ void _validateCert(int validation_policy,
|
|||
(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
|
||||
(std::string)CERT_KU_CERT_SIGN)))
|
||||
{
|
||||
throw LLCertKeyUsageValidationException(cert);
|
||||
LLTHROW(LLCertKeyUsageValidationException(cert));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -942,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])
|
||||
{
|
||||
throw 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())))
|
||||
{
|
||||
throw LLCertBasicConstraintsValidationException(cert);
|
||||
LLTHROW(LLCertBasicConstraintsValidationException(cert));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1018,7 +1020,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
|
||||
if(cert_chain->size() < 1)
|
||||
{
|
||||
throw LLCertException(NULL, "No certs in chain");
|
||||
LLTHROW(LLCertException(NULL, "No certs in chain"));
|
||||
}
|
||||
iterator current_cert = cert_chain->begin();
|
||||
LLSD current_cert_info;
|
||||
|
|
@ -1033,11 +1035,11 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
(*current_cert)->getLLSD(current_cert_info);
|
||||
if(!validation_params.has(CERT_HOSTNAME))
|
||||
{
|
||||
throw 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))
|
||||
{
|
||||
throw LLInvalidCertificate((*current_cert));
|
||||
LLTHROW(LLInvalidCertificate((*current_cert)));
|
||||
}
|
||||
|
||||
LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<
|
||||
|
|
@ -1054,7 +1056,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
X509* cert_x509 = (*current_cert)->getOpenSSLX509();
|
||||
if(!cert_x509)
|
||||
{
|
||||
throw LLInvalidCertificate((*current_cert));
|
||||
LLTHROW(LLInvalidCertificate((*current_cert)));
|
||||
}
|
||||
std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
|
||||
X509_free( cert_x509 );
|
||||
|
|
@ -1075,7 +1077,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
if((validation_date < cache_entry->second.first) ||
|
||||
(validation_date > cache_entry->second.second))
|
||||
{
|
||||
throw LLCertValidationExpirationException((*current_cert), validation_date);
|
||||
LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));
|
||||
}
|
||||
}
|
||||
// successfully found in cache
|
||||
|
|
@ -1107,7 +1109,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
if(!_verify_signature((*current_cert),
|
||||
previous_cert))
|
||||
{
|
||||
throw LLCertValidationInvalidSignatureException(previous_cert);
|
||||
LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));
|
||||
}
|
||||
}
|
||||
_validateCert(local_validation_policy,
|
||||
|
|
@ -1156,7 +1158,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
if(!_verify_signature((*found_store_cert),
|
||||
(*current_cert)))
|
||||
{
|
||||
throw LLCertValidationInvalidSignatureException(*current_cert);
|
||||
LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));
|
||||
}
|
||||
// successfully validated.
|
||||
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
|
||||
|
|
@ -1173,7 +1175,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
|
|||
if (validation_policy & VALIDATION_POLICY_TRUSTED)
|
||||
{
|
||||
// we reached the end without finding a trusted cert.
|
||||
throw 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);
|
||||
|
|
@ -1261,7 +1263,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
|
|||
protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
|
||||
if (protected_data_stream.gcount() < STORE_SALT_SIZE)
|
||||
{
|
||||
throw LLProtectedDataException("Config file too short.");
|
||||
LLTHROW(LLProtectedDataException("Config file too short."));
|
||||
}
|
||||
|
||||
cipher.decrypt(salt, STORE_SALT_SIZE);
|
||||
|
|
@ -1301,7 +1303,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
|
|||
if (parser->parse(parse_stream, mProtectedDataMap,
|
||||
LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
|
||||
{
|
||||
throw LLProtectedDataException("Config file cannot be decrypted.");
|
||||
LLTHROW(LLProtectedDataException("Config file cannot be decrypted."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1364,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.
|
||||
|
|
@ -1372,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
|
||||
//throw 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
|
||||
//throw 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
|
||||
//throw 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -7918,7 +7918,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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 282 B |
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -153,6 +153,136 @@
|
|||
function="WebContent.PopExternal" />
|
||||
</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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace tut
|
|||
public:
|
||||
virtual bool init() { return true; }
|
||||
virtual bool cleanup() { return true; }
|
||||
virtual bool mainLoop() { return true; }
|
||||
virtual bool frame() { return true; }
|
||||
};
|
||||
LLTestApp* mApp;
|
||||
application()
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
// Tell caller this didn't work out so well.
|
||||
|
||||
// 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;
|
||||
}
|
||||
// *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()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "llupdatedownloader.h"
|
||||
#include "httpcommon.h"
|
||||
#include <stdexcept>
|
||||
#include "llexception.h"
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <curl/curl.h>
|
||||
|
|
@ -85,11 +85,11 @@ private:
|
|||
|
||||
namespace {
|
||||
class DownloadError:
|
||||
public std::runtime_error
|
||||
public LLException
|
||||
{
|
||||
public:
|
||||
DownloadError(const char * message):
|
||||
std::runtime_error(message)
|
||||
LLException(message)
|
||||
{
|
||||
; // No op.
|
||||
}
|
||||
|
|
@ -467,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
|
|||
|
||||
if(!mCurl)
|
||||
{
|
||||
throw 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));
|
||||
|
|
@ -508,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
|
|||
mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
|
||||
if(mHeaderList == 0)
|
||||
{
|
||||
throw DownloadError("cannot add Range header");
|
||||
LLTHROW(DownloadError("cannot add Range header"));
|
||||
}
|
||||
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList));
|
||||
|
||||
|
|
@ -524,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) throw 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;
|
||||
|
|
@ -547,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
|
|||
if(code != CURLE_OK) {
|
||||
const char * errorString = curl_easy_strerror(code);
|
||||
if(errorString != 0) {
|
||||
throw DownloadError(curl_easy_strerror(code));
|
||||
LLTHROW(DownloadError(curl_easy_strerror(code)));
|
||||
} else {
|
||||
throw DownloadError("unknown curl error");
|
||||
LLTHROW(DownloadError("unknown curl error"));
|
||||
}
|
||||
} else {
|
||||
; // No op.
|
||||
|
|
|
|||
|
|
@ -30,23 +30,25 @@
|
|||
#include "llupdateinstaller.h"
|
||||
#include "lldir.h"
|
||||
#include "llsd.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!).
|
||||
#endif
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
class RelocateError {};
|
||||
|
||||
|
||||
struct RelocateError: public LLException
|
||||
{
|
||||
RelocateError(): LLException("llupdateinstaller: RelocateError") {}
|
||||
};
|
||||
|
||||
std::string copy_to_temp(std::string const & path)
|
||||
{
|
||||
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) throw RelocateError();
|
||||
if(status != APR_SUCCESS) LLTHROW(RelocateError());
|
||||
|
||||
return newPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "llupdatechecker.h"
|
||||
#include "llupdateinstaller.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
|
@ -190,8 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string& channel,
|
|||
{
|
||||
if(mIsChecking || mIsDownloading)
|
||||
{
|
||||
throw LLUpdaterService::UsageError("LLUpdaterService::initialize call "
|
||||
"while updater is running.");
|
||||
LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call "
|
||||
"while updater is running."));
|
||||
}
|
||||
|
||||
mChannel = channel;
|
||||
|
|
@ -222,8 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
|
|||
{
|
||||
if(mChannel.empty() || mVersion.empty())
|
||||
{
|
||||
throw LLUpdaterService::UsageError("Set params before call to "
|
||||
"LLUpdaterService::startCheck().");
|
||||
LLTHROW(LLUpdaterService::UsageError("Set params before call to "
|
||||
"LLUpdaterService::startCheck()."));
|
||||
}
|
||||
|
||||
mIsChecking = true;
|
||||
|
|
|
|||
|
|
@ -29,16 +29,17 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include "llhasheduniqueid.h"
|
||||
#include "llexception.h"
|
||||
|
||||
class LLUpdaterServiceImpl;
|
||||
|
||||
class LLUpdaterService
|
||||
{
|
||||
public:
|
||||
class UsageError: public std::runtime_error
|
||||
class UsageError: public LLException
|
||||
{
|
||||
public:
|
||||
UsageError(const std::string& msg) : std::runtime_error(msg) {}
|
||||
UsageError(const std::string& msg) : LLException(msg) {}
|
||||
};
|
||||
|
||||
// Name of the event pump through which update events will be delivered.
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles()
|
|||
//mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); //Not initialized.
|
||||
}
|
||||
|
||||
bool LLCrashLoggerWindows::mainLoop()
|
||||
bool LLCrashLoggerWindows::frame()
|
||||
{
|
||||
LL_INFOS() << "CrashSubmitBehavior is " << mCrashBehavior << LL_ENDL;
|
||||
|
||||
|
|
@ -503,14 +503,14 @@ bool LLCrashLoggerWindows::mainLoop()
|
|||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return msg.wParam;
|
||||
return true; // msg.wParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Unknown crash behavior " << mCrashBehavior << LL_ENDL;
|
||||
return 1;
|
||||
return true; // 1;
|
||||
}
|
||||
return 0;
|
||||
return true; // 0;
|
||||
}
|
||||
|
||||
void LLCrashLoggerWindows::updateApplication(const std::string& message)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public:
|
|||
static LLCrashLoggerWindows* sInstance;
|
||||
|
||||
virtual bool init();
|
||||
virtual bool mainLoop();
|
||||
virtual bool frame();
|
||||
virtual void updateApplication(const std::string& message = LLStringUtil::null);
|
||||
virtual bool cleanup();
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
|||
}
|
||||
|
||||
app.processingLoop();
|
||||
app.mainLoop();
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue