diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py index fff78ecbe3..17bce6f434 100644 --- a/indra/cmake/run_build_test.py +++ b/indra/cmake/run_build_test.py @@ -1,111 +1,111 @@ -#!/usr/bin/python -"""\ -@file run_build_test.py -@author Nat Goodspeed -@date 2009-09-03 -@brief Helper script to allow CMake to run some command after setting - environment variables. - -CMake has commands to run an external program. But remember that each CMake -command must be backed by multiple build-system implementations. Unfortunately -it seems CMake can't promise that every target build system can set specified -environment variables before running the external program of interest. - -This helper script is a workaround. It simply sets the requested environment -variables and then executes the program specified on the rest of its command -line. - -Example: - -python run_build_test.py -DFOO=bar myprog somearg otherarg - -sets environment variable FOO=bar, then runs: -myprog somearg otherarg - -$LicenseInfo:firstyear=2009&license=internal$ -Copyright (c) 2009, Linden Research, Inc. -$/LicenseInfo$ -""" - -import os -import sys -import subprocess - -def main(command, libpath=[], vars={}): - """Pass: - command is a sequence (e.g. a list) of strings. The first item in the list - must be the command name, the rest are its arguments. - - libpath is a sequence of directory pathnames. These will be appended to - the platform-specific dynamic library search path environment variable. - - vars is a dict of arbitrary (var, value) pairs to be added to the - environment before running 'command'. - - This function runs the specified command, waits for it to terminate and - returns its return code. This will be negative if the command terminated - with a signal, else it will be the process's specified exit code. - """ - # Handle platform-dependent libpath first. - if sys.platform == "win32": - lpvars = ["PATH"] - elif sys.platform == "darwin": - lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"] - elif sys.platform.startswith("linux"): - lpvars = ["LD_LIBRARY_PATH"] - else: - # No idea what the right pathname might be! But only crump if this - # feature is requested. - if libpath: - raise NotImplemented("run_build_test: unknown platform %s" % sys.platform) - lpvars = [] - for var in lpvars: - # Split the existing path. Bear in mind that the variable in question - # might not exist; instead of KeyError, just use an empty string. - dirs = os.environ.get(var, "").split(os.pathsep) - # Append the sequence in libpath -## print "%s += %r" % (var, libpath) - dirs.extend(libpath) - # Now rebuild the path string. This way we use a minimum of separators - # -- and we avoid adding a pointless separator when libpath is empty. - os.environ[var] = os.pathsep.join(dirs) - # Now handle arbitrary environment variables. The tricky part is ensuring - # that all the keys and values we try to pass are actually strings. -## if vars: -## print "Setting:" -## for key, value in vars.iteritems(): -## print "%s=%s" % (key, value) - os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()])) - # Run the child process. -## print "Running: %s" % " ".join(command) - return subprocess.call(command) - -if __name__ == "__main__": - from optparse import OptionParser - parser = OptionParser(usage="usage: %prog [options] command args...") - # We want optparse support for the options we ourselves handle -- but we - # DO NOT want it looking at options for the executable we intend to run, - # rejecting them as invalid because we don't define them. So configure the - # parser to stop looking for options as soon as it sees the first - # positional argument (traditional Unix syntax). - parser.disable_interspersed_args() - parser.add_option("-D", "--define", dest="vars", default=[], action="append", - metavar="VAR=value", - help="Add VAR=value to the env variables defined") - parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append", - metavar="DIR", - help="Add DIR to the platform-dependent DLL search path") - opts, args = parser.parse_args() - # What we have in opts.vars is a list of strings of the form "VAR=value" - # or possibly just "VAR". What we want is a dict. We can build that dict by - # constructing a list of ["VAR", "value"] pairs -- so split each - # "VAR=value" string on the '=' sign (but only once, in case we have - # "VAR=some=user=string"). To handle the case of just "VAR", append "" to - # the list returned by split(), then slice off anything after the pair we - # want. - rc = main(command=args, libpath=opts.libpath, - vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars])) - if rc not in (None, 0): - print >>sys.stderr, "Failure running: %s" % " ".join(args) - print >>sys.stderr, "Error: %s" % rc - sys.exit((rc < 0) and 255 or rc) +#!/usr/bin/python +"""\ +@file run_build_test.py +@author Nat Goodspeed +@date 2009-09-03 +@brief Helper script to allow CMake to run some command after setting + environment variables. + +CMake has commands to run an external program. But remember that each CMake +command must be backed by multiple build-system implementations. Unfortunately +it seems CMake can't promise that every target build system can set specified +environment variables before running the external program of interest. + +This helper script is a workaround. It simply sets the requested environment +variables and then executes the program specified on the rest of its command +line. + +Example: + +python run_build_test.py -DFOO=bar myprog somearg otherarg + +sets environment variable FOO=bar, then runs: +myprog somearg otherarg + +$LicenseInfo:firstyear=2009&license=internal$ +Copyright (c) 2009, Linden Research, Inc. +$/LicenseInfo$ +""" + +import os +import sys +import subprocess + +def main(command, libpath=[], vars={}): + """Pass: + command is a sequence (e.g. a list) of strings. The first item in the list + must be the command name, the rest are its arguments. + + libpath is a sequence of directory pathnames. These will be appended to + the platform-specific dynamic library search path environment variable. + + vars is a dict of arbitrary (var, value) pairs to be added to the + environment before running 'command'. + + This function runs the specified command, waits for it to terminate and + returns its return code. This will be negative if the command terminated + with a signal, else it will be the process's specified exit code. + """ + # Handle platform-dependent libpath first. + if sys.platform == "win32": + lpvars = ["PATH"] + elif sys.platform == "darwin": + lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"] + elif sys.platform.startswith("linux"): + lpvars = ["LD_LIBRARY_PATH"] + else: + # No idea what the right pathname might be! But only crump if this + # feature is requested. + if libpath: + raise NotImplemented("run_build_test: unknown platform %s" % sys.platform) + lpvars = [] + for var in lpvars: + # Split the existing path. Bear in mind that the variable in question + # might not exist; instead of KeyError, just use an empty string. + dirs = os.environ.get(var, "").split(os.pathsep) + # Append the sequence in libpath +## print "%s += %r" % (var, libpath) + dirs.extend(libpath) + # Now rebuild the path string. This way we use a minimum of separators + # -- and we avoid adding a pointless separator when libpath is empty. + os.environ[var] = os.pathsep.join(dirs) + # Now handle arbitrary environment variables. The tricky part is ensuring + # that all the keys and values we try to pass are actually strings. +## if vars: +## print "Setting:" +## for key, value in vars.iteritems(): +## print "%s=%s" % (key, value) + os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()])) + # Run the child process. +## print "Running: %s" % " ".join(command) + return subprocess.call(command) + +if __name__ == "__main__": + from optparse import OptionParser + parser = OptionParser(usage="usage: %prog [options] command args...") + # We want optparse support for the options we ourselves handle -- but we + # DO NOT want it looking at options for the executable we intend to run, + # rejecting them as invalid because we don't define them. So configure the + # parser to stop looking for options as soon as it sees the first + # positional argument (traditional Unix syntax). + parser.disable_interspersed_args() + parser.add_option("-D", "--define", dest="vars", default=[], action="append", + metavar="VAR=value", + help="Add VAR=value to the env variables defined") + parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append", + metavar="DIR", + help="Add DIR to the platform-dependent DLL search path") + opts, args = parser.parse_args() + # What we have in opts.vars is a list of strings of the form "VAR=value" + # or possibly just "VAR". What we want is a dict. We can build that dict by + # constructing a list of ["VAR", "value"] pairs -- so split each + # "VAR=value" string on the '=' sign (but only once, in case we have + # "VAR=some=user=string"). To handle the case of just "VAR", append "" to + # the list returned by split(), then slice off anything after the pair we + # want. + rc = main(command=args, libpath=opts.libpath, + vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars])) + if rc not in (None, 0): + print >>sys.stderr, "Failure running: %s" % " ".join(args) + print >>sys.stderr, "Error: %s" % rc + sys.exit((rc < 0) and 255 or rc) diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h index 50129b4526..0d6f18c5d4 100644 --- a/indra/llcommon/llallocator.h +++ b/indra/llcommon/llallocator.h @@ -1,63 +1,63 @@ -/** - * @file llallocator.h - * @brief Declaration of the LLAllocator class. - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLALLOCATOR_H -#define LL_LLALLOCATOR_H - -#include - -#include "llmemtype.h" -#include "llallocator_heap_profile.h" - -class LL_COMMON_API LLAllocator { - friend class LLMemoryView; - friend class LLMemType; - -private: - static void pushMemType(S32 type); - static S32 popMemType(); - -public: - void setProfilingEnabled(bool should_enable); - - static bool isProfiling(); - - LLAllocatorHeapProfile const & getProfile(); - -private: - std::string getRawProfile(); - -private: - LLAllocatorHeapProfile mProf; -}; - -#endif // LL_LLALLOCATOR_H +/** + * @file llallocator.h + * @brief Declaration of the LLAllocator class. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLALLOCATOR_H +#define LL_LLALLOCATOR_H + +#include + +#include "llmemtype.h" +#include "llallocator_heap_profile.h" + +class LL_COMMON_API LLAllocator { + friend class LLMemoryView; + friend class LLMemType; + +private: + static void pushMemType(S32 type); + static S32 popMemType(); + +public: + void setProfilingEnabled(bool should_enable); + + static bool isProfiling(); + + LLAllocatorHeapProfile const & getProfile(); + +private: + std::string getRawProfile(); + +private: + LLAllocatorHeapProfile mProf; +}; + +#endif // LL_LLALLOCATOR_H diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 141b0df43c..6c5fa5af6d 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -1,149 +1,149 @@ -/** - * @file llcoros.h - * @author Nat Goodspeed - * @date 2009-06-02 - * @brief Manage running boost::coroutine instances - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * Copyright (c) 2009, Linden Research, Inc. - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLCOROS_H) -#define LL_LLCOROS_H - -#include -#include "llsingleton.h" -#include -#include -#include -#include -#include -#include - -/** - * Registry of named Boost.Coroutine instances - * - * The Boost.Coroutine library supports the general case of a coroutine - * accepting arbitrary parameters and yielding multiple (sets of) results. For - * such use cases, it's natural for the invoking code to retain the coroutine - * instance: the consumer repeatedly calls into the coroutine, perhaps passing - * new parameter values, prompting it to yield its next result. - * - * Our typical coroutine usage is different, though. For us, coroutines - * provide an alternative to the @c Responder pattern. Our typical coroutine - * has @c void return, invoked in fire-and-forget mode: the handler for some - * user gesture launches the coroutine and promptly returns to the main loop. - * The coroutine initiates some action that will take multiple frames (e.g. a - * capability request), waits for its result, processes it and silently steals - * away. - * - * This usage poses two (related) problems: - * - * # Who should own the coroutine instance? If it's simply local to the - * handler code that launches it, return from the handler will destroy the - * coroutine object, terminating the coroutine. - * # Once the coroutine terminates, in whatever way, who's responsible for - * cleaning up the coroutine object? - * - * LLCoros is a Singleton collection of currently-active coroutine instances. - * Each has a name. You ask LLCoros to launch a new coroutine with a suggested - * name prefix; from your prefix it generates a distinct name, registers the - * new coroutine and returns the actual name. - * - * The name can be used to kill off the coroutine prematurely, if needed. It - * can also provide diagnostic info: we can look up the name of the - * currently-running coroutine. - * - * Finally, the next frame ("mainloop" event) after the coroutine terminates, - * LLCoros will notice its demise and destroy it. - */ -class LL_COMMON_API LLCoros: public LLSingleton -{ -public: - /// Canonical boost::coroutines::coroutine signature we use - typedef boost::coroutines::coroutine coro; - /// Canonical 'self' type - typedef coro::self self; - - /** - * Create and start running a new coroutine with specified name. The name - * string you pass is a suggestion; it will be tweaked for uniqueness. The - * actual name is returned to you. - * - * Usage looks like this, for (e.g.) two coroutine parameters: - * @code - * class MyClass - * { - * public: - * ... - * // Do NOT NOT NOT accept reference params other than 'self'! - * // Pass by value only! - * void myCoroutineMethod(LLCoros::self& self, std::string, LLSD); - * ... - * }; - * ... - * std::string name = LLCoros::instance().launch( - * "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1, - * "somestring", LLSD(17)); - * @endcode - * - * Your function/method must accept LLCoros::self& as its first parameter. - * It can accept any other parameters you want -- but ONLY BY VALUE! - * Other reference parameters are a BAD IDEA! You Have Been Warned. See - * DEV-32777 comments for an explanation. - * - * Pass a callable that accepts the single LLCoros::self& parameter. It - * may work to pass a free function whose only parameter is 'self'; for - * all other cases use boost::bind(). Of course, for a non-static class - * method, the first parameter must be the class instance. Use the - * placeholder _1 for the 'self' parameter. Any other parameters should be - * passed via the bind() expression. - * - * launch() tweaks the suggested name so it won't collide with any - * existing coroutine instance, creates the coroutine instance, registers - * it with the tweaked name and runs it until its first wait. At that - * point it returns the tweaked name. - */ - template - std::string launch(const std::string& prefix, const CALLABLE& callable) - { - return launchImpl(prefix, new coro(callable)); - } - - /** - * Abort a running coroutine by name. Normally, when a coroutine either - * runs to completion or terminates with an exception, LLCoros quietly - * cleans it up. This is for use only when you must explicitly interrupt - * one prematurely. Returns @c true if the specified name was found and - * still running at the time. - */ - bool kill(const std::string& name); - - /** - * From within a coroutine, pass its @c self object to look up the - * (tweaked) name string by which this coroutine is registered. Returns - * the empty string if not found (e.g. if the coroutine was launched by - * hand rather than using LLCoros::launch()). - */ - template - std::string getName(const COROUTINE_SELF& self) const - { - return getNameByID(self.get_id()); - } - - /// getName() by self.get_id() - std::string getNameByID(const void* self_id) const; - -private: - friend class LLSingleton; - LLCoros(); - std::string launchImpl(const std::string& prefix, coro* newCoro); - std::string generateDistinctName(const std::string& prefix) const; - bool cleanup(const LLSD&); - - typedef boost::ptr_map CoroMap; - CoroMap mCoros; -}; - -#endif /* ! defined(LL_LLCOROS_H) */ +/** + * @file llcoros.h + * @author Nat Goodspeed + * @date 2009-06-02 + * @brief Manage running boost::coroutine instances + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCOROS_H) +#define LL_LLCOROS_H + +#include +#include "llsingleton.h" +#include +#include +#include +#include +#include +#include + +/** + * Registry of named Boost.Coroutine instances + * + * The Boost.Coroutine library supports the general case of a coroutine + * accepting arbitrary parameters and yielding multiple (sets of) results. For + * such use cases, it's natural for the invoking code to retain the coroutine + * instance: the consumer repeatedly calls into the coroutine, perhaps passing + * new parameter values, prompting it to yield its next result. + * + * Our typical coroutine usage is different, though. For us, coroutines + * provide an alternative to the @c Responder pattern. Our typical coroutine + * has @c void return, invoked in fire-and-forget mode: the handler for some + * user gesture launches the coroutine and promptly returns to the main loop. + * The coroutine initiates some action that will take multiple frames (e.g. a + * capability request), waits for its result, processes it and silently steals + * away. + * + * This usage poses two (related) problems: + * + * # Who should own the coroutine instance? If it's simply local to the + * handler code that launches it, return from the handler will destroy the + * coroutine object, terminating the coroutine. + * # Once the coroutine terminates, in whatever way, who's responsible for + * cleaning up the coroutine object? + * + * LLCoros is a Singleton collection of currently-active coroutine instances. + * Each has a name. You ask LLCoros to launch a new coroutine with a suggested + * name prefix; from your prefix it generates a distinct name, registers the + * new coroutine and returns the actual name. + * + * The name can be used to kill off the coroutine prematurely, if needed. It + * can also provide diagnostic info: we can look up the name of the + * currently-running coroutine. + * + * Finally, the next frame ("mainloop" event) after the coroutine terminates, + * LLCoros will notice its demise and destroy it. + */ +class LL_COMMON_API LLCoros: public LLSingleton +{ +public: + /// Canonical boost::coroutines::coroutine signature we use + typedef boost::coroutines::coroutine coro; + /// Canonical 'self' type + typedef coro::self self; + + /** + * Create and start running a new coroutine with specified name. The name + * string you pass is a suggestion; it will be tweaked for uniqueness. The + * actual name is returned to you. + * + * Usage looks like this, for (e.g.) two coroutine parameters: + * @code + * class MyClass + * { + * public: + * ... + * // Do NOT NOT NOT accept reference params other than 'self'! + * // Pass by value only! + * void myCoroutineMethod(LLCoros::self& self, std::string, LLSD); + * ... + * }; + * ... + * std::string name = LLCoros::instance().launch( + * "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1, + * "somestring", LLSD(17)); + * @endcode + * + * Your function/method must accept LLCoros::self& as its first parameter. + * It can accept any other parameters you want -- but ONLY BY VALUE! + * Other reference parameters are a BAD IDEA! You Have Been Warned. See + * DEV-32777 comments for an explanation. + * + * Pass a callable that accepts the single LLCoros::self& parameter. It + * may work to pass a free function whose only parameter is 'self'; for + * all other cases use boost::bind(). Of course, for a non-static class + * method, the first parameter must be the class instance. Use the + * placeholder _1 for the 'self' parameter. Any other parameters should be + * passed via the bind() expression. + * + * launch() tweaks the suggested name so it won't collide with any + * existing coroutine instance, creates the coroutine instance, registers + * it with the tweaked name and runs it until its first wait. At that + * point it returns the tweaked name. + */ + template + std::string launch(const std::string& prefix, const CALLABLE& callable) + { + return launchImpl(prefix, new coro(callable)); + } + + /** + * Abort a running coroutine by name. Normally, when a coroutine either + * runs to completion or terminates with an exception, LLCoros quietly + * cleans it up. This is for use only when you must explicitly interrupt + * one prematurely. Returns @c true if the specified name was found and + * still running at the time. + */ + bool kill(const std::string& name); + + /** + * From within a coroutine, pass its @c self object to look up the + * (tweaked) name string by which this coroutine is registered. Returns + * the empty string if not found (e.g. if the coroutine was launched by + * hand rather than using LLCoros::launch()). + */ + template + std::string getName(const COROUTINE_SELF& self) const + { + return getNameByID(self.get_id()); + } + + /// getName() by self.get_id() + std::string getNameByID(const void* self_id) const; + +private: + friend class LLSingleton; + LLCoros(); + std::string launchImpl(const std::string& prefix, coro* newCoro); + std::string generateDistinctName(const std::string& prefix) const; + bool cleanup(const LLSD&); + + typedef boost::ptr_map CoroMap; + CoroMap mCoros; +}; + +#endif /* ! defined(LL_LLCOROS_H) */ diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 45b84ea3ea..905d736d62 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -1,317 +1,317 @@ -/** - * @file llfasttimer.h - * @brief Declaration of a fast timer. - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_FASTTIMER_H -#define LL_FASTTIMER_H - -#include "llinstancetracker.h" - -#define FAST_TIMER_ON 1 - -#if LL_WINDOWS - -// shift off lower 8 bits for lower resolution but longer term timing -// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing -inline U32 get_cpu_clock_count_32() -{ - U32 ret_val; - __asm - { - _emit 0x0f - _emit 0x31 - shr eax,8 - shl edx,24 - or eax, edx - mov dword ptr [ret_val], eax - } - return ret_val; -} - -// return full timer value, still shifted by 8 bits -inline U64 get_cpu_clock_count_64() -{ - U64 ret_val; - __asm - { - _emit 0x0f - _emit 0x31 - mov eax,eax - mov edx,edx - mov dword ptr [ret_val+4], edx - mov dword ptr [ret_val], eax - } - return ret_val >> 8; -} - -#endif // LL_WINDOWS - -#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) -inline U32 get_cpu_clock_count_32() -{ - U64 x; - __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); - return (U32)x >> 8; -} - -inline U32 get_cpu_clock_count_64() -{ - U64 x; - __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); - return x >> 8; -} -#endif - -#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__)) -// -// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock -// -// Just use gettimeofday implementation for now - -inline U32 get_cpu_clock_count_32() -{ - return (U32)get_clock_count(); -} - -inline U32 get_cpu_clock_count_64() -{ - return get_clock_count(); -} -#endif - -class LLMutex; - -#include -#include "llsd.h" - - -class LL_COMMON_API LLFastTimer -{ -public: - // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances - class LL_COMMON_API NamedTimer - : public LLInstanceTracker - { - friend class DeclareTimer; - public: - ~NamedTimer(); - - enum { HISTORY_NUM = 60 }; - - const std::string& getName() const { return mName; } - NamedTimer* getParent() const { return mParent; } - void setParent(NamedTimer* parent); - S32 getDepth(); - std::string getToolTip(S32 history_index = -1); - - typedef std::vector::const_iterator child_const_iter; - child_const_iter beginChildren(); - child_const_iter endChildren(); - std::vector& getChildren(); - - void setCollapsed(bool collapsed) { mCollapsed = collapsed; } - bool getCollapsed() const { return mCollapsed; } - - U32 getCountAverage() const { return mCountAverage; } - U32 getCallAverage() const { return mCallAverage; } - - U32 getHistoricalCount(S32 history_index = 0) const; - U32 getHistoricalCalls(S32 history_index = 0) const; - - static NamedTimer& getRootNamedTimer(); - - struct FrameState - { - FrameState(NamedTimer* timerp); - - U32 mSelfTimeCounter; - U32 mCalls; - FrameState* mParent; // info for caller timer - FrameState* mLastCaller; // used to bootstrap tree construction - NamedTimer* mTimer; - U16 mActiveCount; // number of timers with this ID active on stack - bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame - }; - - S32 getFrameStateIndex() const { return mFrameStateIndex; } - - FrameState& getFrameState() const; - - - private: - friend class LLFastTimer; - friend class NamedTimerFactory; - - // - // methods - // - NamedTimer(const std::string& name); - // recursive call to gather total time from children - static void accumulateTimings(); - - // updates cumulative times and hierarchy, - // can be called multiple times in a frame, at any point - static void processTimes(); - - static void buildHierarchy(); - static void resetFrame(); - static void reset(); - - - // - // members - // - S32 mFrameStateIndex; - - std::string mName; - - U32 mTotalTimeCounter; - - U32 mCountAverage; - U32 mCallAverage; - - U32* mCountHistory; - U32* mCallHistory; - - // tree structure - NamedTimer* mParent; // NamedTimer of caller(parent) - std::vector mChildren; - bool mCollapsed; // don't show children - bool mNeedsSorting; // sort children whenever child added - - }; - - // used to statically declare a new named timer - class LL_COMMON_API DeclareTimer - : public LLInstanceTracker - { - public: - DeclareTimer(const std::string& name, bool open); - DeclareTimer(const std::string& name); - - static void updateCachedPointers(); - - // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) - operator NamedTimer::FrameState&() { return *mFrameState; } - private: - NamedTimer& mTimer; - NamedTimer::FrameState* mFrameState; - }; - - -public: - static LLMutex* sLogLock; - static std::queue sLogQueue; - static BOOL sLog; - static BOOL sMetricLog; - - typedef std::vector info_list_t; - static info_list_t& getFrameStateList(); - - enum RootTimerMarker { ROOT }; - LLFastTimer(RootTimerMarker); - - LLFastTimer(NamedTimer::FrameState& timer) - : mFrameState(&timer) - { -#if FAST_TIMER_ON - NamedTimer::FrameState* frame_state = &timer; - U32 cur_time = get_cpu_clock_count_32(); - mStartSelfTime = cur_time; - mStartTotalTime = cur_time; - - frame_state->mActiveCount++; - frame_state->mCalls++; - // keep current parent as long as it is active when we are - frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); - - mLastTimer = sCurTimer; - sCurTimer = this; -#endif - } - - ~LLFastTimer() - { -#if FAST_TIMER_ON - NamedTimer::FrameState* frame_state = mFrameState; - U32 cur_time = get_cpu_clock_count_32(); - frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; - - frame_state->mActiveCount--; - LLFastTimer* last_timer = mLastTimer; - sCurTimer = last_timer; - - // store last caller to bootstrap tree creation - frame_state->mLastCaller = last_timer->mFrameState; - - // we are only tracking self time, so subtract our total time delta from parents - U32 total_time = cur_time - mStartTotalTime; - last_timer->mStartSelfTime += total_time; -#endif - } - - - // call this once a frame to reset timers - static void nextFrame(); - - // dumps current cumulative frame stats to log - // call nextFrame() to reset timers - static void dumpCurTimes(); - - // call this to reset timer hierarchy, averages, etc. - static void reset(); - - static U64 countsPerSecond(); - static S32 getLastFrameIndex() { return sLastFrameIndex; } - static S32 getCurFrameIndex() { return sCurFrameIndex; } - - static void writeLog(std::ostream& os); - static const NamedTimer* getTimerByName(const std::string& name); - -public: - static bool sPauseHistory; - static bool sResetHistory; - -private: - typedef std::vector timer_stack_t; - static LLFastTimer* sCurTimer; - static S32 sCurFrameIndex; - static S32 sLastFrameIndex; - static U64 sLastFrameTime; - static info_list_t* sTimerInfos; - - U32 mStartSelfTime; // start time + time of all child timers - U32 mStartTotalTime; // start time + time of all child timers - NamedTimer::FrameState* mFrameState; - LLFastTimer* mLastTimer; -}; - -#endif // LL_LLFASTTIMER_H +/** + * @file llfasttimer.h + * @brief Declaration of a fast timer. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_FASTTIMER_H +#define LL_FASTTIMER_H + +#include "llinstancetracker.h" + +#define FAST_TIMER_ON 1 + +#if LL_WINDOWS + +// shift off lower 8 bits for lower resolution but longer term timing +// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing +inline U32 get_cpu_clock_count_32() +{ + U32 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + shr eax,8 + shl edx,24 + or eax, edx + mov dword ptr [ret_val], eax + } + return ret_val; +} + +// return full timer value, still shifted by 8 bits +inline U64 get_cpu_clock_count_64() +{ + U64 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + mov eax,eax + mov edx,edx + mov dword ptr [ret_val+4], edx + mov dword ptr [ret_val], eax + } + return ret_val >> 8; +} + +#endif // LL_WINDOWS + +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +inline U32 get_cpu_clock_count_32() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return (U32)x >> 8; +} + +inline U32 get_cpu_clock_count_64() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return x >> 8; +} +#endif + +#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__)) +// +// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock +// +// Just use gettimeofday implementation for now + +inline U32 get_cpu_clock_count_32() +{ + return (U32)get_clock_count(); +} + +inline U32 get_cpu_clock_count_64() +{ + return get_clock_count(); +} +#endif + +class LLMutex; + +#include +#include "llsd.h" + + +class LL_COMMON_API LLFastTimer +{ +public: + // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances + class LL_COMMON_API NamedTimer + : public LLInstanceTracker + { + friend class DeclareTimer; + public: + ~NamedTimer(); + + enum { HISTORY_NUM = 60 }; + + const std::string& getName() const { return mName; } + NamedTimer* getParent() const { return mParent; } + void setParent(NamedTimer* parent); + S32 getDepth(); + std::string getToolTip(S32 history_index = -1); + + typedef std::vector::const_iterator child_const_iter; + child_const_iter beginChildren(); + child_const_iter endChildren(); + std::vector& getChildren(); + + void setCollapsed(bool collapsed) { mCollapsed = collapsed; } + bool getCollapsed() const { return mCollapsed; } + + U32 getCountAverage() const { return mCountAverage; } + U32 getCallAverage() const { return mCallAverage; } + + U32 getHistoricalCount(S32 history_index = 0) const; + U32 getHistoricalCalls(S32 history_index = 0) const; + + static NamedTimer& getRootNamedTimer(); + + struct FrameState + { + FrameState(NamedTimer* timerp); + + U32 mSelfTimeCounter; + U32 mCalls; + FrameState* mParent; // info for caller timer + FrameState* mLastCaller; // used to bootstrap tree construction + NamedTimer* mTimer; + U16 mActiveCount; // number of timers with this ID active on stack + bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame + }; + + S32 getFrameStateIndex() const { return mFrameStateIndex; } + + FrameState& getFrameState() const; + + + private: + friend class LLFastTimer; + friend class NamedTimerFactory; + + // + // methods + // + NamedTimer(const std::string& name); + // recursive call to gather total time from children + static void accumulateTimings(); + + // updates cumulative times and hierarchy, + // can be called multiple times in a frame, at any point + static void processTimes(); + + static void buildHierarchy(); + static void resetFrame(); + static void reset(); + + + // + // members + // + S32 mFrameStateIndex; + + std::string mName; + + U32 mTotalTimeCounter; + + U32 mCountAverage; + U32 mCallAverage; + + U32* mCountHistory; + U32* mCallHistory; + + // tree structure + NamedTimer* mParent; // NamedTimer of caller(parent) + std::vector mChildren; + bool mCollapsed; // don't show children + bool mNeedsSorting; // sort children whenever child added + + }; + + // used to statically declare a new named timer + class LL_COMMON_API DeclareTimer + : public LLInstanceTracker + { + public: + DeclareTimer(const std::string& name, bool open); + DeclareTimer(const std::string& name); + + static void updateCachedPointers(); + + // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) + operator NamedTimer::FrameState&() { return *mFrameState; } + private: + NamedTimer& mTimer; + NamedTimer::FrameState* mFrameState; + }; + + +public: + static LLMutex* sLogLock; + static std::queue sLogQueue; + static BOOL sLog; + static BOOL sMetricLog; + + typedef std::vector info_list_t; + static info_list_t& getFrameStateList(); + + enum RootTimerMarker { ROOT }; + LLFastTimer(RootTimerMarker); + + LLFastTimer(NamedTimer::FrameState& timer) + : mFrameState(&timer) + { +#if FAST_TIMER_ON + NamedTimer::FrameState* frame_state = &timer; + U32 cur_time = get_cpu_clock_count_32(); + mStartSelfTime = cur_time; + mStartTotalTime = cur_time; + + frame_state->mActiveCount++; + frame_state->mCalls++; + // keep current parent as long as it is active when we are + frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); + + mLastTimer = sCurTimer; + sCurTimer = this; +#endif + } + + ~LLFastTimer() + { +#if FAST_TIMER_ON + NamedTimer::FrameState* frame_state = mFrameState; + U32 cur_time = get_cpu_clock_count_32(); + frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; + + frame_state->mActiveCount--; + LLFastTimer* last_timer = mLastTimer; + sCurTimer = last_timer; + + // store last caller to bootstrap tree creation + frame_state->mLastCaller = last_timer->mFrameState; + + // we are only tracking self time, so subtract our total time delta from parents + U32 total_time = cur_time - mStartTotalTime; + last_timer->mStartSelfTime += total_time; +#endif + } + + + // call this once a frame to reset timers + static void nextFrame(); + + // dumps current cumulative frame stats to log + // call nextFrame() to reset timers + static void dumpCurTimes(); + + // call this to reset timer hierarchy, averages, etc. + static void reset(); + + static U64 countsPerSecond(); + static S32 getLastFrameIndex() { return sLastFrameIndex; } + static S32 getCurFrameIndex() { return sCurFrameIndex; } + + static void writeLog(std::ostream& os); + static const NamedTimer* getTimerByName(const std::string& name); + +public: + static bool sPauseHistory; + static bool sResetHistory; + +private: + typedef std::vector timer_stack_t; + static LLFastTimer* sCurTimer; + static S32 sCurFrameIndex; + static S32 sLastFrameIndex; + static U64 sLastFrameTime; + static info_list_t* sTimerInfos; + + U32 mStartSelfTime; // start time + time of all child timers + U32 mStartTotalTime; // start time + time of all child timers + NamedTimer::FrameState* mFrameState; + LLFastTimer* mLastTimer; +}; + +#endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 1c6f64dd8b..09f19532b7 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -1,65 +1,65 @@ -/** - * @file llmemory.h - * @brief Memory allocation/deallocation header-stuff goes here. - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ -#ifndef LLMEMORY_H -#define LLMEMORY_H - - - -extern S32 gTotalDAlloc; -extern S32 gTotalDAUse; -extern S32 gDACount; - -extern void* ll_allocate (size_t size); -extern void ll_release (void *p); - -class LL_COMMON_API LLMemory -{ -public: - static void initClass(); - static void cleanupClass(); - static void freeReserve(); - // Return the resident set size of the current process, in bytes. - // Return value is zero if not known. - static U64 getCurrentRSS(); -private: - static char* reserveMem; -}; - -// LLRefCount moved to llrefcount.h - -// LLPointer moved to llpointer.h - -// LLSafeHandle moved to llsafehandle.h - -// LLSingleton moved to llsingleton.h - -#endif +/** + * @file llmemory.h + * @brief Memory allocation/deallocation header-stuff goes here. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLMEMORY_H +#define LLMEMORY_H + + + +extern S32 gTotalDAlloc; +extern S32 gTotalDAUse; +extern S32 gDACount; + +extern void* ll_allocate (size_t size); +extern void ll_release (void *p); + +class LL_COMMON_API LLMemory +{ +public: + static void initClass(); + static void cleanupClass(); + static void freeReserve(); + // Return the resident set size of the current process, in bytes. + // Return value is zero if not known. + static U64 getCurrentRSS(); +private: + static char* reserveMem; +}; + +// LLRefCount moved to llrefcount.h + +// LLPointer moved to llpointer.h + +// LLSafeHandle moved to llsafehandle.h + +// LLSingleton moved to llsingleton.h + +#endif diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h index 677fad3034..5952a3a7c5 100644 --- a/indra/llcommon/llmemtype.h +++ b/indra/llcommon/llmemtype.h @@ -1,248 +1,248 @@ -/** - * @file llmemtype.h - * @brief Runtime memory usage debugging utilities. - * - * $LicenseInfo:firstyear=2005&license=viewergpl$ - * - * Copyright (c) 2005-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_MEMTYPE_H -#define LL_MEMTYPE_H - -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- - -#include "linden_common.h" -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// WARNING: Never commit with MEM_TRACK_MEM == 1 -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -#define MEM_TRACK_MEM (0 && LL_WINDOWS) - -#include - -#define MEM_TYPE_NEW(T) - -class LL_COMMON_API LLMemType -{ -public: - - // class we'll initialize all instances of as - // static members of MemType. Then use - // to construct any new mem type. - class LL_COMMON_API DeclareMemType - { - public: - DeclareMemType(char const * st); - ~DeclareMemType(); - - S32 mID; - char const * mName; - - // array so we can map an index ID to Name - static std::vector mNameList; - }; - - LLMemType(DeclareMemType& dt); - ~LLMemType(); - - static char const * getNameFromID(S32 id); - - static DeclareMemType MTYPE_INIT; - static DeclareMemType MTYPE_STARTUP; - static DeclareMemType MTYPE_MAIN; - static DeclareMemType MTYPE_FRAME; - - static DeclareMemType MTYPE_GATHER_INPUT; - static DeclareMemType MTYPE_JOY_KEY; - - static DeclareMemType MTYPE_IDLE; - static DeclareMemType MTYPE_IDLE_PUMP; - static DeclareMemType MTYPE_IDLE_NETWORK; - static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS; - static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION; - static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE; - static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY; - static DeclareMemType MTYPE_IDLE_AUDIO; - - static DeclareMemType MTYPE_CACHE_PROCESS_PENDING; - static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS; - static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES; - - static DeclareMemType MTYPE_MESSAGE_CHECK_ALL; - static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS; - - static DeclareMemType MTYPE_RENDER; - static DeclareMemType MTYPE_SLEEP; - - static DeclareMemType MTYPE_NETWORK; - static DeclareMemType MTYPE_PHYSICS; - static DeclareMemType MTYPE_INTERESTLIST; - - static DeclareMemType MTYPE_IMAGEBASE; - static DeclareMemType MTYPE_IMAGERAW; - static DeclareMemType MTYPE_IMAGEFORMATTED; - - static DeclareMemType MTYPE_APPFMTIMAGE; - static DeclareMemType MTYPE_APPRAWIMAGE; - static DeclareMemType MTYPE_APPAUXRAWIMAGE; - - static DeclareMemType MTYPE_DRAWABLE; - - static DeclareMemType MTYPE_OBJECT; - static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE; - static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE; - - static DeclareMemType MTYPE_DISPLAY; - static DeclareMemType MTYPE_DISPLAY_UPDATE; - static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA; - static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM; - static DeclareMemType MTYPE_DISPLAY_SWAP; - static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD; - static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION; - static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE; - static DeclareMemType MTYPE_DISPLAY_STATE_SORT; - static DeclareMemType MTYPE_DISPLAY_SKY; - static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM; - static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH; - static DeclareMemType MTYPE_DISPLAY_RENDER_UI; - static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS; - - static DeclareMemType MTYPE_VERTEX_DATA; - static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR; - static DeclareMemType MTYPE_VERTEX_DESTRUCTOR; - static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES; - static DeclareMemType MTYPE_VERTEX_CREATE_INDICES; - static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER; - static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES; - static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS; - static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES; - static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER; - static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER; - static DeclareMemType MTYPE_VERTEX_MAP_BUFFER; - static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES; - static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES; - static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER; - static DeclareMemType MTYPE_VERTEX_SET_STRIDE; - static DeclareMemType MTYPE_VERTEX_SET_BUFFER; - static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER; - static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS; - - static DeclareMemType MTYPE_SPACE_PARTITION; - - static DeclareMemType MTYPE_PIPELINE; - static DeclareMemType MTYPE_PIPELINE_INIT; - static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS; - static DeclareMemType MTYPE_PIPELINE_RESTORE_GL; - static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS; - static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL; - static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE; - static DeclareMemType MTYPE_PIPELINE_ADD_POOL; - static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE; - static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT; - static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS; - static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE; - static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM; - static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE; - static DeclareMemType MTYPE_PIPELINE_MARK_MOVED; - static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT; - static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS; - static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED; - static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD; - static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL; - static DeclareMemType MTYPE_PIPELINE_STATE_SORT; - static DeclareMemType MTYPE_PIPELINE_POST_SORT; - - static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS; - static DeclareMemType MTYPE_PIPELINE_RENDER_HL; - static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM; - static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED; - static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF; - static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW; - static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT; - static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS; - static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP; - static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS; - static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR; - static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM; - - static DeclareMemType MTYPE_UPKEEP_POOLS; - - static DeclareMemType MTYPE_AVATAR; - static DeclareMemType MTYPE_AVATAR_MESH; - static DeclareMemType MTYPE_PARTICLES; - static DeclareMemType MTYPE_REGIONS; - - static DeclareMemType MTYPE_INVENTORY; - static DeclareMemType MTYPE_INVENTORY_DRAW; - static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS; - static DeclareMemType MTYPE_INVENTORY_DO_FOLDER; - static DeclareMemType MTYPE_INVENTORY_POST_BUILD; - static DeclareMemType MTYPE_INVENTORY_FROM_XML; - static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM; - static DeclareMemType MTYPE_INVENTORY_VIEW_INIT; - static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW; - static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE; - - static DeclareMemType MTYPE_ANIMATION; - static DeclareMemType MTYPE_VOLUME; - static DeclareMemType MTYPE_PRIMITIVE; - - static DeclareMemType MTYPE_SCRIPT; - static DeclareMemType MTYPE_SCRIPT_RUN; - static DeclareMemType MTYPE_SCRIPT_BYTECODE; - - static DeclareMemType MTYPE_IO_PUMP; - static DeclareMemType MTYPE_IO_TCP; - static DeclareMemType MTYPE_IO_BUFFER; - static DeclareMemType MTYPE_IO_HTTP_SERVER; - static DeclareMemType MTYPE_IO_SD_SERVER; - static DeclareMemType MTYPE_IO_SD_CLIENT; - static DeclareMemType MTYPE_IO_URL_REQUEST; - - static DeclareMemType MTYPE_DIRECTX_INIT; - - static DeclareMemType MTYPE_TEMP1; - static DeclareMemType MTYPE_TEMP2; - static DeclareMemType MTYPE_TEMP3; - static DeclareMemType MTYPE_TEMP4; - static DeclareMemType MTYPE_TEMP5; - static DeclareMemType MTYPE_TEMP6; - static DeclareMemType MTYPE_TEMP7; - static DeclareMemType MTYPE_TEMP8; - static DeclareMemType MTYPE_TEMP9; - - static DeclareMemType MTYPE_OTHER; // Special; used by display code - - S32 mTypeIndex; -}; - -//---------------------------------------------------------------------------- - -#endif - +/** + * @file llmemtype.h + * @brief Runtime memory usage debugging utilities. + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_MEMTYPE_H +#define LL_MEMTYPE_H + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- + +#include "linden_common.h" +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// WARNING: Never commit with MEM_TRACK_MEM == 1 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#define MEM_TRACK_MEM (0 && LL_WINDOWS) + +#include + +#define MEM_TYPE_NEW(T) + +class LL_COMMON_API LLMemType +{ +public: + + // class we'll initialize all instances of as + // static members of MemType. Then use + // to construct any new mem type. + class LL_COMMON_API DeclareMemType + { + public: + DeclareMemType(char const * st); + ~DeclareMemType(); + + S32 mID; + char const * mName; + + // array so we can map an index ID to Name + static std::vector mNameList; + }; + + LLMemType(DeclareMemType& dt); + ~LLMemType(); + + static char const * getNameFromID(S32 id); + + static DeclareMemType MTYPE_INIT; + static DeclareMemType MTYPE_STARTUP; + static DeclareMemType MTYPE_MAIN; + static DeclareMemType MTYPE_FRAME; + + static DeclareMemType MTYPE_GATHER_INPUT; + static DeclareMemType MTYPE_JOY_KEY; + + static DeclareMemType MTYPE_IDLE; + static DeclareMemType MTYPE_IDLE_PUMP; + static DeclareMemType MTYPE_IDLE_NETWORK; + static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS; + static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION; + static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE; + static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY; + static DeclareMemType MTYPE_IDLE_AUDIO; + + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING; + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS; + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES; + + static DeclareMemType MTYPE_MESSAGE_CHECK_ALL; + static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS; + + static DeclareMemType MTYPE_RENDER; + static DeclareMemType MTYPE_SLEEP; + + static DeclareMemType MTYPE_NETWORK; + static DeclareMemType MTYPE_PHYSICS; + static DeclareMemType MTYPE_INTERESTLIST; + + static DeclareMemType MTYPE_IMAGEBASE; + static DeclareMemType MTYPE_IMAGERAW; + static DeclareMemType MTYPE_IMAGEFORMATTED; + + static DeclareMemType MTYPE_APPFMTIMAGE; + static DeclareMemType MTYPE_APPRAWIMAGE; + static DeclareMemType MTYPE_APPAUXRAWIMAGE; + + static DeclareMemType MTYPE_DRAWABLE; + + static DeclareMemType MTYPE_OBJECT; + static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE; + static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE; + + static DeclareMemType MTYPE_DISPLAY; + static DeclareMemType MTYPE_DISPLAY_UPDATE; + static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA; + static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM; + static DeclareMemType MTYPE_DISPLAY_SWAP; + static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD; + static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION; + static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE; + static DeclareMemType MTYPE_DISPLAY_STATE_SORT; + static DeclareMemType MTYPE_DISPLAY_SKY; + static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM; + static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH; + static DeclareMemType MTYPE_DISPLAY_RENDER_UI; + static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS; + + static DeclareMemType MTYPE_VERTEX_DATA; + static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR; + static DeclareMemType MTYPE_VERTEX_DESTRUCTOR; + static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES; + static DeclareMemType MTYPE_VERTEX_CREATE_INDICES; + static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER; + static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES; + static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS; + static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES; + static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER; + static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES; + static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER; + static DeclareMemType MTYPE_VERTEX_SET_STRIDE; + static DeclareMemType MTYPE_VERTEX_SET_BUFFER; + static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER; + static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS; + + static DeclareMemType MTYPE_SPACE_PARTITION; + + static DeclareMemType MTYPE_PIPELINE; + static DeclareMemType MTYPE_PIPELINE_INIT; + static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS; + static DeclareMemType MTYPE_PIPELINE_RESTORE_GL; + static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS; + static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL; + static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE; + static DeclareMemType MTYPE_PIPELINE_ADD_POOL; + static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE; + static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT; + static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE; + static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM; + static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE; + static DeclareMemType MTYPE_PIPELINE_MARK_MOVED; + static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT; + static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED; + static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD; + static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL; + static DeclareMemType MTYPE_PIPELINE_STATE_SORT; + static DeclareMemType MTYPE_PIPELINE_POST_SORT; + + static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS; + static DeclareMemType MTYPE_PIPELINE_RENDER_HL; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW; + static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT; + static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS; + static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP; + static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR; + static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM; + + static DeclareMemType MTYPE_UPKEEP_POOLS; + + static DeclareMemType MTYPE_AVATAR; + static DeclareMemType MTYPE_AVATAR_MESH; + static DeclareMemType MTYPE_PARTICLES; + static DeclareMemType MTYPE_REGIONS; + + static DeclareMemType MTYPE_INVENTORY; + static DeclareMemType MTYPE_INVENTORY_DRAW; + static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS; + static DeclareMemType MTYPE_INVENTORY_DO_FOLDER; + static DeclareMemType MTYPE_INVENTORY_POST_BUILD; + static DeclareMemType MTYPE_INVENTORY_FROM_XML; + static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM; + static DeclareMemType MTYPE_INVENTORY_VIEW_INIT; + static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW; + static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE; + + static DeclareMemType MTYPE_ANIMATION; + static DeclareMemType MTYPE_VOLUME; + static DeclareMemType MTYPE_PRIMITIVE; + + static DeclareMemType MTYPE_SCRIPT; + static DeclareMemType MTYPE_SCRIPT_RUN; + static DeclareMemType MTYPE_SCRIPT_BYTECODE; + + static DeclareMemType MTYPE_IO_PUMP; + static DeclareMemType MTYPE_IO_TCP; + static DeclareMemType MTYPE_IO_BUFFER; + static DeclareMemType MTYPE_IO_HTTP_SERVER; + static DeclareMemType MTYPE_IO_SD_SERVER; + static DeclareMemType MTYPE_IO_SD_CLIENT; + static DeclareMemType MTYPE_IO_URL_REQUEST; + + static DeclareMemType MTYPE_DIRECTX_INIT; + + static DeclareMemType MTYPE_TEMP1; + static DeclareMemType MTYPE_TEMP2; + static DeclareMemType MTYPE_TEMP3; + static DeclareMemType MTYPE_TEMP4; + static DeclareMemType MTYPE_TEMP5; + static DeclareMemType MTYPE_TEMP6; + static DeclareMemType MTYPE_TEMP7; + static DeclareMemType MTYPE_TEMP8; + static DeclareMemType MTYPE_TEMP9; + + static DeclareMemType MTYPE_OTHER; // Special; used by display code + + S32 mTypeIndex; +}; + +//---------------------------------------------------------------------------- + +#endif + diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 48244480b1..48baa50edb 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -1,168 +1,168 @@ -/** - * @file llpreprocessor.h - * @brief This file should be included in all Linden Lab files and - * should only contain special preprocessor directives - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLPREPROCESSOR_H -#define LLPREPROCESSOR_H - -// Figure out endianness of platform -#ifdef LL_LINUX -#define __ENABLE_WSTRING -#include -#endif // LL_LINUX - -#if LL_SOLARIS -# ifdef __sparc // Since we're talking Solaris 10 and up, only 64 bit is supported. -# define LL_BIG_ENDIAN 1 -# define LL_SOLARIS_ALIGNED_CPU 1 // used to designate issues where SPARC alignment is addressed -# define LL_SOLARIS_NON_MESA_GL 1 // The SPARC GL does not provide a MESA-based GL API -# endif -# include // ensure we know which end is up -#endif // LL_SOLARIS - -#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386))) -#define LL_LITTLE_ENDIAN 1 -#else -#define LL_BIG_ENDIAN 1 -#endif - -// Per-compiler switches -#ifdef __GNUC__ -#define LL_FORCE_INLINE inline __attribute__((always_inline)) -#else -#define LL_FORCE_INLINE __forceinline -#endif - -// Figure out differences between compilers -#if defined(__GNUC__) - #define GCC_VERSION (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) - #ifndef LL_GNUC - #define LL_GNUC 1 - #endif -#elif defined(__MSVC_VER__) || defined(_MSC_VER) - #ifndef LL_MSVC - #define LL_MSVC 1 - #endif - #if _MSC_VER < 1400 - #define LL_MSVC7 //Visual C++ 2003 or earlier - #endif -#endif - -// Deal with minor differences on Unixy OSes. -#if LL_DARWIN || LL_LINUX - // Different name, same functionality. - #define stricmp strcasecmp - #define strnicmp strncasecmp - - // Not sure why this is different, but... - #ifndef MAX_PATH - #define MAX_PATH PATH_MAX - #endif // not MAX_PATH - -#endif - - -// Static linking with apr on windows needs to be declared. -#if LL_WINDOWS && !LL_COMMON_LINK_SHARED -#ifndef APR_DECLARE_STATIC -#define APR_DECLARE_STATIC // For APR on Windows -#endif -#ifndef APU_DECLARE_STATIC -#define APU_DECLARE_STATIC // For APR util on Windows -#endif -#endif - -#if defined(LL_WINDOWS) -#define BOOST_REGEX_NO_LIB 1 -#define CURL_STATICLIB 1 -#ifndef XML_STATIC -#define XML_STATIC -#endif -#endif // LL_WINDOWS - - -// Deal with VC6 problems -#if LL_MSVC -#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4. -#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4. -#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4. -//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4. -#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function -#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden" -#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" -#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden -#pragma warning( disable : 4284 ) // silly MS warning deep inside their include file -#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. -#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) -#pragma warning( disable : 4996 ) // warning: deprecated - -// level 4 warnings that we need to disable: -#pragma warning (disable : 4100) // unreferenced formal parameter -#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) ) -#pragma warning (disable : 4244) // possible loss of data on conversions -#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template -#pragma warning (disable : 4512) // assignment operator could not be generated -#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) ) - -#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class -#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class -#endif // LL_MSVC - -#if LL_WINDOWS -#define LL_DLLEXPORT __declspec(dllexport) -#define LL_DLLIMPORT __declspec(dllimport) -#elif LL_LINUX -#define LL_DLLEXPORT __attribute__ ((visibility("default"))) -#define LL_DLLIMPORT -#else -#define LL_DLLEXPORT -#define LL_DLLIMPORT -#endif // LL_WINDOWS - -#if LL_COMMON_LINK_SHARED -// CMake automagically defines llcommon_EXPORTS only when building llcommon -// sources, and only when llcommon is a shared library (i.e. when -// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because -// otherwise we can't distinguish between (non-llcommon source) and (llcommon -// not shared). -# if defined(llcommon_EXPORTS) -# define LL_COMMON_API LL_DLLEXPORT -# else //llcommon_EXPORTS -# define LL_COMMON_API LL_DLLIMPORT -# endif //llcommon_EXPORTS -#else // LL_COMMON_LINK_SHARED -# define LL_COMMON_API -#endif // LL_COMMON_LINK_SHARED - -#endif // not LL_LINDEN_PREPROCESSOR_H +/** + * @file llpreprocessor.h + * @brief This file should be included in all Linden Lab files and + * should only contain special preprocessor directives + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLPREPROCESSOR_H +#define LLPREPROCESSOR_H + +// Figure out endianness of platform +#ifdef LL_LINUX +#define __ENABLE_WSTRING +#include +#endif // LL_LINUX + +#if LL_SOLARIS +# ifdef __sparc // Since we're talking Solaris 10 and up, only 64 bit is supported. +# define LL_BIG_ENDIAN 1 +# define LL_SOLARIS_ALIGNED_CPU 1 // used to designate issues where SPARC alignment is addressed +# define LL_SOLARIS_NON_MESA_GL 1 // The SPARC GL does not provide a MESA-based GL API +# endif +# include // ensure we know which end is up +#endif // LL_SOLARIS + +#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386))) +#define LL_LITTLE_ENDIAN 1 +#else +#define LL_BIG_ENDIAN 1 +#endif + +// Per-compiler switches +#ifdef __GNUC__ +#define LL_FORCE_INLINE inline __attribute__((always_inline)) +#else +#define LL_FORCE_INLINE __forceinline +#endif + +// Figure out differences between compilers +#if defined(__GNUC__) + #define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + #ifndef LL_GNUC + #define LL_GNUC 1 + #endif +#elif defined(__MSVC_VER__) || defined(_MSC_VER) + #ifndef LL_MSVC + #define LL_MSVC 1 + #endif + #if _MSC_VER < 1400 + #define LL_MSVC7 //Visual C++ 2003 or earlier + #endif +#endif + +// Deal with minor differences on Unixy OSes. +#if LL_DARWIN || LL_LINUX + // Different name, same functionality. + #define stricmp strcasecmp + #define strnicmp strncasecmp + + // Not sure why this is different, but... + #ifndef MAX_PATH + #define MAX_PATH PATH_MAX + #endif // not MAX_PATH + +#endif + + +// Static linking with apr on windows needs to be declared. +#if LL_WINDOWS && !LL_COMMON_LINK_SHARED +#ifndef APR_DECLARE_STATIC +#define APR_DECLARE_STATIC // For APR on Windows +#endif +#ifndef APU_DECLARE_STATIC +#define APU_DECLARE_STATIC // For APR util on Windows +#endif +#endif + +#if defined(LL_WINDOWS) +#define BOOST_REGEX_NO_LIB 1 +#define CURL_STATICLIB 1 +#ifndef XML_STATIC +#define XML_STATIC +#endif +#endif // LL_WINDOWS + + +// Deal with VC6 problems +#if LL_MSVC +#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4. +#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4. +#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4. +//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4. +#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function +#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden" +#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" +#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden +#pragma warning( disable : 4284 ) // silly MS warning deep inside their include file +#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. +#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning( disable : 4996 ) // warning: deprecated + +// level 4 warnings that we need to disable: +#pragma warning (disable : 4100) // unreferenced formal parameter +#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) ) +#pragma warning (disable : 4244) // possible loss of data on conversions +#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template +#pragma warning (disable : 4512) // assignment operator could not be generated +#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) ) + +#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class +#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class +#endif // LL_MSVC + +#if LL_WINDOWS +#define LL_DLLEXPORT __declspec(dllexport) +#define LL_DLLIMPORT __declspec(dllimport) +#elif LL_LINUX +#define LL_DLLEXPORT __attribute__ ((visibility("default"))) +#define LL_DLLIMPORT +#else +#define LL_DLLEXPORT +#define LL_DLLIMPORT +#endif // LL_WINDOWS + +#if LL_COMMON_LINK_SHARED +// CMake automagically defines llcommon_EXPORTS only when building llcommon +// sources, and only when llcommon is a shared library (i.e. when +// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because +// otherwise we can't distinguish between (non-llcommon source) and (llcommon +// not shared). +# if defined(llcommon_EXPORTS) +# define LL_COMMON_API LL_DLLEXPORT +# else //llcommon_EXPORTS +# define LL_COMMON_API LL_DLLIMPORT +# endif //llcommon_EXPORTS +#else // LL_COMMON_LINK_SHARED +# define LL_COMMON_API +#endif // LL_COMMON_LINK_SHARED + +#endif // not LL_LINDEN_PREPROCESSOR_H diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index 6558df70a4..3cb074257b 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -1,142 +1,142 @@ -/** - * @file llstacktrace.cpp - * @brief stack tracing functionality - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llstacktrace.h" - -#ifdef LL_WINDOWS - -#include -#include - -#include "windows.h" -#include "Dbghelp.h" - -typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( - IN ULONG frames_to_skip, - IN ULONG frames_to_capture, - OUT PVOID *backtrace, - OUT PULONG backtrace_hash); - -static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = - (RtlCaptureStackBackTrace_Function*) - GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); - -bool ll_get_stack_trace(std::vector& lines) -{ - const S32 MAX_STACK_DEPTH = 32; - const S32 STRING_NAME_LENGTH = 200; - const S32 FRAME_SKIP = 2; - static BOOL symbolsLoaded = false; - static BOOL firstCall = true; - - HANDLE hProc = GetCurrentProcess(); - - // load the symbols if they're not loaded - if(!symbolsLoaded && firstCall) - { - symbolsLoaded = SymInitialize(hProc, NULL, true); - firstCall = false; - } - - // if loaded, get the call stack - if(symbolsLoaded) - { - // create the frames to hold the addresses - void* frames[MAX_STACK_DEPTH]; - memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); - S32 depth = 0; - - // get the addresses - depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); - - IMAGEHLP_LINE64 line; - memset(&line, 0, sizeof(IMAGEHLP_LINE64)); - line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - - // create something to hold address info - PIMAGEHLP_SYMBOL64 pSym; - pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); - memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); - pSym->MaxNameLength = STRING_NAME_LENGTH; - pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); - - // get address info for each address frame - // and store - for(S32 i=0; i < depth; i++) - { - std::stringstream stack_line; - BOOL ret; - - DWORD64 addr = (DWORD64)frames[i]; - ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); - if(ret) - { - stack_line << pSym->Name << " "; - } - - DWORD dummy; - ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); - if(ret) - { - std::string file_name = line.FileName; - std::string::size_type index = file_name.rfind("\\"); - stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; - } - - lines.push_back(stack_line.str()); - } - - free(pSym); - - // TODO: figure out a way to cleanup symbol loading - // Not hugely necessary, however. - //SymCleanup(hProc); - return true; - } - else - { - lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); - } - - return false; -} - -#else - -bool ll_get_stack_trace(std::vector& lines) -{ - return false; -} - -#endif - +/** + * @file llstacktrace.cpp + * @brief stack tracing functionality + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llstacktrace.h" + +#ifdef LL_WINDOWS + +#include +#include + +#include "windows.h" +#include "Dbghelp.h" + +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( + IN ULONG frames_to_skip, + IN ULONG frames_to_capture, + OUT PVOID *backtrace, + OUT PULONG backtrace_hash); + +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = + (RtlCaptureStackBackTrace_Function*) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); + +bool ll_get_stack_trace(std::vector& lines) +{ + const S32 MAX_STACK_DEPTH = 32; + const S32 STRING_NAME_LENGTH = 200; + const S32 FRAME_SKIP = 2; + static BOOL symbolsLoaded = false; + static BOOL firstCall = true; + + HANDLE hProc = GetCurrentProcess(); + + // load the symbols if they're not loaded + if(!symbolsLoaded && firstCall) + { + symbolsLoaded = SymInitialize(hProc, NULL, true); + firstCall = false; + } + + // if loaded, get the call stack + if(symbolsLoaded) + { + // create the frames to hold the addresses + void* frames[MAX_STACK_DEPTH]; + memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); + S32 depth = 0; + + // get the addresses + depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); + + IMAGEHLP_LINE64 line; + memset(&line, 0, sizeof(IMAGEHLP_LINE64)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + // create something to hold address info + PIMAGEHLP_SYMBOL64 pSym; + pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + pSym->MaxNameLength = STRING_NAME_LENGTH; + pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + // get address info for each address frame + // and store + for(S32 i=0; i < depth; i++) + { + std::stringstream stack_line; + BOOL ret; + + DWORD64 addr = (DWORD64)frames[i]; + ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); + if(ret) + { + stack_line << pSym->Name << " "; + } + + DWORD dummy; + ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); + if(ret) + { + std::string file_name = line.FileName; + std::string::size_type index = file_name.rfind("\\"); + stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; + } + + lines.push_back(stack_line.str()); + } + + free(pSym); + + // TODO: figure out a way to cleanup symbol loading + // Not hugely necessary, however. + //SymCleanup(hProc); + return true; + } + else + { + lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); + } + + return false; +} + +#else + +bool ll_get_stack_trace(std::vector& lines) +{ + return false; +} + +#endif + diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h index 9f857f0fd3..b84b1aa6ad 100644 --- a/indra/llcommon/llstacktrace.h +++ b/indra/llcommon/llstacktrace.h @@ -1,44 +1,44 @@ -/** - * @file llstacktrace.h - * @brief stack trace functions - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#ifndef LL_LLSTACKTRACE_H -#define LL_LLSTACKTRACE_H - -#include "stdtypes.h" -#include -#include - -LL_COMMON_API bool ll_get_stack_trace(std::vector& lines); - -#endif - +/** + * @file llstacktrace.h + * @brief stack trace functions + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_LLSTACKTRACE_H +#define LL_LLSTACKTRACE_H + +#include "stdtypes.h" +#include +#include + +LL_COMMON_API bool ll_get_stack_trace(std::vector& lines); + +#endif + diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 31e70e0fe4..edbb007f61 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -1,1300 +1,1300 @@ -/** - * @file llstring.h - * @brief String utility functions and std::string class. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLSTRING_H -#define LL_LLSTRING_H - -#include -#include -#include -#include -#include "llsd.h" -#include "llfasttimer.h" - -#if LL_LINUX || LL_SOLARIS -#include -#include -#endif - -#include - -#if LL_SOLARIS -// stricmp and strnicmp do not exist on Solaris: -#define stricmp strcasecmp -#define strnicmp strncasecmp -#endif - -const char LL_UNKNOWN_CHAR = '?'; - -#if LL_DARWIN || LL_LINUX || LL_SOLARIS -// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already) -#include - -namespace std -{ -template<> -struct char_traits -{ - typedef U16 char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - typedef mbstate_t state_type; - - static void - assign(char_type& __c1, const char_type& __c2) - { __c1 = __c2; } - - static bool - eq(const char_type& __c1, const char_type& __c2) - { return __c1 == __c2; } - - static bool - lt(const char_type& __c1, const char_type& __c2) - { return __c1 < __c2; } - - static int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { return memcmp(__s1, __s2, __n * sizeof(char_type)); } - - static size_t - length(const char_type* __s) - { - const char_type *cur_char = __s; - while (*cur_char != 0) - { - ++cur_char; - } - return cur_char - __s; - } - - static const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { return static_cast(memchr(__s, __a, __n * sizeof(char_type))); } - - static char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { return static_cast(memmove(__s1, __s2, __n * sizeof(char_type))); } - - static char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { return static_cast(memcpy(__s1, __s2, __n * sizeof(char_type))); } /* Flawfinder: ignore */ - - static char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - // This isn't right. - //return static_cast(memset(__s, __a, __n * sizeof(char_type))); - - // I don't think there's a standard 'memset' for 16-bit values. - // Do this the old-fashioned way. - - size_t __i; - for(__i = 0; __i < __n; __i++) - { - __s[__i] = __a; - } - return __s; - } - - static char_type - to_char_type(const int_type& __c) - { return static_cast(__c); } - - static int_type - to_int_type(const char_type& __c) - { return static_cast(__c); } - - static bool - eq_int_type(const int_type& __c1, const int_type& __c2) - { return __c1 == __c2; } - - static int_type - eof() { return static_cast(EOF); } - - static int_type - not_eof(const int_type& __c) - { return (__c == eof()) ? 0 : __c; } - }; -}; -#endif - -class LL_COMMON_API LLStringOps -{ -private: - static long sPacificTimeOffset; - static long sLocalTimeOffset; - static bool sPacificDaylightTime; - static std::map datetimeToCodes; - -public: - static char toUpper(char elem) { return toupper((unsigned char)elem); } - static llwchar toUpper(llwchar elem) { return towupper(elem); } - - static char toLower(char elem) { return tolower((unsigned char)elem); } - static llwchar toLower(llwchar elem) { return towlower(elem); } - - static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; } - static bool isSpace(llwchar elem) { return iswspace(elem) != 0; } - - static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; } - static bool isUpper(llwchar elem) { return iswupper(elem) != 0; } - - static bool isLower(char elem) { return islower((unsigned char)elem) != 0; } - static bool isLower(llwchar elem) { return iswlower(elem) != 0; } - - static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; } - static bool isDigit(llwchar a) { return iswdigit(a) != 0; } - - static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } - static bool isPunct(llwchar a) { return iswpunct(a) != 0; } - - static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } - static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } - - static S32 collate(const char* a, const char* b) { return strcoll(a, b); } - static S32 collate(const llwchar* a, const llwchar* b); - - static void setupDatetimeInfo(bool pacific_daylight_time); - static long getPacificTimeOffset(void) { return sPacificTimeOffset;} - static long getLocalTimeOffset(void) { return sLocalTimeOffset;} - // Is the Pacific time zone (aka server time zone) - // currently in daylight savings time? - static bool getPacificDaylightTime(void) { return sPacificDaylightTime;} - - static std::string getDatetimeCode (std::string key); -}; - -/** - * @brief Return a string constructed from in without crashing if the - * pointer is NULL. - */ -LL_COMMON_API std::string ll_safe_string(const char* in); -LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen); - - -// Allowing assignments from non-strings into format_map_t is apparently -// *really* error-prone, so subclass std::string with just basic c'tors. -class LLFormatMapString -{ -public: - LLFormatMapString() {}; - LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {}; - LLFormatMapString(const std::string& s) : mString(s) {}; - operator std::string() const { return mString; } - bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; } - std::size_t length() const { return mString.length(); } - -private: - std::string mString; -}; - -template -class LLStringUtilBase -{ -private: - static std::string sLocale; - -public: - typedef typename std::basic_string::size_type size_type; - -public: - ///////////////////////////////////////////////////////////////////////////////////////// - // Static Utility functions that operate on std::strings - - static std::basic_string null; - - typedef std::map format_map_t; - LL_COMMON_API static void getTokens(const std::basic_string& instr, std::vector >& tokens, const std::basic_string& delims); - LL_COMMON_API static void formatNumber(std::basic_string& numStr, std::basic_string decimals); - LL_COMMON_API static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, S32 secFromEpoch); - LL_COMMON_API static S32 format(std::basic_string& s, const format_map_t& substitutions); - LL_COMMON_API static S32 format(std::basic_string& s, const LLSD& substitutions); - LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const format_map_t& substitutions); - LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); - static void setLocale (std::string inLocale) {sLocale = inLocale;}; - static std::string getLocale (void) {return sLocale;}; - - static bool isValidIndex(const std::basic_string& string, size_type i) - { - return !string.empty() && (0 <= i) && (i <= string.size()); - } - - static void trimHead(std::basic_string& string); - static void trimTail(std::basic_string& string); - static void trim(std::basic_string& string) { trimHead(string); trimTail(string); } - static void truncate(std::basic_string& string, size_type count); - - static void toUpper(std::basic_string& string); - static void toLower(std::basic_string& string); - - // True if this is the head of s. - static BOOL isHead( const std::basic_string& string, const T* s ); - - /** - * @brief Returns true if string starts with substr - * - * If etither string or substr are empty, this method returns false. - */ - static bool startsWith( - const std::basic_string& string, - const std::basic_string& substr); - - /** - * @brief Returns true if string ends in substr - * - * If etither string or substr are empty, this method returns false. - */ - static bool endsWith( - const std::basic_string& string, - const std::basic_string& substr); - - static void addCRLF(std::basic_string& string); - static void removeCRLF(std::basic_string& string); - - static void replaceTabsWithSpaces( std::basic_string& string, size_type spaces_per_tab ); - static void replaceNonstandardASCII( std::basic_string& string, T replacement ); - static void replaceChar( std::basic_string& string, T target, T replacement ); - static void replaceString( std::basic_string& string, std::basic_string target, std::basic_string replacement ); - - static BOOL containsNonprintable(const std::basic_string& string); - static void stripNonprintable(std::basic_string& string); - - /** - * @brief Unsafe way to make ascii characters. You should probably - * only call this when interacting with the host operating system. - * The 1 byte std::string does not work correctly. - * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII - * should work. - */ - static void _makeASCII(std::basic_string& string); - - // Conversion to other data types - static BOOL convertToBOOL(const std::basic_string& string, BOOL& value); - static BOOL convertToU8(const std::basic_string& string, U8& value); - static BOOL convertToS8(const std::basic_string& string, S8& value); - static BOOL convertToS16(const std::basic_string& string, S16& value); - static BOOL convertToU16(const std::basic_string& string, U16& value); - static BOOL convertToU32(const std::basic_string& string, U32& value); - static BOOL convertToS32(const std::basic_string& string, S32& value); - static BOOL convertToF32(const std::basic_string& string, F32& value); - static BOOL convertToF64(const std::basic_string& string, F64& value); - - ///////////////////////////////////////////////////////////////////////////////////////// - // Utility functions for working with char*'s and strings - - // Like strcmp but also handles empty strings. Uses - // current locale. - static S32 compareStrings(const T* lhs, const T* rhs); - static S32 compareStrings(const std::basic_string& lhs, const std::basic_string& rhs); - - // case insensitive version of above. Uses current locale on - // Win32, and falls back to a non-locale aware comparison on - // Linux. - static S32 compareInsensitive(const T* lhs, const T* rhs); - static S32 compareInsensitive(const std::basic_string& lhs, const std::basic_string& rhs); - - // Case sensitive comparison with good handling of numbers. Does not use current locale. - // a.k.a. strdictcmp() - static S32 compareDict(const std::basic_string& a, const std::basic_string& b); - - // Case *in*sensitive comparison with good handling of numbers. Does not use current locale. - // a.k.a. strdictcmp() - static S32 compareDictInsensitive(const std::basic_string& a, const std::basic_string& b); - - // Puts compareDict() in a form appropriate for LL container classes to use for sorting. - static BOOL precedesDict( const std::basic_string& a, const std::basic_string& b ); - - // A replacement for strncpy. - // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds - // up to dst_size-1 characters of src. - static void copy(T* dst, const T* src, size_type dst_size); - - // Copies src into dst at a given offset. - static void copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset); - - static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } - - -#ifdef _DEBUG - LL_COMMON_API static void testHarness(); -#endif - -private: - LL_COMMON_API static size_type getSubstitution(const std::basic_string& instr, size_type& start, std::vector >& tokens); -}; - -template std::basic_string LLStringUtilBase::null; -template std::string LLStringUtilBase::sLocale; - -typedef LLStringUtilBase LLStringUtil; -typedef LLStringUtilBase LLWStringUtil; -typedef std::basic_string LLWString; - -//@ Use this where we want to disallow input in the form of "foo" -// This is used to catch places where english text is embedded in the code -// instead of in a translatable XUI file. -class LLStringExplicit : public std::string -{ -public: - explicit LLStringExplicit(const char* s) : std::string(s) {} - LLStringExplicit(const std::string& s) : std::string(s) {} - LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {} -}; - -struct LLDictionaryLess -{ -public: - bool operator()(const std::string& a, const std::string& b) - { - return (LLStringUtil::precedesDict(a, b) ? true : false); - } -}; - - -/** - * Simple support functions - */ - -/** - * @brief chop off the trailing characters in a string. - * - * This function works on bytes rather than glyphs, so this will - * incorrectly truncate non-single byte strings. - * Use utf8str_truncate() for utf8 strings - * @return a copy of in string minus the trailing count bytes. - */ -inline std::string chop_tail_copy( - const std::string& in, - std::string::size_type count) -{ - return std::string(in, 0, in.length() - count); -} - -/** - * @brief This translates a nybble stored as a hex value from 0-f back - * to a nybble in the low order bits of the return byte. - */ -LL_COMMON_API U8 hex_as_nybble(char hex); - -/** - * @brief read the contents of a file into a string. - * - * Since this function has no concept of character encoding, most - * anything you do with this method ill-advised. Please avoid. - * @param str [out] The string which will have. - * @param filename The full name of the file to read. - * @return Returns true on success. If false, str is unmodified. - */ -LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename); -LL_COMMON_API bool iswindividual(llwchar elem); - -/** - * Unicode support - */ - -// Make the incoming string a utf8 string. Replaces any unknown glyph -// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest -// of the data may not be recovered. -LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw); - -// -// We should never use UTF16 except when communicating with Win32! -// -typedef std::basic_string llutf16string; - -LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); -LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); - -LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); -LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str); - -LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); -LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str ); - -LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); -LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str); -// Same function, better name. JC -inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } - -// -LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars); - -LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); -LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str); - -LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); -LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str); - -// Length of this UTF32 string in bytes when transformed to UTF8 -LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); - -// Length in bytes of this wide char in a UTF8 string -LL_COMMON_API S32 wchar_utf8_length(const llwchar wc); - -LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str); - -// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string. -LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len); - -// Length in utf16string (UTF-16) of wlen wchars beginning at woffset. -LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); - -// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) -LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); - -/** - * @brief Properly truncate a utf8 string to a maximum byte count. - * - * The returned string may be less than max_len if the truncation - * happens in the middle of a glyph. If max_len is longer than the - * string passed in, the return value == utf8str. - * @param utf8str A valid utf8 string to truncate. - * @param max_len The maximum number of bytes in the return value. - * @return Returns a valid utf8 string with byte count <= max_len. - */ -LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len); - -LL_COMMON_API std::string utf8str_trim(const std::string& utf8str); - -LL_COMMON_API S32 utf8str_compare_insensitive( - const std::string& lhs, - const std::string& rhs); - -/** - * @brief Replace all occurences of target_char with replace_char - * - * @param utf8str A utf8 string to process. - * @param target_char The wchar to be replaced - * @param replace_char The wchar which is written on replace - */ -LL_COMMON_API std::string utf8str_substChar( - const std::string& utf8str, - const llwchar target_char, - const llwchar replace_char); - -LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str); - -// Hack - used for evil notecards. -LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str); - -LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); - - -#if LL_WINDOWS -/* @name Windows string helpers - */ -//@{ - -/** - * @brief Implementation the expected snprintf interface. - * - * If the size of the passed in buffer is not large enough to hold the string, - * two bad things happen: - * 1. resulting formatted string is NOT null terminated - * 2. Depending on the platform, the return value could be a) the required - * size of the buffer to copy the entire formatted string or b) -1. - * On Windows with VS.Net 2003, it returns -1 e.g. - * - * safe_snprintf always adds a NULL terminator so that the caller does not - * need to check for return value or need to add the NULL terminator. - * It does not, however change the return value - to let the caller know - * that the passed in buffer size was not large enough to hold the - * formatted string. - * - */ - -// Deal with the differeneces on Windows -namespace snprintf_hack -{ - LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...); -} - -using snprintf_hack::snprintf; - -/** - * @brief Convert a wide string to std::string - * - * This replaces the unsafe W2A macro from ATL. - */ -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); - -//@} -#endif // LL_WINDOWS - -/** - * Many of the 'strip' and 'replace' methods of LLStringUtilBase need - * specialization to work with the signed char type. - * Sadly, it is not possible (AFAIK) to specialize a single method of - * a template class. - * That stuff should go here. - */ -namespace LLStringFn -{ - /** - * @brief Replace all non-printable characters with replacement in - * string. - * NOTE - this will zap non-ascii - * - * @param [in,out] string the to modify. out value is the string - * with zero non-printable characters. - * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. - */ - LL_COMMON_API void replace_nonprintable_in_ascii( - std::basic_string& string, - char replacement); - - - /** - * @brief Replace all non-printable characters and pipe characters - * with replacement in a string. - * NOTE - this will zap non-ascii - * - * @param [in,out] the string to modify. out value is the string - * with zero non-printable characters and zero pipe characters. - * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. - */ - LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string& str, - char replacement); - - - /** - * @brief Remove all characters that are not allowed in XML 1.0. - * Returns a copy of the string with those characters removed. - * Works with US ASCII and UTF-8 encoded strings. JC - */ - LL_COMMON_API std::string strip_invalid_xml(const std::string& input); - - - /** - * @brief Replace all control characters (0 <= c < 0x20) with replacement in - * string. This is safe for utf-8 - * - * @param [in,out] string the to modify. out value is the string - * with zero non-printable characters. - * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. - */ - LL_COMMON_API void replace_ascii_controlchars( - std::basic_string& string, - char replacement); -} - -//////////////////////////////////////////////////////////// -// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. -// There is no LLWStringUtil::format implementation currently. -// Calling thse for anything other than LLStringUtil will produce link errors. - -//////////////////////////////////////////////////////////// - - -// static -template -S32 LLStringUtilBase::compareStrings(const T* lhs, const T* rhs) -{ - S32 result; - if( lhs == rhs ) - { - result = 0; - } - else - if ( !lhs || !lhs[0] ) - { - result = ((!rhs || !rhs[0]) ? 0 : 1); - } - else - if ( !rhs || !rhs[0]) - { - result = -1; - } - else - { - result = LLStringOps::collate(lhs, rhs); - } - return result; -} - -//static -template -S32 LLStringUtilBase::compareStrings(const std::basic_string& lhs, const std::basic_string& rhs) -{ - return LLStringOps::collate(lhs.c_str(), rhs.c_str()); -} - -// static -template -S32 LLStringUtilBase::compareInsensitive(const T* lhs, const T* rhs ) -{ - S32 result; - if( lhs == rhs ) - { - result = 0; - } - else - if ( !lhs || !lhs[0] ) - { - result = ((!rhs || !rhs[0]) ? 0 : 1); - } - else - if ( !rhs || !rhs[0] ) - { - result = -1; - } - else - { - std::basic_string lhs_string(lhs); - std::basic_string rhs_string(rhs); - LLStringUtilBase::toUpper(lhs_string); - LLStringUtilBase::toUpper(rhs_string); - result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); - } - return result; -} - -//static -template -S32 LLStringUtilBase::compareInsensitive(const std::basic_string& lhs, const std::basic_string& rhs) -{ - std::basic_string lhs_string(lhs); - std::basic_string rhs_string(rhs); - LLStringUtilBase::toUpper(lhs_string); - LLStringUtilBase::toUpper(rhs_string); - return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); -} - -// Case sensitive comparison with good handling of numbers. Does not use current locale. -// a.k.a. strdictcmp() - -//static -template -S32 LLStringUtilBase::compareDict(const std::basic_string& astr, const std::basic_string& bstr) -{ - const T* a = astr.c_str(); - const T* b = bstr.c_str(); - T ca, cb; - S32 ai, bi, cnt = 0; - S32 bias = 0; - - ca = *(a++); - cb = *(b++); - while( ca && cb ){ - if( bias==0 ){ - if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; } - if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; } - }else{ - if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); } - if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); } - } - if( LLStringOps::isDigit(ca) ){ - if( cnt-->0 ){ - if( cb!=ca ) break; - }else{ - if( !LLStringOps::isDigit(cb) ) break; - for(ai=0; LLStringOps::isDigit(a[ai]); ai++); - for(bi=0; LLStringOps::isDigit(b[bi]); bi++); - if( ai -S32 LLStringUtilBase::compareDictInsensitive(const std::basic_string& astr, const std::basic_string& bstr) -{ - const T* a = astr.c_str(); - const T* b = bstr.c_str(); - T ca, cb; - S32 ai, bi, cnt = 0; - - ca = *(a++); - cb = *(b++); - while( ca && cb ){ - if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); } - if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); } - if( LLStringOps::isDigit(ca) ){ - if( cnt-->0 ){ - if( cb!=ca ) break; - }else{ - if( !LLStringOps::isDigit(cb) ) break; - for(ai=0; LLStringOps::isDigit(a[ai]); ai++); - for(bi=0; LLStringOps::isDigit(b[bi]); bi++); - if( ai -BOOL LLStringUtilBase::precedesDict( const std::basic_string& a, const std::basic_string& b ) -{ - if( a.size() && b.size() ) - { - return (LLStringUtilBase::compareDict(a.c_str(), b.c_str()) < 0); - } - else - { - return (!b.empty()); - } -} - -//static -template -void LLStringUtilBase::toUpper(std::basic_string& string) -{ - if( !string.empty() ) - { - std::transform( - string.begin(), - string.end(), - string.begin(), - (T(*)(T)) &LLStringOps::toUpper); - } -} - -//static -template -void LLStringUtilBase::toLower(std::basic_string& string) -{ - if( !string.empty() ) - { - std::transform( - string.begin(), - string.end(), - string.begin(), - (T(*)(T)) &LLStringOps::toLower); - } -} - -//static -template -void LLStringUtilBase::trimHead(std::basic_string& string) -{ - if( !string.empty() ) - { - size_type i = 0; - while( i < string.length() && LLStringOps::isSpace( string[i] ) ) - { - i++; - } - string.erase(0, i); - } -} - -//static -template -void LLStringUtilBase::trimTail(std::basic_string& string) -{ - if( string.size() ) - { - size_type len = string.length(); - size_type i = len; - while( i > 0 && LLStringOps::isSpace( string[i-1] ) ) - { - i--; - } - - string.erase( i, len - i ); - } -} - - -// Replace line feeds with carriage return-line feed pairs. -//static -template -void LLStringUtilBase::addCRLF(std::basic_string& string) -{ - const T LF = 10; - const T CR = 13; - - // Count the number of line feeds - size_type count = 0; - size_type len = string.size(); - size_type i; - for( i = 0; i < len; i++ ) - { - if( string[i] == LF ) - { - count++; - } - } - - // Insert a carriage return before each line feed - if( count ) - { - size_type size = len + count; - T *t = new T[size]; - size_type j = 0; - for( i = 0; i < len; ++i ) - { - if( string[i] == LF ) - { - t[j] = CR; - ++j; - } - t[j] = string[i]; - ++j; - } - - string.assign(t, size); - } -} - -// Remove all carriage returns -//static -template -void LLStringUtilBase::removeCRLF(std::basic_string& string) -{ - const T CR = 13; - - size_type cr_count = 0; - size_type len = string.size(); - size_type i; - for( i = 0; i < len - cr_count; i++ ) - { - if( string[i+cr_count] == CR ) - { - cr_count++; - } - - string[i] = string[i+cr_count]; - } - string.erase(i, cr_count); -} - -//static -template -void LLStringUtilBase::replaceChar( std::basic_string& string, T target, T replacement ) -{ - size_type found_pos = 0; - while( (found_pos = string.find(target, found_pos)) != std::basic_string::npos ) - { - string[found_pos] = replacement; - found_pos++; // avoid infinite defeat if target == replacement - } -} - -//static -template -void LLStringUtilBase::replaceString( std::basic_string& string, std::basic_string target, std::basic_string replacement ) -{ - size_type found_pos = 0; - while( (found_pos = string.find(target, found_pos)) != std::basic_string::npos ) - { - string.replace( found_pos, target.length(), replacement ); - found_pos += replacement.length(); // avoid infinite defeat if replacement contains target - } -} - -//static -template -void LLStringUtilBase::replaceNonstandardASCII( std::basic_string& string, T replacement ) -{ - const char LF = 10; - const S8 MIN = 32; -// const S8 MAX = 127; - - size_type len = string.size(); - for( size_type i = 0; i < len; i++ ) - { - // No need to test MAX < mText[i] because we treat mText[i] as a signed char, - // which has a max value of 127. - if( ( S8(string[i]) < MIN ) && (string[i] != LF) ) - { - string[i] = replacement; - } - } -} - -//static -template -void LLStringUtilBase::replaceTabsWithSpaces( std::basic_string& str, size_type spaces_per_tab ) -{ - const T TAB = '\t'; - const T SPACE = ' '; - - std::basic_string out_str; - // Replace tabs with spaces - for (size_type i = 0; i < str.length(); i++) - { - if (str[i] == TAB) - { - for (size_type j = 0; j < spaces_per_tab; j++) - out_str += SPACE; - } - else - { - out_str += str[i]; - } - } - str = out_str; -} - -//static -template -BOOL LLStringUtilBase::containsNonprintable(const std::basic_string& string) -{ - const char MIN = 32; - BOOL rv = FALSE; - for (size_type i = 0; i < string.size(); i++) - { - if(string[i] < MIN) - { - rv = TRUE; - break; - } - } - return rv; -} - -//static -template -void LLStringUtilBase::stripNonprintable(std::basic_string& string) -{ - const char MIN = 32; - size_type j = 0; - if (string.empty()) - { - return; - } - size_t src_size = string.size(); - char* c_string = new char[src_size + 1]; - if(c_string == NULL) - { - return; - } - copy(c_string, string.c_str(), src_size+1); - char* write_head = &c_string[0]; - for (size_type i = 0; i < src_size; i++) - { - char* read_head = &string[i]; - write_head = &c_string[j]; - if(!(*read_head < MIN)) - { - *write_head = *read_head; - ++j; - } - } - c_string[j]= '\0'; - string = c_string; - delete []c_string; -} - -template -void LLStringUtilBase::_makeASCII(std::basic_string& string) -{ - // Replace non-ASCII chars with LL_UNKNOWN_CHAR - for (size_type i = 0; i < string.length(); i++) - { - if (string[i] > 0x7f) - { - string[i] = LL_UNKNOWN_CHAR; - } - } -} - -// static -template -void LLStringUtilBase::copy( T* dst, const T* src, size_type dst_size ) -{ - if( dst_size > 0 ) - { - size_type min_len = 0; - if( src ) - { - min_len = llmin( dst_size - 1, strlen( src ) ); /* Flawfinder: ignore */ - memcpy(dst, src, min_len * sizeof(T)); /* Flawfinder: ignore */ - } - dst[min_len] = '\0'; - } -} - -// static -template -void LLStringUtilBase::copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset) -{ - if ( offset == dst.length() ) - { - // special case - append to end of string and avoid expensive - // (when strings are large) string manipulations - dst += src; - } - else - { - std::basic_string tail = dst.substr(offset); - - dst = dst.substr(0, offset); - dst += src; - dst += tail; - }; -} - -// True if this is the head of s. -//static -template -BOOL LLStringUtilBase::isHead( const std::basic_string& string, const T* s ) -{ - if( string.empty() ) - { - // Early exit - return FALSE; - } - else - { - return (strncmp( s, string.c_str(), string.size() ) == 0); - } -} - -// static -template -bool LLStringUtilBase::startsWith( - const std::basic_string& string, - const std::basic_string& substr) -{ - if(string.empty() || (substr.empty())) return false; - if(0 == string.find(substr)) return true; - return false; -} - -// static -template -bool LLStringUtilBase::endsWith( - const std::basic_string& string, - const std::basic_string& substr) -{ - if(string.empty() || (substr.empty())) return false; - std::string::size_type idx = string.rfind(substr); - if(std::string::npos == idx) return false; - return (idx == (string.size() - substr.size())); -} - - -template -BOOL LLStringUtilBase::convertToBOOL(const std::basic_string& string, BOOL& value) -{ - if( string.empty() ) - { - return FALSE; - } - - std::basic_string temp( string ); - trim(temp); - if( - (temp == "1") || - (temp == "T") || - (temp == "t") || - (temp == "TRUE") || - (temp == "true") || - (temp == "True") ) - { - value = TRUE; - return TRUE; - } - else - if( - (temp == "0") || - (temp == "F") || - (temp == "f") || - (temp == "FALSE") || - (temp == "false") || - (temp == "False") ) - { - value = FALSE; - return TRUE; - } - - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToU8(const std::basic_string& string, U8& value) -{ - S32 value32 = 0; - BOOL success = convertToS32(string, value32); - if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) ) - { - value = (U8) value32; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToS8(const std::basic_string& string, S8& value) -{ - S32 value32 = 0; - BOOL success = convertToS32(string, value32); - if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) ) - { - value = (S8) value32; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToS16(const std::basic_string& string, S16& value) -{ - S32 value32 = 0; - BOOL success = convertToS32(string, value32); - if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) ) - { - value = (S16) value32; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToU16(const std::basic_string& string, U16& value) -{ - S32 value32 = 0; - BOOL success = convertToS32(string, value32); - if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) ) - { - value = (U16) value32; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToU32(const std::basic_string& string, U32& value) -{ - if( string.empty() ) - { - return FALSE; - } - - std::basic_string temp( string ); - trim(temp); - U32 v; - std::basic_istringstream i_stream((std::basic_string)temp); - if(i_stream >> v) - { - value = v; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToS32(const std::basic_string& string, S32& value) -{ - if( string.empty() ) - { - return FALSE; - } - - std::basic_string temp( string ); - trim(temp); - S32 v; - std::basic_istringstream i_stream((std::basic_string)temp); - if(i_stream >> v) - { - //TODO: figure out overflow and underflow reporting here - //if((LONG_MAX == v) || (LONG_MIN == v)) - //{ - // // Underflow or overflow - // return FALSE; - //} - - value = v; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToF32(const std::basic_string& string, F32& value) -{ - F64 value64 = 0.0; - BOOL success = convertToF64(string, value64); - if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) ) - { - value = (F32) value64; - return TRUE; - } - return FALSE; -} - -template -BOOL LLStringUtilBase::convertToF64(const std::basic_string& string, F64& value) -{ - if( string.empty() ) - { - return FALSE; - } - - std::basic_string temp( string ); - trim(temp); - F64 v; - std::basic_istringstream i_stream((std::basic_string)temp); - if(i_stream >> v) - { - //TODO: figure out overflow and underflow reporting here - //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) ) - //{ - // // Underflow or overflow - // return FALSE; - //} - - value = v; - return TRUE; - } - return FALSE; -} - -template -void LLStringUtilBase::truncate(std::basic_string& string, size_type count) -{ - size_type cur_size = string.size(); - string.resize(count < cur_size ? count : cur_size); -} - -#endif // LL_STRING_H +/** + * @file llstring.h + * @brief String utility functions and std::string class. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSTRING_H +#define LL_LLSTRING_H + +#include +#include +#include +#include +#include "llsd.h" +#include "llfasttimer.h" + +#if LL_LINUX || LL_SOLARIS +#include +#include +#endif + +#include + +#if LL_SOLARIS +// stricmp and strnicmp do not exist on Solaris: +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + +const char LL_UNKNOWN_CHAR = '?'; + +#if LL_DARWIN || LL_LINUX || LL_SOLARIS +// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already) +#include + +namespace std +{ +template<> +struct char_traits +{ + typedef U16 char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; + + static void + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } + + static bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { return memcmp(__s1, __s2, __n * sizeof(char_type)); } + + static size_t + length(const char_type* __s) + { + const char_type *cur_char = __s; + while (*cur_char != 0) + { + ++cur_char; + } + return cur_char - __s; + } + + static const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { return static_cast(memchr(__s, __a, __n * sizeof(char_type))); } + + static char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { return static_cast(memmove(__s1, __s2, __n * sizeof(char_type))); } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { return static_cast(memcpy(__s1, __s2, __n * sizeof(char_type))); } /* Flawfinder: ignore */ + + static char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + // This isn't right. + //return static_cast(memset(__s, __a, __n * sizeof(char_type))); + + // I don't think there's a standard 'memset' for 16-bit values. + // Do this the old-fashioned way. + + size_t __i; + for(__i = 0; __i < __n; __i++) + { + __s[__i] = __a; + } + return __s; + } + + static char_type + to_char_type(const int_type& __c) + { return static_cast(__c); } + + static int_type + to_int_type(const char_type& __c) + { return static_cast(__c); } + + static bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static int_type + eof() { return static_cast(EOF); } + + static int_type + not_eof(const int_type& __c) + { return (__c == eof()) ? 0 : __c; } + }; +}; +#endif + +class LL_COMMON_API LLStringOps +{ +private: + static long sPacificTimeOffset; + static long sLocalTimeOffset; + static bool sPacificDaylightTime; + static std::map datetimeToCodes; + +public: + static char toUpper(char elem) { return toupper((unsigned char)elem); } + static llwchar toUpper(llwchar elem) { return towupper(elem); } + + static char toLower(char elem) { return tolower((unsigned char)elem); } + static llwchar toLower(llwchar elem) { return towlower(elem); } + + static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; } + static bool isSpace(llwchar elem) { return iswspace(elem) != 0; } + + static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; } + static bool isUpper(llwchar elem) { return iswupper(elem) != 0; } + + static bool isLower(char elem) { return islower((unsigned char)elem) != 0; } + static bool isLower(llwchar elem) { return iswlower(elem) != 0; } + + static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; } + static bool isDigit(llwchar a) { return iswdigit(a) != 0; } + + static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } + static bool isPunct(llwchar a) { return iswpunct(a) != 0; } + + static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } + static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } + + static S32 collate(const char* a, const char* b) { return strcoll(a, b); } + static S32 collate(const llwchar* a, const llwchar* b); + + static void setupDatetimeInfo(bool pacific_daylight_time); + static long getPacificTimeOffset(void) { return sPacificTimeOffset;} + static long getLocalTimeOffset(void) { return sLocalTimeOffset;} + // Is the Pacific time zone (aka server time zone) + // currently in daylight savings time? + static bool getPacificDaylightTime(void) { return sPacificDaylightTime;} + + static std::string getDatetimeCode (std::string key); +}; + +/** + * @brief Return a string constructed from in without crashing if the + * pointer is NULL. + */ +LL_COMMON_API std::string ll_safe_string(const char* in); +LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen); + + +// Allowing assignments from non-strings into format_map_t is apparently +// *really* error-prone, so subclass std::string with just basic c'tors. +class LLFormatMapString +{ +public: + LLFormatMapString() {}; + LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {}; + LLFormatMapString(const std::string& s) : mString(s) {}; + operator std::string() const { return mString; } + bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; } + std::size_t length() const { return mString.length(); } + +private: + std::string mString; +}; + +template +class LLStringUtilBase +{ +private: + static std::string sLocale; + +public: + typedef typename std::basic_string::size_type size_type; + +public: + ///////////////////////////////////////////////////////////////////////////////////////// + // Static Utility functions that operate on std::strings + + static std::basic_string null; + + typedef std::map format_map_t; + LL_COMMON_API static void getTokens(const std::basic_string& instr, std::vector >& tokens, const std::basic_string& delims); + LL_COMMON_API static void formatNumber(std::basic_string& numStr, std::basic_string decimals); + LL_COMMON_API static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, S32 secFromEpoch); + LL_COMMON_API static S32 format(std::basic_string& s, const format_map_t& substitutions); + LL_COMMON_API static S32 format(std::basic_string& s, const LLSD& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const format_map_t& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); + static void setLocale (std::string inLocale) {sLocale = inLocale;}; + static std::string getLocale (void) {return sLocale;}; + + static bool isValidIndex(const std::basic_string& string, size_type i) + { + return !string.empty() && (0 <= i) && (i <= string.size()); + } + + static void trimHead(std::basic_string& string); + static void trimTail(std::basic_string& string); + static void trim(std::basic_string& string) { trimHead(string); trimTail(string); } + static void truncate(std::basic_string& string, size_type count); + + static void toUpper(std::basic_string& string); + static void toLower(std::basic_string& string); + + // True if this is the head of s. + static BOOL isHead( const std::basic_string& string, const T* s ); + + /** + * @brief Returns true if string starts with substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool startsWith( + const std::basic_string& string, + const std::basic_string& substr); + + /** + * @brief Returns true if string ends in substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool endsWith( + const std::basic_string& string, + const std::basic_string& substr); + + static void addCRLF(std::basic_string& string); + static void removeCRLF(std::basic_string& string); + + static void replaceTabsWithSpaces( std::basic_string& string, size_type spaces_per_tab ); + static void replaceNonstandardASCII( std::basic_string& string, T replacement ); + static void replaceChar( std::basic_string& string, T target, T replacement ); + static void replaceString( std::basic_string& string, std::basic_string target, std::basic_string replacement ); + + static BOOL containsNonprintable(const std::basic_string& string); + static void stripNonprintable(std::basic_string& string); + + /** + * @brief Unsafe way to make ascii characters. You should probably + * only call this when interacting with the host operating system. + * The 1 byte std::string does not work correctly. + * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII + * should work. + */ + static void _makeASCII(std::basic_string& string); + + // Conversion to other data types + static BOOL convertToBOOL(const std::basic_string& string, BOOL& value); + static BOOL convertToU8(const std::basic_string& string, U8& value); + static BOOL convertToS8(const std::basic_string& string, S8& value); + static BOOL convertToS16(const std::basic_string& string, S16& value); + static BOOL convertToU16(const std::basic_string& string, U16& value); + static BOOL convertToU32(const std::basic_string& string, U32& value); + static BOOL convertToS32(const std::basic_string& string, S32& value); + static BOOL convertToF32(const std::basic_string& string, F32& value); + static BOOL convertToF64(const std::basic_string& string, F64& value); + + ///////////////////////////////////////////////////////////////////////////////////////// + // Utility functions for working with char*'s and strings + + // Like strcmp but also handles empty strings. Uses + // current locale. + static S32 compareStrings(const T* lhs, const T* rhs); + static S32 compareStrings(const std::basic_string& lhs, const std::basic_string& rhs); + + // case insensitive version of above. Uses current locale on + // Win32, and falls back to a non-locale aware comparison on + // Linux. + static S32 compareInsensitive(const T* lhs, const T* rhs); + static S32 compareInsensitive(const std::basic_string& lhs, const std::basic_string& rhs); + + // Case sensitive comparison with good handling of numbers. Does not use current locale. + // a.k.a. strdictcmp() + static S32 compareDict(const std::basic_string& a, const std::basic_string& b); + + // Case *in*sensitive comparison with good handling of numbers. Does not use current locale. + // a.k.a. strdictcmp() + static S32 compareDictInsensitive(const std::basic_string& a, const std::basic_string& b); + + // Puts compareDict() in a form appropriate for LL container classes to use for sorting. + static BOOL precedesDict( const std::basic_string& a, const std::basic_string& b ); + + // A replacement for strncpy. + // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds + // up to dst_size-1 characters of src. + static void copy(T* dst, const T* src, size_type dst_size); + + // Copies src into dst at a given offset. + static void copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset); + + static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } + + +#ifdef _DEBUG + LL_COMMON_API static void testHarness(); +#endif + +private: + LL_COMMON_API static size_type getSubstitution(const std::basic_string& instr, size_type& start, std::vector >& tokens); +}; + +template std::basic_string LLStringUtilBase::null; +template std::string LLStringUtilBase::sLocale; + +typedef LLStringUtilBase LLStringUtil; +typedef LLStringUtilBase LLWStringUtil; +typedef std::basic_string LLWString; + +//@ Use this where we want to disallow input in the form of "foo" +// This is used to catch places where english text is embedded in the code +// instead of in a translatable XUI file. +class LLStringExplicit : public std::string +{ +public: + explicit LLStringExplicit(const char* s) : std::string(s) {} + LLStringExplicit(const std::string& s) : std::string(s) {} + LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {} +}; + +struct LLDictionaryLess +{ +public: + bool operator()(const std::string& a, const std::string& b) + { + return (LLStringUtil::precedesDict(a, b) ? true : false); + } +}; + + +/** + * Simple support functions + */ + +/** + * @brief chop off the trailing characters in a string. + * + * This function works on bytes rather than glyphs, so this will + * incorrectly truncate non-single byte strings. + * Use utf8str_truncate() for utf8 strings + * @return a copy of in string minus the trailing count bytes. + */ +inline std::string chop_tail_copy( + const std::string& in, + std::string::size_type count) +{ + return std::string(in, 0, in.length() - count); +} + +/** + * @brief This translates a nybble stored as a hex value from 0-f back + * to a nybble in the low order bits of the return byte. + */ +LL_COMMON_API U8 hex_as_nybble(char hex); + +/** + * @brief read the contents of a file into a string. + * + * Since this function has no concept of character encoding, most + * anything you do with this method ill-advised. Please avoid. + * @param str [out] The string which will have. + * @param filename The full name of the file to read. + * @return Returns true on success. If false, str is unmodified. + */ +LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename); +LL_COMMON_API bool iswindividual(llwchar elem); + +/** + * Unicode support + */ + +// Make the incoming string a utf8 string. Replaces any unknown glyph +// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest +// of the data may not be recovered. +LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw); + +// +// We should never use UTF16 except when communicating with Win32! +// +typedef std::basic_string llutf16string; + +LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); +LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); + +LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); +LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str); + +LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); +LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str ); + +LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); +LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str); +// Same function, better name. JC +inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } + +// +LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars); + +LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); +LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str); + +LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); +LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str); + +// Length of this UTF32 string in bytes when transformed to UTF8 +LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); + +// Length in bytes of this wide char in a UTF8 string +LL_COMMON_API S32 wchar_utf8_length(const llwchar wc); + +LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str); + +// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string. +LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len); + +// Length in utf16string (UTF-16) of wlen wchars beginning at woffset. +LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); + +// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) +LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); + +/** + * @brief Properly truncate a utf8 string to a maximum byte count. + * + * The returned string may be less than max_len if the truncation + * happens in the middle of a glyph. If max_len is longer than the + * string passed in, the return value == utf8str. + * @param utf8str A valid utf8 string to truncate. + * @param max_len The maximum number of bytes in the return value. + * @return Returns a valid utf8 string with byte count <= max_len. + */ +LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len); + +LL_COMMON_API std::string utf8str_trim(const std::string& utf8str); + +LL_COMMON_API S32 utf8str_compare_insensitive( + const std::string& lhs, + const std::string& rhs); + +/** + * @brief Replace all occurences of target_char with replace_char + * + * @param utf8str A utf8 string to process. + * @param target_char The wchar to be replaced + * @param replace_char The wchar which is written on replace + */ +LL_COMMON_API std::string utf8str_substChar( + const std::string& utf8str, + const llwchar target_char, + const llwchar replace_char); + +LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str); + +// Hack - used for evil notecards. +LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str); + +LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); + + +#if LL_WINDOWS +/* @name Windows string helpers + */ +//@{ + +/** + * @brief Implementation the expected snprintf interface. + * + * If the size of the passed in buffer is not large enough to hold the string, + * two bad things happen: + * 1. resulting formatted string is NOT null terminated + * 2. Depending on the platform, the return value could be a) the required + * size of the buffer to copy the entire formatted string or b) -1. + * On Windows with VS.Net 2003, it returns -1 e.g. + * + * safe_snprintf always adds a NULL terminator so that the caller does not + * need to check for return value or need to add the NULL terminator. + * It does not, however change the return value - to let the caller know + * that the passed in buffer size was not large enough to hold the + * formatted string. + * + */ + +// Deal with the differeneces on Windows +namespace snprintf_hack +{ + LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...); +} + +using snprintf_hack::snprintf; + +/** + * @brief Convert a wide string to std::string + * + * This replaces the unsafe W2A macro from ATL. + */ +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); + +//@} +#endif // LL_WINDOWS + +/** + * Many of the 'strip' and 'replace' methods of LLStringUtilBase need + * specialization to work with the signed char type. + * Sadly, it is not possible (AFAIK) to specialize a single method of + * a template class. + * That stuff should go here. + */ +namespace LLStringFn +{ + /** + * @brief Replace all non-printable characters with replacement in + * string. + * NOTE - this will zap non-ascii + * + * @param [in,out] string the to modify. out value is the string + * with zero non-printable characters. + * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. + */ + LL_COMMON_API void replace_nonprintable_in_ascii( + std::basic_string& string, + char replacement); + + + /** + * @brief Replace all non-printable characters and pipe characters + * with replacement in a string. + * NOTE - this will zap non-ascii + * + * @param [in,out] the string to modify. out value is the string + * with zero non-printable characters and zero pipe characters. + * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. + */ + LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string& str, + char replacement); + + + /** + * @brief Remove all characters that are not allowed in XML 1.0. + * Returns a copy of the string with those characters removed. + * Works with US ASCII and UTF-8 encoded strings. JC + */ + LL_COMMON_API std::string strip_invalid_xml(const std::string& input); + + + /** + * @brief Replace all control characters (0 <= c < 0x20) with replacement in + * string. This is safe for utf-8 + * + * @param [in,out] string the to modify. out value is the string + * with zero non-printable characters. + * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. + */ + LL_COMMON_API void replace_ascii_controlchars( + std::basic_string& string, + char replacement); +} + +//////////////////////////////////////////////////////////// +// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. +// There is no LLWStringUtil::format implementation currently. +// Calling thse for anything other than LLStringUtil will produce link errors. + +//////////////////////////////////////////////////////////// + + +// static +template +S32 LLStringUtilBase::compareStrings(const T* lhs, const T* rhs) +{ + S32 result; + if( lhs == rhs ) + { + result = 0; + } + else + if ( !lhs || !lhs[0] ) + { + result = ((!rhs || !rhs[0]) ? 0 : 1); + } + else + if ( !rhs || !rhs[0]) + { + result = -1; + } + else + { + result = LLStringOps::collate(lhs, rhs); + } + return result; +} + +//static +template +S32 LLStringUtilBase::compareStrings(const std::basic_string& lhs, const std::basic_string& rhs) +{ + return LLStringOps::collate(lhs.c_str(), rhs.c_str()); +} + +// static +template +S32 LLStringUtilBase::compareInsensitive(const T* lhs, const T* rhs ) +{ + S32 result; + if( lhs == rhs ) + { + result = 0; + } + else + if ( !lhs || !lhs[0] ) + { + result = ((!rhs || !rhs[0]) ? 0 : 1); + } + else + if ( !rhs || !rhs[0] ) + { + result = -1; + } + else + { + std::basic_string lhs_string(lhs); + std::basic_string rhs_string(rhs); + LLStringUtilBase::toUpper(lhs_string); + LLStringUtilBase::toUpper(rhs_string); + result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); + } + return result; +} + +//static +template +S32 LLStringUtilBase::compareInsensitive(const std::basic_string& lhs, const std::basic_string& rhs) +{ + std::basic_string lhs_string(lhs); + std::basic_string rhs_string(rhs); + LLStringUtilBase::toUpper(lhs_string); + LLStringUtilBase::toUpper(rhs_string); + return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); +} + +// Case sensitive comparison with good handling of numbers. Does not use current locale. +// a.k.a. strdictcmp() + +//static +template +S32 LLStringUtilBase::compareDict(const std::basic_string& astr, const std::basic_string& bstr) +{ + const T* a = astr.c_str(); + const T* b = bstr.c_str(); + T ca, cb; + S32 ai, bi, cnt = 0; + S32 bias = 0; + + ca = *(a++); + cb = *(b++); + while( ca && cb ){ + if( bias==0 ){ + if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; } + if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; } + }else{ + if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); } + if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); } + } + if( LLStringOps::isDigit(ca) ){ + if( cnt-->0 ){ + if( cb!=ca ) break; + }else{ + if( !LLStringOps::isDigit(cb) ) break; + for(ai=0; LLStringOps::isDigit(a[ai]); ai++); + for(bi=0; LLStringOps::isDigit(b[bi]); bi++); + if( ai +S32 LLStringUtilBase::compareDictInsensitive(const std::basic_string& astr, const std::basic_string& bstr) +{ + const T* a = astr.c_str(); + const T* b = bstr.c_str(); + T ca, cb; + S32 ai, bi, cnt = 0; + + ca = *(a++); + cb = *(b++); + while( ca && cb ){ + if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); } + if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); } + if( LLStringOps::isDigit(ca) ){ + if( cnt-->0 ){ + if( cb!=ca ) break; + }else{ + if( !LLStringOps::isDigit(cb) ) break; + for(ai=0; LLStringOps::isDigit(a[ai]); ai++); + for(bi=0; LLStringOps::isDigit(b[bi]); bi++); + if( ai +BOOL LLStringUtilBase::precedesDict( const std::basic_string& a, const std::basic_string& b ) +{ + if( a.size() && b.size() ) + { + return (LLStringUtilBase::compareDict(a.c_str(), b.c_str()) < 0); + } + else + { + return (!b.empty()); + } +} + +//static +template +void LLStringUtilBase::toUpper(std::basic_string& string) +{ + if( !string.empty() ) + { + std::transform( + string.begin(), + string.end(), + string.begin(), + (T(*)(T)) &LLStringOps::toUpper); + } +} + +//static +template +void LLStringUtilBase::toLower(std::basic_string& string) +{ + if( !string.empty() ) + { + std::transform( + string.begin(), + string.end(), + string.begin(), + (T(*)(T)) &LLStringOps::toLower); + } +} + +//static +template +void LLStringUtilBase::trimHead(std::basic_string& string) +{ + if( !string.empty() ) + { + size_type i = 0; + while( i < string.length() && LLStringOps::isSpace( string[i] ) ) + { + i++; + } + string.erase(0, i); + } +} + +//static +template +void LLStringUtilBase::trimTail(std::basic_string& string) +{ + if( string.size() ) + { + size_type len = string.length(); + size_type i = len; + while( i > 0 && LLStringOps::isSpace( string[i-1] ) ) + { + i--; + } + + string.erase( i, len - i ); + } +} + + +// Replace line feeds with carriage return-line feed pairs. +//static +template +void LLStringUtilBase::addCRLF(std::basic_string& string) +{ + const T LF = 10; + const T CR = 13; + + // Count the number of line feeds + size_type count = 0; + size_type len = string.size(); + size_type i; + for( i = 0; i < len; i++ ) + { + if( string[i] == LF ) + { + count++; + } + } + + // Insert a carriage return before each line feed + if( count ) + { + size_type size = len + count; + T *t = new T[size]; + size_type j = 0; + for( i = 0; i < len; ++i ) + { + if( string[i] == LF ) + { + t[j] = CR; + ++j; + } + t[j] = string[i]; + ++j; + } + + string.assign(t, size); + } +} + +// Remove all carriage returns +//static +template +void LLStringUtilBase::removeCRLF(std::basic_string& string) +{ + const T CR = 13; + + size_type cr_count = 0; + size_type len = string.size(); + size_type i; + for( i = 0; i < len - cr_count; i++ ) + { + if( string[i+cr_count] == CR ) + { + cr_count++; + } + + string[i] = string[i+cr_count]; + } + string.erase(i, cr_count); +} + +//static +template +void LLStringUtilBase::replaceChar( std::basic_string& string, T target, T replacement ) +{ + size_type found_pos = 0; + while( (found_pos = string.find(target, found_pos)) != std::basic_string::npos ) + { + string[found_pos] = replacement; + found_pos++; // avoid infinite defeat if target == replacement + } +} + +//static +template +void LLStringUtilBase::replaceString( std::basic_string& string, std::basic_string target, std::basic_string replacement ) +{ + size_type found_pos = 0; + while( (found_pos = string.find(target, found_pos)) != std::basic_string::npos ) + { + string.replace( found_pos, target.length(), replacement ); + found_pos += replacement.length(); // avoid infinite defeat if replacement contains target + } +} + +//static +template +void LLStringUtilBase::replaceNonstandardASCII( std::basic_string& string, T replacement ) +{ + const char LF = 10; + const S8 MIN = 32; +// const S8 MAX = 127; + + size_type len = string.size(); + for( size_type i = 0; i < len; i++ ) + { + // No need to test MAX < mText[i] because we treat mText[i] as a signed char, + // which has a max value of 127. + if( ( S8(string[i]) < MIN ) && (string[i] != LF) ) + { + string[i] = replacement; + } + } +} + +//static +template +void LLStringUtilBase::replaceTabsWithSpaces( std::basic_string& str, size_type spaces_per_tab ) +{ + const T TAB = '\t'; + const T SPACE = ' '; + + std::basic_string out_str; + // Replace tabs with spaces + for (size_type i = 0; i < str.length(); i++) + { + if (str[i] == TAB) + { + for (size_type j = 0; j < spaces_per_tab; j++) + out_str += SPACE; + } + else + { + out_str += str[i]; + } + } + str = out_str; +} + +//static +template +BOOL LLStringUtilBase::containsNonprintable(const std::basic_string& string) +{ + const char MIN = 32; + BOOL rv = FALSE; + for (size_type i = 0; i < string.size(); i++) + { + if(string[i] < MIN) + { + rv = TRUE; + break; + } + } + return rv; +} + +//static +template +void LLStringUtilBase::stripNonprintable(std::basic_string& string) +{ + const char MIN = 32; + size_type j = 0; + if (string.empty()) + { + return; + } + size_t src_size = string.size(); + char* c_string = new char[src_size + 1]; + if(c_string == NULL) + { + return; + } + copy(c_string, string.c_str(), src_size+1); + char* write_head = &c_string[0]; + for (size_type i = 0; i < src_size; i++) + { + char* read_head = &string[i]; + write_head = &c_string[j]; + if(!(*read_head < MIN)) + { + *write_head = *read_head; + ++j; + } + } + c_string[j]= '\0'; + string = c_string; + delete []c_string; +} + +template +void LLStringUtilBase::_makeASCII(std::basic_string& string) +{ + // Replace non-ASCII chars with LL_UNKNOWN_CHAR + for (size_type i = 0; i < string.length(); i++) + { + if (string[i] > 0x7f) + { + string[i] = LL_UNKNOWN_CHAR; + } + } +} + +// static +template +void LLStringUtilBase::copy( T* dst, const T* src, size_type dst_size ) +{ + if( dst_size > 0 ) + { + size_type min_len = 0; + if( src ) + { + min_len = llmin( dst_size - 1, strlen( src ) ); /* Flawfinder: ignore */ + memcpy(dst, src, min_len * sizeof(T)); /* Flawfinder: ignore */ + } + dst[min_len] = '\0'; + } +} + +// static +template +void LLStringUtilBase::copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset) +{ + if ( offset == dst.length() ) + { + // special case - append to end of string and avoid expensive + // (when strings are large) string manipulations + dst += src; + } + else + { + std::basic_string tail = dst.substr(offset); + + dst = dst.substr(0, offset); + dst += src; + dst += tail; + }; +} + +// True if this is the head of s. +//static +template +BOOL LLStringUtilBase::isHead( const std::basic_string& string, const T* s ) +{ + if( string.empty() ) + { + // Early exit + return FALSE; + } + else + { + return (strncmp( s, string.c_str(), string.size() ) == 0); + } +} + +// static +template +bool LLStringUtilBase::startsWith( + const std::basic_string& string, + const std::basic_string& substr) +{ + if(string.empty() || (substr.empty())) return false; + if(0 == string.find(substr)) return true; + return false; +} + +// static +template +bool LLStringUtilBase::endsWith( + const std::basic_string& string, + const std::basic_string& substr) +{ + if(string.empty() || (substr.empty())) return false; + std::string::size_type idx = string.rfind(substr); + if(std::string::npos == idx) return false; + return (idx == (string.size() - substr.size())); +} + + +template +BOOL LLStringUtilBase::convertToBOOL(const std::basic_string& string, BOOL& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string temp( string ); + trim(temp); + if( + (temp == "1") || + (temp == "T") || + (temp == "t") || + (temp == "TRUE") || + (temp == "true") || + (temp == "True") ) + { + value = TRUE; + return TRUE; + } + else + if( + (temp == "0") || + (temp == "F") || + (temp == "f") || + (temp == "FALSE") || + (temp == "false") || + (temp == "False") ) + { + value = FALSE; + return TRUE; + } + + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToU8(const std::basic_string& string, U8& value) +{ + S32 value32 = 0; + BOOL success = convertToS32(string, value32); + if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) ) + { + value = (U8) value32; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToS8(const std::basic_string& string, S8& value) +{ + S32 value32 = 0; + BOOL success = convertToS32(string, value32); + if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) ) + { + value = (S8) value32; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToS16(const std::basic_string& string, S16& value) +{ + S32 value32 = 0; + BOOL success = convertToS32(string, value32); + if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) ) + { + value = (S16) value32; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToU16(const std::basic_string& string, U16& value) +{ + S32 value32 = 0; + BOOL success = convertToS32(string, value32); + if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) ) + { + value = (U16) value32; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToU32(const std::basic_string& string, U32& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string temp( string ); + trim(temp); + U32 v; + std::basic_istringstream i_stream((std::basic_string)temp); + if(i_stream >> v) + { + value = v; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToS32(const std::basic_string& string, S32& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string temp( string ); + trim(temp); + S32 v; + std::basic_istringstream i_stream((std::basic_string)temp); + if(i_stream >> v) + { + //TODO: figure out overflow and underflow reporting here + //if((LONG_MAX == v) || (LONG_MIN == v)) + //{ + // // Underflow or overflow + // return FALSE; + //} + + value = v; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToF32(const std::basic_string& string, F32& value) +{ + F64 value64 = 0.0; + BOOL success = convertToF64(string, value64); + if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) ) + { + value = (F32) value64; + return TRUE; + } + return FALSE; +} + +template +BOOL LLStringUtilBase::convertToF64(const std::basic_string& string, F64& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string temp( string ); + trim(temp); + F64 v; + std::basic_istringstream i_stream((std::basic_string)temp); + if(i_stream >> v) + { + //TODO: figure out overflow and underflow reporting here + //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) ) + //{ + // // Underflow or overflow + // return FALSE; + //} + + value = v; + return TRUE; + } + return FALSE; +} + +template +void LLStringUtilBase::truncate(std::basic_string& string, size_type count) +{ + size_type cur_size = string.size(); + string.resize(count < cur_size ? count : cur_size); +} + +#endif // LL_STRING_H diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index de927de1cd..fb6d5b2905 100644 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -1,1098 +1,1098 @@ -/** - * @file media_plugin_quicktime.cpp - * @brief QuickTime plugin for LLMedia API plugin system - * - * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2008, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#if LL_QUICKTIME_ENABLED - -#if defined(LL_DARWIN) - #include -#elif defined(LL_WINDOWS) - #include "MacTypes.h" - #include "QTML.h" - #include "Movies.h" - #include "QDoffscreen.h" - #include "FixMath.h" - #include "QTLoadLibraryUtils.h" -#endif - -// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginQuickTime : public MediaPluginBase -{ -public: - MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginQuickTime(); - - /* virtual */ void receiveMessage(const char *message_string); - -private: - - int mNaturalWidth; - int mNaturalHeight; - Movie mMovieHandle; - GWorldPtr mGWorldHandle; - ComponentInstance mMovieController; - int mCurVolume; - bool mMediaSizeChanging; - bool mIsLooping; - std::string mMovieTitle; - bool mReceivedTitle; - const int mMinWidth; - const int mMaxWidth; - const int mMinHeight; - const int mMaxHeight; - F64 mPlayRate; - std::string mNavigateURL; - - enum ECommand { - COMMAND_NONE, - COMMAND_STOP, - COMMAND_PLAY, - COMMAND_FAST_FORWARD, - COMMAND_FAST_REWIND, - COMMAND_PAUSE, - COMMAND_SEEK, - }; - ECommand mCommand; - - // Override this to add current time and duration to the message - /*virtual*/ void 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); - - if(mMovieHandle) - { - message.setValueReal("current_time", getCurrentTime()); - message.setValueReal("duration", getDuration()); - message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); - } - - sendMessage(message); - } - - - static Rect rectFromSize(int width, int height) - { - Rect result; - - - result.left = 0; - result.top = 0; - result.right = width; - result.bottom = height; - - return result; - } - - Fixed getPlayRate(void) - { - Fixed result; - if(mPlayRate == 0.0f) - { - // Default to the movie's preferred rate - result = GetMoviePreferredRate(mMovieHandle); - if(result == 0) - { - // Don't return a 0 play rate, ever. - std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl; - result = X2Fix(1.0f); - } - } - else - { - result = X2Fix(mPlayRate); - } - - return result; - } - - void load( const std::string url ) - { - - if ( url.empty() ) - return; - - // Stop and unload any existing movie before starting another one. - unload(); - - setStatus(STATUS_LOADING); - - //In case std::string::c_str() makes a copy of the url data, - //make sure there is memory to hold it before allocating memory for handle. - //if fails, NewHandleClear(...) should return NULL. - const char* url_string = url.c_str() ; - Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); - - if ( NULL == handle || noErr != MemError() || NULL == *handle ) - { - setStatus(STATUS_ERROR); - return; - } - - BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); - - OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); - DisposeHandle( handle ); - if ( noErr != err ) - { - setStatus(STATUS_ERROR); - return; - }; - - mNavigateURL = url; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); - message.setValue("uri", mNavigateURL); - sendMessage(message); - - // do pre-roll actions (typically fired for streaming movies but not always) - PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); - - Rect movie_rect = rectFromSize(mWidth, mHeight); - - // make a new movie controller - mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); - - // movie controller - MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); - - SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); - - // function that gets called when a frame is drawn - SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); - - setStatus(STATUS_LOADED); - - sizeChanged(); - }; - - bool unload() - { - // new movie and have to get title again - mReceivedTitle = false; - - if ( mMovieHandle ) - { - StopMovie( mMovieHandle ); - if ( mMovieController ) - { - MCMovieChanged( mMovieController, mMovieHandle ); - }; - }; - - if ( mMovieController ) - { - MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); - DisposeMovieController( mMovieController ); - mMovieController = NULL; - }; - - if ( mMovieHandle ) - { - SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); - DisposeMovie( mMovieHandle ); - mMovieHandle = NULL; - }; - - if ( mGWorldHandle ) - { - DisposeGWorld( mGWorldHandle ); - mGWorldHandle = NULL; - }; - - setStatus(STATUS_NONE); - - return true; - } - - bool navigateTo( const std::string url ) - { - unload(); - load( url ); - - return true; - }; - - bool sizeChanged() - { - if ( ! mMovieHandle ) - return false; - - // Check to see whether the movie's natural size has updated - { - int width, height; - getMovieNaturalSize(&width, &height); - if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight))) - { - mNaturalWidth = width; - mNaturalHeight = height; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); - message.setValue("name", mTextureSegmentName); - message.setValueS32("width", width); - message.setValueS32("height", height); - sendMessage(message); - //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; - } - } - - // sanitize destination size - Rect dest_rect = rectFromSize(mWidth, mHeight); - - // media depth won't change - int depth_bits = mDepth * 8; - long rowbytes = mDepth * mTextureWidth; - - GWorldPtr old_gworld_handle = mGWorldHandle; - - if(mPixels != NULL) - { - // We have pixels. Set up a GWorld pointing at the texture. - OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes); - if ( noErr != result ) - { - // TODO: unrecoverable?? throw exception? return something? - return false; - } - } - else - { - // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally. - Rect tempRect = rectFromSize(1, 1); - OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0); - if ( noErr != result ) - { - // TODO: unrecoverable?? throw exception? return something? - return false; - } - } - - SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) ); - - // If the GWorld was already set up, delete it. - if(old_gworld_handle != NULL) - { - DisposeGWorld( old_gworld_handle ); - } - - // Set up the movie display matrix - { - // scale movie to fit rect and invert vertically to match opengl image format - MatrixRecord transform; - SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix - double scaleX = (double) mWidth / mNaturalWidth; - double scaleY = -1.0 * (double) mHeight / mNaturalHeight; - double centerX = mWidth / 2.0; - double centerY = mHeight / 2.0; - ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); - SetMovieMatrix( mMovieHandle, &transform ); - } - - // update movie controller - if ( mMovieController ) - { - MCSetControllerPort( mMovieController, mGWorldHandle ); - MCPositionController( mMovieController, &dest_rect, &dest_rect, - mcTopLeftMovie | mcPositionDontInvalidate ); - MCMovieChanged( mMovieController, mMovieHandle ); - } - - - // Emit event with size change so the calling app knows about it too - // TODO: - //LLMediaEvent event( this ); - //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - return true; - } - static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) - { - Boolean result = false; - - MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; - - switch( action ) - { - // handle window resizing - case mcActionControllerSizeChanged: - // Ensure that the movie draws correctly at the new size - self->sizeChanged(); - break; - - // Block any movie controller actions that open URLs. - case mcActionLinkToURL: - case mcActionGetNextURL: - case mcActionLinkToURLExtended: - // Prevent the movie controller from handling the message - result = true; - break; - - default: - break; - }; - - return result; - }; - - static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ) - { - MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; - - // IMPORTANT: typically, a consumer who is observing this event will set a flag - // when this event is fired then render later. Be aware that the media stream - // can change during this period - dimensions, depth, format etc. - //LLMediaEvent event( self ); -// self->updateQuickTime(); - // TODO ^^^ - - - if ( self->mWidth > 0 && self->mHeight > 0 ) - self->setDirty( 0, 0, self->mWidth, self->mHeight ); - - return noErr; - }; - - static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) - { - MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; - - // TODO: - //LLMediaEvent event( self ); - //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); - - // Send a "navigate complete" event. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); - message.setValue("uri", self->mNavigateURL); - message.setValueS32("result_code", 200); - message.setValue("result_string", "OK"); - self->sendMessage(message); - }; - - - void rewind() - { - GoToBeginningOfMovie( mMovieHandle ); - MCMovieChanged( mMovieController, mMovieHandle ); - }; - - bool processState() - { - if ( mCommand == COMMAND_PLAY ) - { - if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE ) - { - long state = GetMovieLoadState( mMovieHandle ); - - if ( state >= kMovieLoadStatePlaythroughOK ) - { - // if the movie is at the end (generally because it reached it naturally) - // and we play is requested, jump back to the start of the movie. - // note: this is different from having loop flag set. - if ( IsMovieDone( mMovieHandle ) ) - { - Fixed rate = X2Fix( 0.0 ); - MCDoAction( mMovieController, mcActionPlay, (void*)rate ); - rewind(); - }; - - MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); - MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); - setStatus(STATUS_PLAYING); - mCommand = COMMAND_NONE; - }; - }; - } - else - if ( mCommand == COMMAND_STOP ) - { - if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE ) - { - if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) - { - Fixed rate = X2Fix( 0.0 ); - MCDoAction( mMovieController, mcActionPlay, (void*)rate ); - rewind(); - - setStatus(STATUS_LOADED); - mCommand = COMMAND_NONE; - }; - }; - } - else - if ( mCommand == COMMAND_PAUSE ) - { - if ( mStatus == STATUS_PLAYING ) - { - if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) - { - Fixed rate = X2Fix( 0.0 ); - MCDoAction( mMovieController, mcActionPlay, (void*)rate ); - setStatus(STATUS_PAUSED); - mCommand = COMMAND_NONE; - }; - }; - }; - - return true; - }; - - void play(F64 rate) - { - mPlayRate = rate; - mCommand = COMMAND_PLAY; - }; - - void stop() - { - mCommand = COMMAND_STOP; - }; - - void pause() - { - mCommand = COMMAND_PAUSE; - }; - - void getMovieNaturalSize(int *movie_width, int *movie_height) - { - Rect rect; - - GetMovieNaturalBoundsRect( mMovieHandle, &rect ); - - int width = ( rect.right - rect.left ); - int height = ( rect.bottom - rect.top ); - - // make sure width and height fall in valid range - if ( width < mMinWidth ) - width = mMinWidth; - - if ( width > mMaxWidth ) - width = mMaxWidth; - - if ( height < mMinHeight ) - height = mMinHeight; - - if ( height > mMaxHeight ) - height = mMaxHeight; - - // return the new rect - *movie_width = width; - *movie_height = height; - } - - void updateQuickTime(int milliseconds) - { - if ( ! mMovieHandle ) - return; - - if ( ! mMovieController ) - return; - - // service QuickTime - // Calling it this way doesn't have good behavior on Windows... -// MoviesTask( mMovieHandle, milliseconds ); - // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle. -// MoviesTask( mMovieHandle, 0 ); - - MCIdle( mMovieController ); - - if ( ! mGWorldHandle ) - return; - - if ( mMediaSizeChanging ) - return; - - // update state machine - processState(); - - // see if title arrived and if so, update member variable with contents - checkTitle(); - - // QT call to see if we are at the end - can't do with controller - if ( IsMovieDone( mMovieHandle ) ) - { - // special code for looping - need to rewind at the end of the movie - if ( mIsLooping ) - { - // go back to start - rewind(); - - if ( mMovieController ) - { - // kick off new play - MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); - - // set the volume - MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); - }; - } - else - { - if(mStatus == STATUS_PLAYING) - { - setStatus(STATUS_DONE); - } - } - } - - }; - - int getDataWidth() const - { - if ( mGWorldHandle ) - { - int depth = mDepth; - - if (depth < 1) - depth = 1; - - // ALWAYS use the row bytes from the PixMap if we have a GWorld because - // sometimes it's not the same as mMediaDepth * mMediaWidth ! - PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); - return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth; - } - else - { - // TODO : return LLMediaImplCommon::getaDataWidth(); - return 0; - } - }; - - void seek( F64 time ) - { - if ( mMovieController ) - { - TimeRecord when; - when.scale = GetMovieTimeScale( mMovieHandle ); - when.base = 0; - - // 'time' is in (floating point) seconds. The timebase time will be in 'units', where - // there are 'scale' units per second. - SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); - - when.value.hi = ( SInt32 )( raw_time >> 32 ); - when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); - - MCDoAction( mMovieController, mcActionGoToTime, &when ); - }; - }; - - F64 getLoadedDuration() - { - TimeValue duration; - if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) - { - // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. - duration = GetMovieDuration( mMovieHandle ); - } - TimeValue scale = GetMovieTimeScale( mMovieHandle ); - - return (F64)duration / (F64)scale; - }; - - F64 getDuration() - { - TimeValue duration = GetMovieDuration( mMovieHandle ); - TimeValue scale = GetMovieTimeScale( mMovieHandle ); - - return (F64)duration / (F64)scale; - }; - - F64 getCurrentTime() - { - TimeValue curr_time = GetMovieTime( mMovieHandle, 0 ); - TimeValue scale = GetMovieTimeScale( mMovieHandle ); - - return (F64)curr_time / (F64)scale; - }; - - void setVolume( F64 volume ) - { - mCurVolume = (short)(volume * ( double ) 0x100 ); - - if ( mMovieController ) - { - MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); - }; - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void update(int milliseconds = 0) - { - updateQuickTime(milliseconds); - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void mouseDown( int x, int y ) - { - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void mouseUp( int x, int y ) - { - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void mouseMove( int x, int y ) - { - }; - - //////////////////////////////////////////////////////////////////////////////// - // - void keyPress( unsigned char key ) - { - }; - - //////////////////////////////////////////////////////////////////////////////// - // Grab movie title into mMovieTitle - should be called repeatedly - // until it returns true since movie title takes a while to become - // available. - const bool getMovieTitle() - { - // grab meta data from movie - QTMetaDataRef media_data_ref; - OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref ); - if ( noErr != result ) - return false; - - // look up "Display Name" in meta data - OSType meta_data_key = kQTMetaDataCommonKeyDisplayName; - QTMetaDataItem item = kQTMetaDataItemUninitialized; - result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, - 0, kQTMetaDataKeyFormatCommon, - (const UInt8 *)&meta_data_key, - sizeof( meta_data_key ), &item ); - if ( noErr != result ) - return false; - - // find the size of the title - ByteCount size; - result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); - if ( noErr != result || size <= 0 ) - return false; - - // allocate some space and grab it - UInt8* item_data = new UInt8( size ); - memset( item_data, 0, size * sizeof( UInt8* ) ); - result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); - if ( noErr != result ) - return false; - - // save it - mMovieTitle = std::string( (char* )item_data ); - - // clean up - delete [] item_data; - - return true; - }; - - // called regularly to see if title changed - void checkTitle() - { - // we did already receive title so keep checking - if ( ! mReceivedTitle ) - { - // grab title from movie meta data - if ( getMovieTitle() ) - { - // pass back to host application - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); - message.setValue("name", mMovieTitle ); - sendMessage( message ); - - // stop looking once we find a title for this movie. - // TODO: this may to be reset if movie title changes - // during playback but this is okay for now - mReceivedTitle = true; - }; - }; - }; -}; - -MediaPluginQuickTime::MediaPluginQuickTime( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data), - mMinWidth( 0 ), - mMaxWidth( 2048 ), - mMinHeight( 0 ), - mMaxHeight( 2048 ) -{ -// std::cerr << "MediaPluginQuickTime constructor" << std::endl; - - mNaturalWidth = -1; - mNaturalHeight = -1; - mMovieHandle = 0; - mGWorldHandle = 0; - mMovieController = 0; - mCurVolume = 0x99; - mMediaSizeChanging = false; - mIsLooping = false; - mMovieTitle = std::string(); - mReceivedTitle = false; - mCommand = COMMAND_NONE; - mPlayRate = 0.0f; - mStatus = STATUS_NONE; -} - -MediaPluginQuickTime::~MediaPluginQuickTime() -{ -// std::cerr << "MediaPluginQuickTime destructor" << std::endl; - - ExitMovies(); - -#ifdef LL_WINDOWS - TerminateQTML(); -// std::cerr << "QuickTime closing down" << std::endl; -#endif -} - - -void MediaPluginQuickTime::receiveMessage(const char *message_string) -{ -// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - // Normally a plugin would only specify one of these two subclasses, but this is a demo... - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; - message.setValueLLSD("versions", versions); - - #ifdef LL_WINDOWS - - // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime - // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html - // The solution presented there appears to work. - QTLoadLibrary("qtcf.dll"); - - // main initialization for QuickTime - only required on Windows - OSErr result = InitializeQTML( 0L ); - if ( result != noErr ) - { - //TODO: If no QT on Windows, this fails - respond accordingly. - } - else - { - //std::cerr << "QuickTime initialized" << std::endl; - }; - #endif - - // required for both Windows and Mac - EnterMovies(); - - std::string plugin_version = "QuickTime media plugin, QuickTime version "; - - long version = 0; - Gestalt( gestaltQuickTimeVersion, &version ); - std::ostringstream codec( "" ); - codec << std::hex << version << std::dec; - plugin_version += codec.str(); - message.setValue("plugin_version", plugin_version); - sendMessage(message); - - // Plugin gets to decide the texture parameters to use. - message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - #if defined(LL_WINDOWS) - // Values for Windows - mDepth = 3; - message.setValueU32("format", GL_RGB); - message.setValueU32("type", GL_UNSIGNED_BYTE); - - // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. - // Padding to a multiple of 3*32 guarantees it'll divide out properly. - message.setValueU32("padding", 32 * 3); - #else - // Values for Mac - mDepth = 4; - message.setValueU32("format", GL_BGRA_EXT); - #ifdef __BIG_ENDIAN__ - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); - #else - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); - #endif - - // Pad texture width to a multiple of 32 bytes, to line up with cache lines. - message.setValueU32("padding", 32); - #endif - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. - message.setValueBoolean("allow_downsample", true); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - F64 time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - // TODO: clean up here - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); -// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name -// << ", size: " << info.mSize -// << ", address: " << info.mAddress -// << std::endl; - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - -// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl; - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - - // Make sure the movie GWorld is no longer pointed at the shared segment. - sizeChanged(); - } - mSharedSegments.erase(iter); - } - else - { -// std::cerr << "MediaPluginQuickTime::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 << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - 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"); - - //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl; - - 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); - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { -// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl; -// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl; - - mPixels = (unsigned char*)iter->second.mAddress; - mTextureSegmentName = name; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - - mMediaSizeChanging = false; - - sizeChanged(); - - update(); - }; - }; - } - else if(message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - load( uri ); - sendStatus(); - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - if(event == "down") - { - mouseDown(x, y); - } - else if(event == "up") - { - mouseUp(x, y); - } - else if(event == "move") - { - mouseMove(x, y); - }; - }; - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if(message_name == "stop") - { - stop(); - } - else if(message_name == "start") - { - F64 rate = 0.0; - if(message_in.hasValue("rate")) - { - rate = message_in.getValueReal("rate"); - } - play(rate); - } - else if(message_name == "pause") - { - pause(); - } - else if(message_name == "seek") - { - F64 time = message_in.getValueReal("time"); - seek(time); - } - else if(message_name == "set_loop") - { - bool loop = message_in.getValueBoolean("loop"); - mIsLooping = loop; - } - else if(message_name == "set_volume") - { - F64 volume = message_in.getValueReal("volume"); - setVolume(volume); - } - } - else - { -// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl; - }; - }; -} - -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); - *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; -} - -#else // LL_QUICKTIME_ENABLED - -// Stubbed-out class with constructor/destructor (necessary or windows linker -// will just think its dead code and optimize it all out) -class MediaPluginQuickTime : public MediaPluginBase -{ -public: - MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginQuickTime(); - /* virtual */ void receiveMessage(const char *message_string); -}; - -MediaPluginQuickTime::MediaPluginQuickTime( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data) -{ - // no-op -} - -MediaPluginQuickTime::~MediaPluginQuickTime() -{ - // no-op -} - -void MediaPluginQuickTime::receiveMessage(const char *message_string) -{ - // no-op -} - -// We're building without quicktime enabled. Just refuse to initialize. -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - return -1; -} - -#endif // LL_QUICKTIME_ENABLED +/** + * @file media_plugin_quicktime.cpp + * @brief QuickTime plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_QUICKTIME_ENABLED + +#if defined(LL_DARWIN) + #include +#elif defined(LL_WINDOWS) + #include "MacTypes.h" + #include "QTML.h" + #include "Movies.h" + #include "QDoffscreen.h" + #include "FixMath.h" + #include "QTLoadLibraryUtils.h" +#endif + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + + /* virtual */ void receiveMessage(const char *message_string); + +private: + + int mNaturalWidth; + int mNaturalHeight; + Movie mMovieHandle; + GWorldPtr mGWorldHandle; + ComponentInstance mMovieController; + int mCurVolume; + bool mMediaSizeChanging; + bool mIsLooping; + std::string mMovieTitle; + bool mReceivedTitle; + const int mMinWidth; + const int mMaxWidth; + const int mMinHeight; + const int mMaxHeight; + F64 mPlayRate; + std::string mNavigateURL; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + + // Override this to add current time and duration to the message + /*virtual*/ void 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); + + if(mMovieHandle) + { + message.setValueReal("current_time", getCurrentTime()); + message.setValueReal("duration", getDuration()); + message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); + } + + sendMessage(message); + } + + + static Rect rectFromSize(int width, int height) + { + Rect result; + + + result.left = 0; + result.top = 0; + result.right = width; + result.bottom = height; + + return result; + } + + Fixed getPlayRate(void) + { + Fixed result; + if(mPlayRate == 0.0f) + { + // Default to the movie's preferred rate + result = GetMoviePreferredRate(mMovieHandle); + if(result == 0) + { + // Don't return a 0 play rate, ever. + std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl; + result = X2Fix(1.0f); + } + } + else + { + result = X2Fix(mPlayRate); + } + + return result; + } + + void load( const std::string url ) + { + + if ( url.empty() ) + return; + + // Stop and unload any existing movie before starting another one. + unload(); + + setStatus(STATUS_LOADING); + + //In case std::string::c_str() makes a copy of the url data, + //make sure there is memory to hold it before allocating memory for handle. + //if fails, NewHandleClear(...) should return NULL. + const char* url_string = url.c_str() ; + Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); + + if ( NULL == handle || noErr != MemError() || NULL == *handle ) + { + setStatus(STATUS_ERROR); + return; + } + + BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); + + OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); + DisposeHandle( handle ); + if ( noErr != err ) + { + setStatus(STATUS_ERROR); + return; + }; + + mNavigateURL = url; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message.setValue("uri", mNavigateURL); + sendMessage(message); + + // do pre-roll actions (typically fired for streaming movies but not always) + PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); + + Rect movie_rect = rectFromSize(mWidth, mHeight); + + // make a new movie controller + mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); + + // movie controller + MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); + + SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); + + // function that gets called when a frame is drawn + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); + + setStatus(STATUS_LOADED); + + sizeChanged(); + }; + + bool unload() + { + // new movie and have to get title again + mReceivedTitle = false; + + if ( mMovieHandle ) + { + StopMovie( mMovieHandle ); + if ( mMovieController ) + { + MCMovieChanged( mMovieController, mMovieHandle ); + }; + }; + + if ( mMovieController ) + { + MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); + DisposeMovieController( mMovieController ); + mMovieController = NULL; + }; + + if ( mMovieHandle ) + { + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); + DisposeMovie( mMovieHandle ); + mMovieHandle = NULL; + }; + + if ( mGWorldHandle ) + { + DisposeGWorld( mGWorldHandle ); + mGWorldHandle = NULL; + }; + + setStatus(STATUS_NONE); + + return true; + } + + bool navigateTo( const std::string url ) + { + unload(); + load( url ); + + return true; + }; + + bool sizeChanged() + { + if ( ! mMovieHandle ) + return false; + + // Check to see whether the movie's natural size has updated + { + int width, height; + getMovieNaturalSize(&width, &height); + if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight))) + { + mNaturalWidth = width; + mNaturalHeight = height; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", width); + message.setValueS32("height", height); + sendMessage(message); + //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; + } + } + + // sanitize destination size + Rect dest_rect = rectFromSize(mWidth, mHeight); + + // media depth won't change + int depth_bits = mDepth * 8; + long rowbytes = mDepth * mTextureWidth; + + GWorldPtr old_gworld_handle = mGWorldHandle; + + if(mPixels != NULL) + { + // We have pixels. Set up a GWorld pointing at the texture. + OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + else + { + // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally. + Rect tempRect = rectFromSize(1, 1); + OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + + SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) ); + + // If the GWorld was already set up, delete it. + if(old_gworld_handle != NULL) + { + DisposeGWorld( old_gworld_handle ); + } + + // Set up the movie display matrix + { + // scale movie to fit rect and invert vertically to match opengl image format + MatrixRecord transform; + SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix + double scaleX = (double) mWidth / mNaturalWidth; + double scaleY = -1.0 * (double) mHeight / mNaturalHeight; + double centerX = mWidth / 2.0; + double centerY = mHeight / 2.0; + ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); + SetMovieMatrix( mMovieHandle, &transform ); + } + + // update movie controller + if ( mMovieController ) + { + MCSetControllerPort( mMovieController, mGWorldHandle ); + MCPositionController( mMovieController, &dest_rect, &dest_rect, + mcTopLeftMovie | mcPositionDontInvalidate ); + MCMovieChanged( mMovieController, mMovieHandle ); + } + + + // Emit event with size change so the calling app knows about it too + // TODO: + //LLMediaEvent event( this ); + //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); + + return true; + } + static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) + { + Boolean result = false; + + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + switch( action ) + { + // handle window resizing + case mcActionControllerSizeChanged: + // Ensure that the movie draws correctly at the new size + self->sizeChanged(); + break; + + // Block any movie controller actions that open URLs. + case mcActionLinkToURL: + case mcActionGetNextURL: + case mcActionLinkToURLExtended: + // Prevent the movie controller from handling the message + result = true; + break; + + default: + break; + }; + + return result; + }; + + static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // IMPORTANT: typically, a consumer who is observing this event will set a flag + // when this event is fired then render later. Be aware that the media stream + // can change during this period - dimensions, depth, format etc. + //LLMediaEvent event( self ); +// self->updateQuickTime(); + // TODO ^^^ + + + if ( self->mWidth > 0 && self->mHeight > 0 ) + self->setDirty( 0, 0, self->mWidth, self->mHeight ); + + return noErr; + }; + + static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // TODO: + //LLMediaEvent event( self ); + //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); + + // Send a "navigate complete" event. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message.setValue("uri", self->mNavigateURL); + message.setValueS32("result_code", 200); + message.setValue("result_string", "OK"); + self->sendMessage(message); + }; + + + void rewind() + { + GoToBeginningOfMovie( mMovieHandle ); + MCMovieChanged( mMovieController, mMovieHandle ); + }; + + bool processState() + { + if ( mCommand == COMMAND_PLAY ) + { + if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE ) + { + long state = GetMovieLoadState( mMovieHandle ); + + if ( state >= kMovieLoadStatePlaythroughOK ) + { + // if the movie is at the end (generally because it reached it naturally) + // and we play is requested, jump back to the start of the movie. + // note: this is different from having loop flag set. + if ( IsMovieDone( mMovieHandle ) ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + }; + + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + setStatus(STATUS_PLAYING); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_STOP ) + { + if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + + setStatus(STATUS_LOADED); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_PAUSE ) + { + if ( mStatus == STATUS_PLAYING ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + setStatus(STATUS_PAUSED); + mCommand = COMMAND_NONE; + }; + }; + }; + + return true; + }; + + void play(F64 rate) + { + mPlayRate = rate; + mCommand = COMMAND_PLAY; + }; + + void stop() + { + mCommand = COMMAND_STOP; + }; + + void pause() + { + mCommand = COMMAND_PAUSE; + }; + + void getMovieNaturalSize(int *movie_width, int *movie_height) + { + Rect rect; + + GetMovieNaturalBoundsRect( mMovieHandle, &rect ); + + int width = ( rect.right - rect.left ); + int height = ( rect.bottom - rect.top ); + + // make sure width and height fall in valid range + if ( width < mMinWidth ) + width = mMinWidth; + + if ( width > mMaxWidth ) + width = mMaxWidth; + + if ( height < mMinHeight ) + height = mMinHeight; + + if ( height > mMaxHeight ) + height = mMaxHeight; + + // return the new rect + *movie_width = width; + *movie_height = height; + } + + void updateQuickTime(int milliseconds) + { + if ( ! mMovieHandle ) + return; + + if ( ! mMovieController ) + return; + + // service QuickTime + // Calling it this way doesn't have good behavior on Windows... +// MoviesTask( mMovieHandle, milliseconds ); + // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle. +// MoviesTask( mMovieHandle, 0 ); + + MCIdle( mMovieController ); + + if ( ! mGWorldHandle ) + return; + + if ( mMediaSizeChanging ) + return; + + // update state machine + processState(); + + // see if title arrived and if so, update member variable with contents + checkTitle(); + + // QT call to see if we are at the end - can't do with controller + if ( IsMovieDone( mMovieHandle ) ) + { + // special code for looping - need to rewind at the end of the movie + if ( mIsLooping ) + { + // go back to start + rewind(); + + if ( mMovieController ) + { + // kick off new play + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + + // set the volume + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + } + else + { + if(mStatus == STATUS_PLAYING) + { + setStatus(STATUS_DONE); + } + } + } + + }; + + int getDataWidth() const + { + if ( mGWorldHandle ) + { + int depth = mDepth; + + if (depth < 1) + depth = 1; + + // ALWAYS use the row bytes from the PixMap if we have a GWorld because + // sometimes it's not the same as mMediaDepth * mMediaWidth ! + PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); + return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth; + } + else + { + // TODO : return LLMediaImplCommon::getaDataWidth(); + return 0; + } + }; + + void seek( F64 time ) + { + if ( mMovieController ) + { + TimeRecord when; + when.scale = GetMovieTimeScale( mMovieHandle ); + when.base = 0; + + // 'time' is in (floating point) seconds. The timebase time will be in 'units', where + // there are 'scale' units per second. + SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); + + when.value.hi = ( SInt32 )( raw_time >> 32 ); + when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); + + MCDoAction( mMovieController, mcActionGoToTime, &when ); + }; + }; + + F64 getLoadedDuration() + { + TimeValue duration; + if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) + { + // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. + duration = GetMovieDuration( mMovieHandle ); + } + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getDuration() + { + TimeValue duration = GetMovieDuration( mMovieHandle ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getCurrentTime() + { + TimeValue curr_time = GetMovieTime( mMovieHandle, 0 ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)curr_time / (F64)scale; + }; + + void setVolume( F64 volume ) + { + mCurVolume = (short)(volume * ( double ) 0x100 ); + + if ( mMovieController ) + { + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update(int milliseconds = 0) + { + updateQuickTime(milliseconds); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // Grab movie title into mMovieTitle - should be called repeatedly + // until it returns true since movie title takes a while to become + // available. + const bool getMovieTitle() + { + // grab meta data from movie + QTMetaDataRef media_data_ref; + OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref ); + if ( noErr != result ) + return false; + + // look up "Display Name" in meta data + OSType meta_data_key = kQTMetaDataCommonKeyDisplayName; + QTMetaDataItem item = kQTMetaDataItemUninitialized; + result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, + 0, kQTMetaDataKeyFormatCommon, + (const UInt8 *)&meta_data_key, + sizeof( meta_data_key ), &item ); + if ( noErr != result ) + return false; + + // find the size of the title + ByteCount size; + result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); + if ( noErr != result || size <= 0 ) + return false; + + // allocate some space and grab it + UInt8* item_data = new UInt8( size ); + memset( item_data, 0, size * sizeof( UInt8* ) ); + result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); + if ( noErr != result ) + return false; + + // save it + mMovieTitle = std::string( (char* )item_data ); + + // clean up + delete [] item_data; + + return true; + }; + + // called regularly to see if title changed + void checkTitle() + { + // we did already receive title so keep checking + if ( ! mReceivedTitle ) + { + // grab title from movie meta data + if ( getMovieTitle() ) + { + // pass back to host application + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", mMovieTitle ); + sendMessage( message ); + + // stop looking once we find a title for this movie. + // TODO: this may to be reset if movie title changes + // during playback but this is okay for now + mReceivedTitle = true; + }; + }; + }; +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data), + mMinWidth( 0 ), + mMaxWidth( 2048 ), + mMinHeight( 0 ), + mMaxHeight( 2048 ) +{ +// std::cerr << "MediaPluginQuickTime constructor" << std::endl; + + mNaturalWidth = -1; + mNaturalHeight = -1; + mMovieHandle = 0; + mGWorldHandle = 0; + mMovieController = 0; + mCurVolume = 0x99; + mMediaSizeChanging = false; + mIsLooping = false; + mMovieTitle = std::string(); + mReceivedTitle = false; + mCommand = COMMAND_NONE; + mPlayRate = 0.0f; + mStatus = STATUS_NONE; +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ +// std::cerr << "MediaPluginQuickTime destructor" << std::endl; + + ExitMovies(); + +#ifdef LL_WINDOWS + TerminateQTML(); +// std::cerr << "QuickTime closing down" << std::endl; +#endif +} + + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ +// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + // Normally a plugin would only specify one of these two subclasses, but this is a demo... + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + #ifdef LL_WINDOWS + + // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime + // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html + // The solution presented there appears to work. + QTLoadLibrary("qtcf.dll"); + + // main initialization for QuickTime - only required on Windows + OSErr result = InitializeQTML( 0L ); + if ( result != noErr ) + { + //TODO: If no QT on Windows, this fails - respond accordingly. + } + else + { + //std::cerr << "QuickTime initialized" << std::endl; + }; + #endif + + // required for both Windows and Mac + EnterMovies(); + + std::string plugin_version = "QuickTime media plugin, QuickTime version "; + + long version = 0; + Gestalt( gestaltQuickTimeVersion, &version ); + std::ostringstream codec( "" ); + codec << std::hex << version << std::dec; + plugin_version += codec.str(); + message.setValue("plugin_version", plugin_version); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + #if defined(LL_WINDOWS) + // Values for Windows + mDepth = 3; + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + + // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. + // Padding to a multiple of 3*32 guarantees it'll divide out properly. + message.setValueU32("padding", 32 * 3); + #else + // Values for Mac + mDepth = 4; + message.setValueU32("format", GL_BGRA_EXT); + #ifdef __BIG_ENDIAN__ + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); + #else + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); + #endif + + // Pad texture width to a multiple of 32 bytes, to line up with cache lines. + message.setValueU32("padding", 32); + #endif + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + // TODO: clean up here + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name +// << ", size: " << info.mSize +// << ", address: " << info.mAddress +// << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + + // Make sure the movie GWorld is no longer pointed at the shared segment. + sizeChanged(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginQuickTime::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 << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + 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"); + + //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl; + + 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); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { +// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl; +// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl; + + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + mMediaSizeChanging = false; + + sizeChanged(); + + update(); + }; + }; + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + load( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + F64 rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + F64 time = message_in.getValueReal("time"); + seek(time); + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); + *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + +#else // LL_QUICKTIME_ENABLED + +// Stubbed-out class with constructor/destructor (necessary or windows linker +// will just think its dead code and optimize it all out) +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + /* virtual */ void receiveMessage(const char *message_string); +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data) +{ + // no-op +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ + // no-op +} + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ + // no-op +} + +// We're building without quicktime enabled. Just refuse to initialize. +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return -1; +} + +#endif // LL_QUICKTIME_ENABLED diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml index ab18febccc..669235af1b 100644 --- a/indra/newview/app_settings/ignorable_dialogs.xml +++ b/indra/newview/app_settings/ignorable_dialogs.xml @@ -1,291 +1,291 @@ - - - - FirstAppearance - - Comment - Enables FirstAppearance warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstAttach - - Comment - Enables FirstAttach warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstBalanceDecrease - - Comment - Enables FirstBalanceDecrease warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstBalanceIncrease - - Comment - Enables FirstBalanceIncrease warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstBuild - - Comment - Enables FirstBuild warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstDebugMenus - - Comment - Enables FirstDebugMenus warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstFlexible - - Comment - Enables FirstFlexible warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstGoTo - - Comment - Enables FirstGoTo warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstInventory - - Comment - Enables FirstInventory warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstLeftClickNoHit - - Comment - Enables FirstLeftClickNoHit warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstMap - - Comment - Enables FirstMap warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstMedia - - Comment - Enables FirstMedia warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstOverrideKeys - - Comment - Enables FirstOverrideKeys warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstSandbox - - Comment - Enables FirstSandbox warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstSculptedPrim - - Comment - Enables FirstSculptedPrim warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstSit - - Comment - Enables FirstSit warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstStreamingMusic - - Comment - Enables FirstStreamingMusic warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstStreamingVideo - - Comment - Enables FirstStreamingVideo warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstTeleport - - Comment - Enables FirstTeleport warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - FirstVoice - - Comment - Enables FirstVoice warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - AboutDirectX9 - - Comment - Enables AboutDirectX9 warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - BrowserLaunch - - Comment - Enables BrowserLaunch warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - DeedObject - - Comment - Enables DeedObject warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - NewClassified - - Comment - Enables NewClassified warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - QuickTimeInstalled - - Comment - Enables QuickTimeInstalled warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - ReturnToOwner - - Comment - Enables ReturnToOwner warning dialog - Persist - 1 - Type - Boolean - Value - 1 - - - + + + + FirstAppearance + + Comment + Enables FirstAppearance warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstAttach + + Comment + Enables FirstAttach warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstBalanceDecrease + + Comment + Enables FirstBalanceDecrease warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstBalanceIncrease + + Comment + Enables FirstBalanceIncrease warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstBuild + + Comment + Enables FirstBuild warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstDebugMenus + + Comment + Enables FirstDebugMenus warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstFlexible + + Comment + Enables FirstFlexible warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstGoTo + + Comment + Enables FirstGoTo warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstInventory + + Comment + Enables FirstInventory warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstLeftClickNoHit + + Comment + Enables FirstLeftClickNoHit warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstMap + + Comment + Enables FirstMap warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstMedia + + Comment + Enables FirstMedia warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstOverrideKeys + + Comment + Enables FirstOverrideKeys warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstSandbox + + Comment + Enables FirstSandbox warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstSculptedPrim + + Comment + Enables FirstSculptedPrim warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstSit + + Comment + Enables FirstSit warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstStreamingMusic + + Comment + Enables FirstStreamingMusic warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstStreamingVideo + + Comment + Enables FirstStreamingVideo warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstTeleport + + Comment + Enables FirstTeleport warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + FirstVoice + + Comment + Enables FirstVoice warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + AboutDirectX9 + + Comment + Enables AboutDirectX9 warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + BrowserLaunch + + Comment + Enables BrowserLaunch warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + DeedObject + + Comment + Enables DeedObject warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + NewClassified + + Comment + Enables NewClassified warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + QuickTimeInstalled + + Comment + Enables QuickTimeInstalled warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + ReturnToOwner + + Comment + Enables ReturnToOwner warning dialog + Persist + 1 + Type + Boolean + Value + 1 + + + diff --git a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt index 30f9349111..185c0180fb 100644 --- a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt +++ b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt @@ -1,6 +1,6 @@ -The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE. - -This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details. - -James Cook -September 2008 +The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE. + +This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details. + +James Cook +September 2008 diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d7be09efa9..2a1fdb081e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -162,16 +162,6 @@ std::string ICON_NAME[ICON_NAME_COUNT] = "inv_item_linkfolder.tga" }; - -// +=================================================+ -// | LLInventoryPanelObserver | -// +=================================================+ -void LLInventoryPanelObserver::changed(U32 mask) -{ - mIP->modelChanged(mask); -} - - // +=================================================+ // | LLInvFVBridge | // +=================================================+ diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 4c7b0a0517..56cb0f93ed 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -107,22 +107,6 @@ struct LLAttachmentRezAction S32 mAttachPt; }; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryPanelObserver -// -// Bridge to support knowing when the inventory has changed. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryPanelObserver : public LLInventoryObserver -{ -public: - LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {} - virtual ~LLInventoryPanelObserver() {} - virtual void changed(U32 mask); -protected: - LLInventoryPanel* mIP; -}; - const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type); void hide_context_entries(LLMenuGL& menu, const std::vector &entries_to_show, diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 95cc68ddbe..efd40576a7 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -1,136 +1,136 @@ -/** - * @file llinventoryfunctions.h - * @brief Miscellaneous inventory-related functions and classes - * class definition - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLINVENTORYFUNCTIONS_H -#define LL_LLINVENTORYFUNCTIONS_H - -#include "llassetstorage.h" -#include "lldarray.h" -#include "llfloater.h" -#include "llinventory.h" -#include "llinventoryfilter.h" -#include "llfolderview.h" -#include "llinventorymodel.h" -#include "lluictrlfactory.h" -#include - - -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel; -class LLInventoryPanel; -class LLInvFVBridge; -class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLScrollContainer; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// This is a collection of miscellaneous functions and classes -// that don't fit cleanly into any other class header. -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryState -{ -public: - // HACK: Until we can route this info through the instant message hierarchy - static BOOL sWearNewClothing; - static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction -}; - -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } -protected: - BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set mOpenFolders; - BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -const std::string& get_item_icon_name(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 attachment_point, - BOOL item_is_multi ); - -LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 attachment_point, - BOOL item_is_multi ); - -#endif // LL_LLINVENTORYFUNCTIONS_H - - - +/** + * @file llinventoryfunctions.h + * @brief Miscellaneous inventory-related functions and classes + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYFUNCTIONS_H +#define LL_LLINVENTORYFUNCTIONS_H + +#include "llassetstorage.h" +#include "lldarray.h" +#include "llfloater.h" +#include "llinventory.h" +#include "llinventoryfilter.h" +#include "llfolderview.h" +#include "llinventorymodel.h" +#include "lluictrlfactory.h" +#include + + +class LLFolderViewItem; +class LLInventoryFilter; +class LLInventoryModel; +class LLInventoryPanel; +class LLInvFVBridge; +class LLInventoryFVBridgeBuilder; +class LLMenuBarGL; +class LLCheckBoxCtrl; +class LLSpinCtrl; +class LLScrollContainer; +class LLTextBox; +class LLIconCtrl; +class LLSaveFolderState; +class LLFilterEditor; +class LLTabContainer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// This is a collection of miscellaneous functions and classes +// that don't fit cleanly into any other class header. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryState +{ +public: + // HACK: Until we can route this info through the instant message hierarchy + static BOOL sWearNewClothing; + static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +const std::string& get_item_icon_name(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ); + +LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ); + +#endif // LL_LLINVENTORYFUNCTIONS_H + + + diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6b1f7313dd..dc704f2b82 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -36,8 +36,6 @@ #include "llinventorypanel.h" -// Seraph TODO: Remove unnecessary headers - #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" @@ -56,6 +54,22 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryPanelObserver +// +// Bridge to support knowing when the inventory has changed. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryPanelObserver : public LLInventoryObserver +{ +public: + LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {} + virtual ~LLInventoryPanelObserver() {} + virtual void changed(U32 mask); +protected: + LLInventoryPanel* mIP; +}; + LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : LLPanel(p), mInventoryObserver(NULL), @@ -872,3 +886,11 @@ void example_param_block_usage() LLUICtrlFactory::create(param_block); } + +// +=================================================+ +// | LLInventoryPanelObserver | +// +=================================================+ +void LLInventoryPanelObserver::changed(U32 mask) +{ + mIP->modelChanged(mask); +} diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 6722bb212e..7a39d8fabc 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -1,102 +1,102 @@ -/** - * @file llpanelobjectinventory.h - * @brief LLPanelObjectInventory class definition - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLPANELOBJECTINVENTORY_H -#define LL_LLPANELOBJECTINVENTORY_H - -#include "llvoinventorylistener.h" -#include "llpanel.h" - -#include "llinventory.h" - -class LLScrollContainer; -class LLFolderView; -class LLFolderViewFolder; -class LLViewerObject; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLPanelObjectInventory -// -// This class represents the panel used to view and control a -// particular task's inventory. -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener -{ -public: - // dummy param block for template registration purposes - struct Params : public LLPanel::Params {}; - - LLPanelObjectInventory(const Params&); - virtual ~LLPanelObjectInventory(); - - virtual BOOL postBuild(); - - void doToSelected(const LLSD& userdata); - - void refresh(); - const LLUUID& getTaskUUID() { return mTaskUUID;} - void removeSelectedItem(); - void startRenamingSelectedItem(); - - LLFolderView* getRootFolder() const { return mFolders; } - - virtual void draw(); - virtual void deleteAllChildren(); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); - - static void idle(void* user_data); - -protected: - void reset(); - /*virtual*/ void inventoryChanged(LLViewerObject* object, - InventoryObjectList* inventory, - S32 serial_num, - void* user_data); - void updateInventory(); - void createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents); - void createViewsForCategory(InventoryObjectList* inventory, - LLInventoryObject* parent, - LLFolderViewFolder* folder); - void clearContents(); - -private: - LLScrollContainer* mScroller; - LLFolderView* mFolders; - - LLUUID mTaskUUID; - BOOL mHaveInventory; - BOOL mIsInventoryEmpty; - BOOL mInventoryNeedsUpdate; -}; - -#endif // LL_LLPANELOBJECTINVENTORY_H +/** + * @file llpanelobjectinventory.h + * @brief LLPanelObjectInventory class definition + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELOBJECTINVENTORY_H +#define LL_LLPANELOBJECTINVENTORY_H + +#include "llvoinventorylistener.h" +#include "llpanel.h" + +#include "llinventory.h" + +class LLScrollContainer; +class LLFolderView; +class LLFolderViewFolder; +class LLViewerObject; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLPanelObjectInventory +// +// This class represents the panel used to view and control a +// particular task's inventory. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener +{ +public: + // dummy param block for template registration purposes + struct Params : public LLPanel::Params {}; + + LLPanelObjectInventory(const Params&); + virtual ~LLPanelObjectInventory(); + + virtual BOOL postBuild(); + + void doToSelected(const LLSD& userdata); + + void refresh(); + const LLUUID& getTaskUUID() { return mTaskUUID;} + void removeSelectedItem(); + void startRenamingSelectedItem(); + + LLFolderView* getRootFolder() const { return mFolders; } + + virtual void draw(); + virtual void deleteAllChildren(); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); + + static void idle(void* user_data); + +protected: + void reset(); + /*virtual*/ void inventoryChanged(LLViewerObject* object, + InventoryObjectList* inventory, + S32 serial_num, + void* user_data); + void updateInventory(); + void createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents); + void createViewsForCategory(InventoryObjectList* inventory, + LLInventoryObject* parent, + LLFolderViewFolder* folder); + void clearContents(); + +private: + LLScrollContainer* mScroller; + LLFolderView* mFolders; + + LLUUID mTaskUUID; + BOOL mHaveInventory; + BOOL mIsInventoryEmpty; + BOOL mInventoryNeedsUpdate; +}; + +#endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/skins/default/html/da/loading/loading.html b/indra/newview/skins/default/html/da/loading/loading.html index 5f3426eb60..cdad5702b9 100644 --- a/indra/newview/skins/default/html/da/loading/loading.html +++ b/indra/newview/skins/default/html/da/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Indlæser... -
- + + + + + + +
+
   Indlæser... +
+ diff --git a/indra/newview/skins/default/html/de/loading/loading.html b/indra/newview/skins/default/html/de/loading/loading.html index 44a621b216..3eddbc24f5 100644 --- a/indra/newview/skins/default/html/de/loading/loading.html +++ b/indra/newview/skins/default/html/de/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Wird geladen... -
- + + + + + + +
+
   Wird geladen... +
+ diff --git a/indra/newview/skins/default/html/en-us/loading/loading.html b/indra/newview/skins/default/html/en-us/loading/loading.html index 1c62d2f73e..34e5c84c4d 100644 --- a/indra/newview/skins/default/html/en-us/loading/loading.html +++ b/indra/newview/skins/default/html/en-us/loading/loading.html @@ -1,9 +1,9 @@ - - - - - -
-
   loading... -
- + + + + + +
+
   loading... +
+ diff --git a/indra/newview/skins/default/html/es/loading/loading.html b/indra/newview/skins/default/html/es/loading/loading.html index c4260b34c0..f03284ba8c 100644 --- a/indra/newview/skins/default/html/es/loading/loading.html +++ b/indra/newview/skins/default/html/es/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Cargando... -
- + + + + + + +
+
   Cargando... +
+ diff --git a/indra/newview/skins/default/html/fr/loading/loading.html b/indra/newview/skins/default/html/fr/loading/loading.html index b3953448e9..23c0ef03bc 100644 --- a/indra/newview/skins/default/html/fr/loading/loading.html +++ b/indra/newview/skins/default/html/fr/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Chargement... -
- + + + + + + +
+
   Chargement... +
+ diff --git a/indra/newview/skins/default/html/hu/loading/loading.html b/indra/newview/skins/default/html/hu/loading/loading.html index ab15a073ba..ade91f76c2 100644 --- a/indra/newview/skins/default/html/hu/loading/loading.html +++ b/indra/newview/skins/default/html/hu/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Betöltés folyamatban... -
- + + + + + + +
+
   Betöltés folyamatban... +
+ diff --git a/indra/newview/skins/default/html/it/loading/loading.html b/indra/newview/skins/default/html/it/loading/loading.html index ab37e41f04..0f9af31f6e 100644 --- a/indra/newview/skins/default/html/it/loading/loading.html +++ b/indra/newview/skins/default/html/it/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Attendi... -
- + + + + + + +
+
   Attendi... +
+ diff --git a/indra/newview/skins/default/html/ja/loading/loading.html b/indra/newview/skins/default/html/ja/loading/loading.html index 35cf74a35f..069dc5d12f 100644 --- a/indra/newview/skins/default/html/ja/loading/loading.html +++ b/indra/newview/skins/default/html/ja/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   ロード中... -
- + + + + + + +
+
   ロード中... +
+ diff --git a/indra/newview/skins/default/html/nl/loading/loading.html b/indra/newview/skins/default/html/nl/loading/loading.html index 0215bd7e47..39a8691f3f 100644 --- a/indra/newview/skins/default/html/nl/loading/loading.html +++ b/indra/newview/skins/default/html/nl/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Laden... -
- + + + + + + +
+
   Laden... +
+ diff --git a/indra/newview/skins/default/html/pl/loading/loading.html b/indra/newview/skins/default/html/pl/loading/loading.html index 50f3dfb0c5..515890c2d5 100644 --- a/indra/newview/skins/default/html/pl/loading/loading.html +++ b/indra/newview/skins/default/html/pl/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Ładowanie... -
- + + + + + + +
+
   Ładowanie... +
+ diff --git a/indra/newview/skins/default/html/pt/loading/loading.html b/indra/newview/skins/default/html/pt/loading/loading.html index a83e1123d0..635ea62406 100644 --- a/indra/newview/skins/default/html/pt/loading/loading.html +++ b/indra/newview/skins/default/html/pt/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Carregando... -
- + + + + + + +
+
   Carregando... +
+ diff --git a/indra/newview/skins/default/html/ru/loading/loading.html b/indra/newview/skins/default/html/ru/loading/loading.html index 892c0b9f7f..dcc0d73c1a 100644 --- a/indra/newview/skins/default/html/ru/loading/loading.html +++ b/indra/newview/skins/default/html/ru/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Загрузка... -
- + + + + + + +
+
   Загрузка... +
+ diff --git a/indra/newview/skins/default/html/tr/loading/loading.html b/indra/newview/skins/default/html/tr/loading/loading.html index 1ac07bff34..e7812e7c8e 100644 --- a/indra/newview/skins/default/html/tr/loading/loading.html +++ b/indra/newview/skins/default/html/tr/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Yükleniyor... -
- + + + + + + +
+
   Yükleniyor... +
+ diff --git a/indra/newview/skins/default/html/uk/loading/loading.html b/indra/newview/skins/default/html/uk/loading/loading.html index 3b5b8679b4..0f67994635 100644 --- a/indra/newview/skins/default/html/uk/loading/loading.html +++ b/indra/newview/skins/default/html/uk/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   Завантаж... -
- + + + + + + +
+
   Завантаж... +
+ diff --git a/indra/newview/skins/default/html/zh/loading/loading.html b/indra/newview/skins/default/html/zh/loading/loading.html index d1d5d25c92..462ea291d9 100644 --- a/indra/newview/skins/default/html/zh/loading/loading.html +++ b/indra/newview/skins/default/html/zh/loading/loading.html @@ -1,10 +1,10 @@ - - - - - - -
-
   请等待... -
- + + + + + + +
+
   请等待... +
+ diff --git a/indra/newview/skins/default/xui/da/panel_edit_profile.xml b/indra/newview/skins/default/xui/da/panel_edit_profile.xml index b4d0fa20ef..74b7c7dd72 100644 --- a/indra/newview/skins/default/xui/da/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/da/panel_edit_profile.xml @@ -1,45 +1,45 @@ - - - - [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] - - - - - - - - - - - - http://www.secondlife.com/account/partners.php?lang=da - - - - - - - [SECOND_LIFE]: - - - - - - - - - Optaget autosvar: - - - - + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + + + + + + + + + + http://www.secondlife.com/account/partners.php?lang=da + + + + + + + [SECOND_LIFE]: + + + + + + + + + Optaget autosvar: + + + + diff --git a/indra/newview/skins/default/xui/es/panel_edit_profile.xml b/indra/newview/skins/default/xui/es/panel_edit_profile.xml index c12dd8d58c..bcf4128e01 100644 --- a/indra/newview/skins/default/xui/es/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/es/panel_edit_profile.xml @@ -1,45 +1,45 @@ - - - - [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] - - - - - - - - - - - - http://www.secondlife.com/account/partners.php?lang=es - - - - - - - [SECOND_LIFE]: - - - - - - - - - Mensaje en el estado ocupado: - - - - + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + + + + + + + + + + http://www.secondlife.com/account/partners.php?lang=es + + + + + + + [SECOND_LIFE]: + + + + + + + + + Mensaje en el estado ocupado: + + + + diff --git a/indra/newview/skins/default/xui/it/panel_edit_profile.xml b/indra/newview/skins/default/xui/it/panel_edit_profile.xml index 33f3c367c2..0eba7bf3b6 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_profile.xml @@ -1,45 +1,45 @@ - - - - [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] - - - - - - - - - - - - http://www.secondlife.com/account/partners.php?lang=it - - - - - - - [SECOND_LIFE]: - - - - - - - - - Risposta agli IM quando sono in 'Occupato': - - - - + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + + + + + + + + + + http://www.secondlife.com/account/partners.php?lang=it + + + + + + + [SECOND_LIFE]: + + + + + + + + + Risposta agli IM quando sono in 'Occupato': + + + + diff --git a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml index 172395e20a..00f8c087de 100644 --- a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml @@ -1,45 +1,45 @@ - - - - [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] - - - - - - - - - - - - http://www.secondlife.com/account/partners.php?lang=nl - - - - - - - [SECOND_LIFE]: - - - - - - - - - Antwoord bij Niet Storen: - - - - + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + + + + + + + + + + http://www.secondlife.com/account/partners.php?lang=nl + + + + + + + [SECOND_LIFE]: + + + + + + + + + Antwoord bij Niet Storen: + + + + diff --git a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml index 97fa3118f8..e449a92d7e 100644 --- a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml @@ -1,45 +1,45 @@ - - - - [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] - - - - - - - - - - - - http://www.secondlife.com/account/partners.php?lang=pl - - - - - - - [SECOND_LIFE]: - - - - - - - - - Pracuś Mówi: - - - - + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + + + + + + + + + + http://www.secondlife.com/account/partners.php?lang=pl + + + + + + + [SECOND_LIFE]: + + + + + + + + + Pracuś Mówi: + + + + diff --git a/indra/newview/skins/default/xui/pt/panel_edit_profile.xml b/indra/newview/skins/default/xui/pt/panel_edit_profile.xml index a989cab167..e97e77cfe6 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_profile.xml @@ -1,45 +1,45 @@ - - - - [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] - - - - - - - - - - - - http://www.secondlife.com/account/partners.php?lang=pt - - - - - - - [SECOND_LIFE]: - - - - - - - - - Resposta no Modo Ocupado: - - - - + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + + + + + + + + + + http://www.secondlife.com/account/partners.php?lang=pt + + + + + + + [SECOND_LIFE]: + + + + + + + + + Resposta no Modo Ocupado: + + + + diff --git a/indra/tools/vstool/README.txt b/indra/tools/vstool/README.txt index 6f64aa41df..e419180031 100644 --- a/indra/tools/vstool/README.txt +++ b/indra/tools/vstool/README.txt @@ -1,9 +1,9 @@ -VSTool is a command line utility to manipulate VisualStudio settings. - -The windows cmake project configuration uses VSTool.exe - -A handy upgrade: - figure out how to make cmake build this csharp app - - or write the app using script (jscript?!?) so it doesn't need to be built. - - +VSTool is a command line utility to manipulate VisualStudio settings. + +The windows cmake project configuration uses VSTool.exe + +A handy upgrade: + figure out how to make cmake build this csharp app + - or write the app using script (jscript?!?) so it doesn't need to be built. + + diff --git a/indra/tools/vstool/VSTool.csproj b/indra/tools/vstool/VSTool.csproj index 5d8764b6bf..24f1031f81 100644 --- a/indra/tools/vstool/VSTool.csproj +++ b/indra/tools/vstool/VSTool.csproj @@ -1,95 +1,95 @@ - - - Local - 8.0.50727 - 2.0 - {96943E2D-1373-4617-A117-D0F997A94919} - Debug - AnyCPU - - - - - VSTool - - - JScript - Grid - IE50 - false - Exe - VSTool - Always - VSTool.VSToolMain - - - - - - - .\ - false - 285212672 - false - - - DEBUG;TRACE - - - true - 4096 - false - - - false - false - false - false - 4 - full - prompt - - - .\ - false - 285212672 - false - - - TRACE - - - false - 4096 - false - - - true - false - false - false - 4 - none - prompt - - - - System - - - System.Data - - - - - Code - - - - - - - - - + + + Local + 8.0.50727 + 2.0 + {96943E2D-1373-4617-A117-D0F997A94919} + Debug + AnyCPU + + + + + VSTool + + + JScript + Grid + IE50 + false + Exe + VSTool + Always + VSTool.VSToolMain + + + + + + + .\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + .\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + System + + + System.Data + + + + + Code + + + + + + + + + \ No newline at end of file diff --git a/indra/tools/vstool/VSTool.sln b/indra/tools/vstool/VSTool.sln index 543a0a2efc..8859671802 100644 --- a/indra/tools/vstool/VSTool.sln +++ b/indra/tools/vstool/VSTool.sln @@ -1,19 +1,19 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/indra/tools/vstool/main.cs b/indra/tools/vstool/main.cs index 5c41c916e2..cc268d59d9 100644 --- a/indra/tools/vstool/main.cs +++ b/indra/tools/vstool/main.cs @@ -1,711 +1,711 @@ -// Code about getting running instances visual studio -// was borrowed from -// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using Microsoft.CSharp; - -namespace VSTool -{ - // The MessageFilter class comes from: - // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx - // It allows vstool to get timing error messages from - // visualstudio and handle them. - public class MessageFilter : IOleMessageFilter - { - // - // Class containing the IOleMessageFilter - // thread error-handling functions. - - // Start the filter. - public static void Register() - { - IOleMessageFilter newFilter = new MessageFilter(); - IOleMessageFilter oldFilter = null; - CoRegisterMessageFilter(newFilter, out oldFilter); - } - - // Done with the filter, close it. - public static void Revoke() - { - IOleMessageFilter oldFilter = null; - CoRegisterMessageFilter(null, out oldFilter); - } - - // - // IOleMessageFilter functions. - // Handle incoming thread requests. - int IOleMessageFilter.HandleInComingCall(int dwCallType, - System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr - lpInterfaceInfo) - { - //Return the flag SERVERCALL_ISHANDLED. - return 0; - } - - // Thread call was rejected, so try again. - int IOleMessageFilter.RetryRejectedCall(System.IntPtr - hTaskCallee, int dwTickCount, int dwRejectType) - { - if (dwRejectType == 2) - // flag = SERVERCALL_RETRYLATER. - { - // Retry the thread call immediately if return >=0 & - // <100. - return 99; - } - // Too busy; cancel call. - return -1; - } - - int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, - int dwTickCount, int dwPendingType) - { - //Return the flag PENDINGMSG_WAITDEFPROCESS. - return 2; - } - - // Implement the IOleMessageFilter interface. - [DllImport("Ole32.dll")] - private static extern int - CoRegisterMessageFilter(IOleMessageFilter newFilter, out - IOleMessageFilter oldFilter); - } - - [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), - InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] - interface IOleMessageFilter - { - [PreserveSig] - int HandleInComingCall( - int dwCallType, - IntPtr hTaskCaller, - int dwTickCount, - IntPtr lpInterfaceInfo); - - [PreserveSig] - int RetryRejectedCall( - IntPtr hTaskCallee, - int dwTickCount, - int dwRejectType); - - [PreserveSig] - int MessagePending( - IntPtr hTaskCallee, - int dwTickCount, - int dwPendingType); - } - - class ViaCOM - { - public static object GetProperty(object from_obj, string prop_name) - { - try - { - Type objType = from_obj.GetType(); - return objType.InvokeMember( - prop_name, - BindingFlags.GetProperty, null, - from_obj, - null); - } - catch (Exception e) - { - Console.WriteLine("Error getting property: \"{0}\"", prop_name); - Console.WriteLine(e.Message); - throw e; - } - } - - public static object SetProperty(object from_obj, string prop_name, object new_value) - { - try - { - object[] args = { new_value }; - Type objType = from_obj.GetType(); - return objType.InvokeMember( - prop_name, - BindingFlags.DeclaredOnly | - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.SetProperty, - null, - from_obj, - args); - } - catch (Exception e) - { - Console.WriteLine("Error setting property: \"{0}\"", prop_name); - Console.WriteLine(e.Message); - throw e; - } - } - - public static object CallMethod(object from_obj, string method_name, params object[] args) - { - try - { - Type objType = from_obj.GetType(); - return objType.InvokeMember( - method_name, - BindingFlags.DeclaredOnly | - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.InvokeMethod, - null, - from_obj, - args); - } - catch (Exception e) - { - Console.WriteLine("Error calling method \"{0}\"", method_name); - Console.WriteLine(e.Message); - throw e; - } - } - }; - - /// - /// The main entry point class for VSTool. - /// - class VSToolMain - { - #region Interop imports - [DllImport("ole32.dll")] - public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); - - [DllImport("ole32.dll")] - public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); - #endregion - - static System.Boolean ignore_case = true; - - static string solution_name = null; - static bool use_new_vs = false; - static Hashtable projectDict = new Hashtable(); - static string startup_project = null; - static string config = null; - - static object dte = null; - static object solution = null; - - /// - /// The main entry point for the application. - /// - [STAThread] - static int Main(string[] args) - { - int retVal = 0; - bool need_save = false; - - try - { - parse_command_line(args); - - Console.WriteLine("Editing solution: {0}", solution_name); - - bool found_open_solution = GetDTEAndSolution(); - - if (dte == null || solution == null) - { - retVal = 1; - } - else - { - MessageFilter.Register(); - - // Walk through all of the projects in the solution - // and list the type of each project. - foreach (DictionaryEntry p in projectDict) - { - string project_name = (string)p.Key; - string working_dir = (string)p.Value; - if (SetProjectWorkingDir(solution, project_name, working_dir)) - { - need_save = true; - } - } - - if (config != null) - { - need_save = SetActiveConfig(config); - } - - if (startup_project != null) - { - need_save = SetStartupProject(startup_project); - } - - if (need_save) - { - if (found_open_solution == false) - { - ViaCOM.CallMethod(solution, "Close", null); - } - } - } - } - catch (Exception e) - { - Console.WriteLine(e.Message); - retVal = 1; - } - finally - { - if (solution != null) - { - Marshal.ReleaseComObject(solution); - solution = null; - } - - if (dte != null) - { - Marshal.ReleaseComObject(dte); - dte = null; - } - - MessageFilter.Revoke(); - } - return retVal; - } - - public static bool parse_command_line(string[] args) - { - string options_desc = - "--solution : MSVC solution name. (required)\n" + - "--use_new_vs : Ignore running versions of visual studio.\n" + - "--workingdir : Set working dir of a VC project.\n" + - "--config : Set the active config for the solution.\n" + - "--startup : Set the startup project for the solution.\n"; - - try - { - // Command line param parsing loop. - int i = 0; - for (; i < args.Length; ++i) - { - if ("--solution" == args[i]) - { - if (solution_name != null) - { - throw new ApplicationException("Found second --solution option"); - } - solution_name = args[++i]; - } - else if ("--use_new_vs" == args[i]) - { - use_new_vs = true; - } - - else if ("--workingdir" == args[i]) - { - string project_name = args[++i]; - string working_dir = args[++i]; - projectDict.Add(project_name, working_dir); - } - else if ("--config" == args[i]) - { - if (config != null) - { - throw new ApplicationException("Found second --config option"); - } - config = args[++i]; - } - else if ("--startup" == args[i]) - { - if (startup_project != null) - { - throw new ApplicationException("Found second --startup option"); - } - startup_project = args[++i]; - } - else - { - throw new ApplicationException("Found unrecognized token on command line: " + args[i]); - } - } - - if (solution_name == null) - { - throw new ApplicationException("The --solution option is required."); - } - } - catch(ApplicationException e) - { - - Console.WriteLine("Oops! " + e.Message); - Console.Write("Command line:"); - foreach (string arg in args) - { - Console.Write(" " + arg); - } - Console.Write("\n\n"); - Console.WriteLine("VSTool command line usage"); - Console.Write(options_desc); - throw e; - } - return true; - } - - public static bool GetDTEAndSolution() - { - bool found_open_solution = true; - - Console.WriteLine("Looking for existing VisualStudio instance..."); - - // Get an instance of the currently running Visual Studio .NET IDE. - // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1"); - string full_solution_name = System.IO.Path.GetFullPath(solution_name); - if (false == use_new_vs) - { - dte = GetIDEInstance(full_solution_name); - } - - if (dte == null) - { - try - { - Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance..."); - Console.WriteLine(" Reading .sln file version..."); - string version = GetSolutionVersion(full_solution_name); - - Console.WriteLine(" Using version: {0}...", version); - string progid = GetVSProgID(version); - - Type objType = Type.GetTypeFromProgID(progid); - dte = System.Activator.CreateInstance(objType); - Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name); - - solution = ViaCOM.GetProperty(dte, "Solution"); - object[] openArgs = { full_solution_name }; - ViaCOM.CallMethod(solution, "Open", openArgs); - } - catch (Exception e) - { - Console.WriteLine(e.Message); - Console.WriteLine("Quitting do to error opening: {0}", full_solution_name); - solution = null; - dte = null; - return found_open_solution; - } - found_open_solution = false; - } - - if (solution == null) - { - solution = ViaCOM.GetProperty(dte, "Solution"); - } - - return found_open_solution; - } - - /// - /// Get the DTE object for the instance of Visual Studio IDE that has - /// the specified solution open. - /// - /// The absolute filename of the solution - /// Corresponding DTE object or null if no such IDE is running - public static object GetIDEInstance( string solutionFile ) - { - Hashtable runningInstances = GetIDEInstances( true ); - IDictionaryEnumerator enumerator = runningInstances.GetEnumerator(); - - while ( enumerator.MoveNext() ) - { - try - { - object ide = enumerator.Value; - if (ide != null) - { - object sol = ViaCOM.GetProperty(ide, "Solution"); - if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case)) - { - return ide; - } - } - } - catch{} - } - - return null; - } - - /// - /// Get a table of the currently running instances of the Visual Studio .NET IDE. - /// - /// Only return instances that have opened a solution - /// A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object - public static Hashtable GetIDEInstances( bool openSolutionsOnly ) - { - Hashtable runningIDEInstances = new Hashtable(); - Hashtable runningObjects = GetRunningObjectTable(); - - IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator(); - while ( rotEnumerator.MoveNext() ) - { - string candidateName = (string) rotEnumerator.Key; - if (!candidateName.StartsWith("!VisualStudio.DTE")) - continue; - - object ide = rotEnumerator.Value; - if (ide == null) - continue; - - if (openSolutionsOnly) - { - try - { - object sol = ViaCOM.GetProperty(ide, "Solution"); - string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName"); - if (solutionFile != String.Empty) - { - runningIDEInstances[ candidateName ] = ide; - } - } - catch {} - } - else - { - runningIDEInstances[ candidateName ] = ide; - } - } - return runningIDEInstances; - } - - /// - /// Get a snapshot of the running object table (ROT). - /// - /// A hashtable mapping the name of the object in the ROT to the corresponding object - [STAThread] - public static Hashtable GetRunningObjectTable() - { - Hashtable result = new Hashtable(); - - int numFetched = 0; - IRunningObjectTable runningObjectTable; - IEnumMoniker monikerEnumerator; - IMoniker[] monikers = new IMoniker[1]; - - GetRunningObjectTable(0, out runningObjectTable); - runningObjectTable.EnumRunning(out monikerEnumerator); - monikerEnumerator.Reset(); - - while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0) - { - IBindCtx ctx; - CreateBindCtx(0, out ctx); - - string runningObjectName; - monikers[0].GetDisplayName(ctx, null, out runningObjectName); - - object runningObjectVal; - runningObjectTable.GetObject( monikers[0], out runningObjectVal); - - result[ runningObjectName ] = runningObjectVal; - } - - return result; - } - - public static string GetSolutionVersion(string solutionFullFileName) - { - string version; - System.IO.StreamReader solutionStreamReader = null; - string firstLine; - string format; - - try - { - solutionStreamReader = new System.IO.StreamReader(solutionFullFileName); - do - { - firstLine = solutionStreamReader.ReadLine(); - } - while (firstLine == ""); - - format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim(); - - switch(format) - { - case "7.00": - version = "VC70"; - break; - - case "8.00": - version = "VC71"; - break; - - case "9.00": - version = "VC80"; - break; - - case "10.00": - version = "VC90"; - break; - default: - throw new ApplicationException("Unknown .sln version: " + format); - } - } - finally - { - if(solutionStreamReader != null) - { - solutionStreamReader.Close(); - } - } - - return version; - } - - public static string GetVSProgID(string version) - { - string progid = null; - switch(version) - { - case "VC70": - progid = "VisualStudio.DTE.7"; - break; - - case "VC71": - progid = "VisualStudio.DTE.7.1"; - break; - - case "VC80": - progid = "VisualStudio.DTE.8.0"; - break; - - case "VC90": - progid = "VisualStudio.DTE.9.0"; - break; - default: - throw new ApplicationException("Can't handle VS version: " + version); - } - - return progid; - } - - public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir) - { - bool made_change = false; - Console.WriteLine("Looking for project {0}...", project_name); - try - { - object prjs = ViaCOM.GetProperty(sol, "Projects"); - object count = ViaCOM.GetProperty(prjs, "Count"); - for(int i = 1; i <= (int)count; ++i) - { - object[] prjItemArgs = { (object)i }; - object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs); - string name = (string)ViaCOM.GetProperty(prj, "Name"); - if (0 == string.Compare(name, project_name, ignore_case)) - { - Console.WriteLine("Found project: {0}", project_name); - Console.WriteLine("Setting working directory"); - - string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName"); - Console.WriteLine(full_project_name); - - // *NOTE:Mani Thanks to incompatibilities between different versions of the - // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to - // the VCProjectEngine types from a different version than the one built - // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built - // in VS 8.0. To avoid this problem, we can use the com object interfaces directly, - // without the type casting. Its tedious code, but it seems to work. - - // oCfgs should be assigned to a 'Project.Configurations' collection. - object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations"); - - // oCount will be assigned to the number of configs present in oCfgs. - object oCount = ViaCOM.GetProperty(oCfgs, "Count"); - - for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex) - { - object[] itemArgs = {(object)cfgIndex}; - object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs); - object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings"); - ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir); - } - - break; - } - } - made_change = true; - } - catch( Exception e ) - { - Console.WriteLine(e.Message); - Console.WriteLine("Failed to set working dir for project, {0}.", project_name); - } - - return made_change; - } - - public static bool SetStartupProject(string startup_project) - { - bool result = false; - try - { - // You need the 'unique name of the project to set StartupProjects. - // find the project by generic name. - Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project); - object prjs = ViaCOM.GetProperty(solution, "Projects"); - object count = ViaCOM.GetProperty(prjs, "Count"); - for (int i = 1; i <= (int)count; ++i) - { - object[] itemArgs = { (object)i }; - object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs); - object prjName = ViaCOM.GetProperty(prj, "Name"); - if (0 == string.Compare((string)prjName, startup_project, ignore_case)) - { - object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); - ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName")); - Console.WriteLine(" Success!"); - result = true; - break; - } - } - - if (result == false) - { - Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project); - } - } - catch (Exception e) - { - Console.WriteLine(" Failed to set the startup project!"); - Console.WriteLine(e.Message); - } - return result; - } - - public static bool SetActiveConfig(string config) - { - bool result = false; - try - { - Console.WriteLine("Trying to set active config to \"{0}\"", config); - object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); - object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations"); - object[] itemArgs = { (object)config }; - object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs); - ViaCOM.CallMethod(solCfg, "Activate", null); - Console.WriteLine(" Success!"); - result = true; - } - catch (Exception e) - { - Console.WriteLine(" Failed to set \"{0}\" as the active config.", config); - Console.WriteLine(e.Message); - } - return result; - } - } -} +// Code about getting running instances visual studio +// was borrowed from +// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.CSharp; + +namespace VSTool +{ + // The MessageFilter class comes from: + // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx + // It allows vstool to get timing error messages from + // visualstudio and handle them. + public class MessageFilter : IOleMessageFilter + { + // + // Class containing the IOleMessageFilter + // thread error-handling functions. + + // Start the filter. + public static void Register() + { + IOleMessageFilter newFilter = new MessageFilter(); + IOleMessageFilter oldFilter = null; + CoRegisterMessageFilter(newFilter, out oldFilter); + } + + // Done with the filter, close it. + public static void Revoke() + { + IOleMessageFilter oldFilter = null; + CoRegisterMessageFilter(null, out oldFilter); + } + + // + // IOleMessageFilter functions. + // Handle incoming thread requests. + int IOleMessageFilter.HandleInComingCall(int dwCallType, + System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr + lpInterfaceInfo) + { + //Return the flag SERVERCALL_ISHANDLED. + return 0; + } + + // Thread call was rejected, so try again. + int IOleMessageFilter.RetryRejectedCall(System.IntPtr + hTaskCallee, int dwTickCount, int dwRejectType) + { + if (dwRejectType == 2) + // flag = SERVERCALL_RETRYLATER. + { + // Retry the thread call immediately if return >=0 & + // <100. + return 99; + } + // Too busy; cancel call. + return -1; + } + + int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, + int dwTickCount, int dwPendingType) + { + //Return the flag PENDINGMSG_WAITDEFPROCESS. + return 2; + } + + // Implement the IOleMessageFilter interface. + [DllImport("Ole32.dll")] + private static extern int + CoRegisterMessageFilter(IOleMessageFilter newFilter, out + IOleMessageFilter oldFilter); + } + + [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + interface IOleMessageFilter + { + [PreserveSig] + int HandleInComingCall( + int dwCallType, + IntPtr hTaskCaller, + int dwTickCount, + IntPtr lpInterfaceInfo); + + [PreserveSig] + int RetryRejectedCall( + IntPtr hTaskCallee, + int dwTickCount, + int dwRejectType); + + [PreserveSig] + int MessagePending( + IntPtr hTaskCallee, + int dwTickCount, + int dwPendingType); + } + + class ViaCOM + { + public static object GetProperty(object from_obj, string prop_name) + { + try + { + Type objType = from_obj.GetType(); + return objType.InvokeMember( + prop_name, + BindingFlags.GetProperty, null, + from_obj, + null); + } + catch (Exception e) + { + Console.WriteLine("Error getting property: \"{0}\"", prop_name); + Console.WriteLine(e.Message); + throw e; + } + } + + public static object SetProperty(object from_obj, string prop_name, object new_value) + { + try + { + object[] args = { new_value }; + Type objType = from_obj.GetType(); + return objType.InvokeMember( + prop_name, + BindingFlags.DeclaredOnly | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.SetProperty, + null, + from_obj, + args); + } + catch (Exception e) + { + Console.WriteLine("Error setting property: \"{0}\"", prop_name); + Console.WriteLine(e.Message); + throw e; + } + } + + public static object CallMethod(object from_obj, string method_name, params object[] args) + { + try + { + Type objType = from_obj.GetType(); + return objType.InvokeMember( + method_name, + BindingFlags.DeclaredOnly | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.InvokeMethod, + null, + from_obj, + args); + } + catch (Exception e) + { + Console.WriteLine("Error calling method \"{0}\"", method_name); + Console.WriteLine(e.Message); + throw e; + } + } + }; + + /// + /// The main entry point class for VSTool. + /// + class VSToolMain + { + #region Interop imports + [DllImport("ole32.dll")] + public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); + + [DllImport("ole32.dll")] + public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); + #endregion + + static System.Boolean ignore_case = true; + + static string solution_name = null; + static bool use_new_vs = false; + static Hashtable projectDict = new Hashtable(); + static string startup_project = null; + static string config = null; + + static object dte = null; + static object solution = null; + + /// + /// The main entry point for the application. + /// + [STAThread] + static int Main(string[] args) + { + int retVal = 0; + bool need_save = false; + + try + { + parse_command_line(args); + + Console.WriteLine("Editing solution: {0}", solution_name); + + bool found_open_solution = GetDTEAndSolution(); + + if (dte == null || solution == null) + { + retVal = 1; + } + else + { + MessageFilter.Register(); + + // Walk through all of the projects in the solution + // and list the type of each project. + foreach (DictionaryEntry p in projectDict) + { + string project_name = (string)p.Key; + string working_dir = (string)p.Value; + if (SetProjectWorkingDir(solution, project_name, working_dir)) + { + need_save = true; + } + } + + if (config != null) + { + need_save = SetActiveConfig(config); + } + + if (startup_project != null) + { + need_save = SetStartupProject(startup_project); + } + + if (need_save) + { + if (found_open_solution == false) + { + ViaCOM.CallMethod(solution, "Close", null); + } + } + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + retVal = 1; + } + finally + { + if (solution != null) + { + Marshal.ReleaseComObject(solution); + solution = null; + } + + if (dte != null) + { + Marshal.ReleaseComObject(dte); + dte = null; + } + + MessageFilter.Revoke(); + } + return retVal; + } + + public static bool parse_command_line(string[] args) + { + string options_desc = + "--solution : MSVC solution name. (required)\n" + + "--use_new_vs : Ignore running versions of visual studio.\n" + + "--workingdir : Set working dir of a VC project.\n" + + "--config : Set the active config for the solution.\n" + + "--startup : Set the startup project for the solution.\n"; + + try + { + // Command line param parsing loop. + int i = 0; + for (; i < args.Length; ++i) + { + if ("--solution" == args[i]) + { + if (solution_name != null) + { + throw new ApplicationException("Found second --solution option"); + } + solution_name = args[++i]; + } + else if ("--use_new_vs" == args[i]) + { + use_new_vs = true; + } + + else if ("--workingdir" == args[i]) + { + string project_name = args[++i]; + string working_dir = args[++i]; + projectDict.Add(project_name, working_dir); + } + else if ("--config" == args[i]) + { + if (config != null) + { + throw new ApplicationException("Found second --config option"); + } + config = args[++i]; + } + else if ("--startup" == args[i]) + { + if (startup_project != null) + { + throw new ApplicationException("Found second --startup option"); + } + startup_project = args[++i]; + } + else + { + throw new ApplicationException("Found unrecognized token on command line: " + args[i]); + } + } + + if (solution_name == null) + { + throw new ApplicationException("The --solution option is required."); + } + } + catch(ApplicationException e) + { + + Console.WriteLine("Oops! " + e.Message); + Console.Write("Command line:"); + foreach (string arg in args) + { + Console.Write(" " + arg); + } + Console.Write("\n\n"); + Console.WriteLine("VSTool command line usage"); + Console.Write(options_desc); + throw e; + } + return true; + } + + public static bool GetDTEAndSolution() + { + bool found_open_solution = true; + + Console.WriteLine("Looking for existing VisualStudio instance..."); + + // Get an instance of the currently running Visual Studio .NET IDE. + // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1"); + string full_solution_name = System.IO.Path.GetFullPath(solution_name); + if (false == use_new_vs) + { + dte = GetIDEInstance(full_solution_name); + } + + if (dte == null) + { + try + { + Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance..."); + Console.WriteLine(" Reading .sln file version..."); + string version = GetSolutionVersion(full_solution_name); + + Console.WriteLine(" Using version: {0}...", version); + string progid = GetVSProgID(version); + + Type objType = Type.GetTypeFromProgID(progid); + dte = System.Activator.CreateInstance(objType); + Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name); + + solution = ViaCOM.GetProperty(dte, "Solution"); + object[] openArgs = { full_solution_name }; + ViaCOM.CallMethod(solution, "Open", openArgs); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine("Quitting do to error opening: {0}", full_solution_name); + solution = null; + dte = null; + return found_open_solution; + } + found_open_solution = false; + } + + if (solution == null) + { + solution = ViaCOM.GetProperty(dte, "Solution"); + } + + return found_open_solution; + } + + /// + /// Get the DTE object for the instance of Visual Studio IDE that has + /// the specified solution open. + /// + /// The absolute filename of the solution + /// Corresponding DTE object or null if no such IDE is running + public static object GetIDEInstance( string solutionFile ) + { + Hashtable runningInstances = GetIDEInstances( true ); + IDictionaryEnumerator enumerator = runningInstances.GetEnumerator(); + + while ( enumerator.MoveNext() ) + { + try + { + object ide = enumerator.Value; + if (ide != null) + { + object sol = ViaCOM.GetProperty(ide, "Solution"); + if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case)) + { + return ide; + } + } + } + catch{} + } + + return null; + } + + /// + /// Get a table of the currently running instances of the Visual Studio .NET IDE. + /// + /// Only return instances that have opened a solution + /// A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object + public static Hashtable GetIDEInstances( bool openSolutionsOnly ) + { + Hashtable runningIDEInstances = new Hashtable(); + Hashtable runningObjects = GetRunningObjectTable(); + + IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator(); + while ( rotEnumerator.MoveNext() ) + { + string candidateName = (string) rotEnumerator.Key; + if (!candidateName.StartsWith("!VisualStudio.DTE")) + continue; + + object ide = rotEnumerator.Value; + if (ide == null) + continue; + + if (openSolutionsOnly) + { + try + { + object sol = ViaCOM.GetProperty(ide, "Solution"); + string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName"); + if (solutionFile != String.Empty) + { + runningIDEInstances[ candidateName ] = ide; + } + } + catch {} + } + else + { + runningIDEInstances[ candidateName ] = ide; + } + } + return runningIDEInstances; + } + + /// + /// Get a snapshot of the running object table (ROT). + /// + /// A hashtable mapping the name of the object in the ROT to the corresponding object + [STAThread] + public static Hashtable GetRunningObjectTable() + { + Hashtable result = new Hashtable(); + + int numFetched = 0; + IRunningObjectTable runningObjectTable; + IEnumMoniker monikerEnumerator; + IMoniker[] monikers = new IMoniker[1]; + + GetRunningObjectTable(0, out runningObjectTable); + runningObjectTable.EnumRunning(out monikerEnumerator); + monikerEnumerator.Reset(); + + while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0) + { + IBindCtx ctx; + CreateBindCtx(0, out ctx); + + string runningObjectName; + monikers[0].GetDisplayName(ctx, null, out runningObjectName); + + object runningObjectVal; + runningObjectTable.GetObject( monikers[0], out runningObjectVal); + + result[ runningObjectName ] = runningObjectVal; + } + + return result; + } + + public static string GetSolutionVersion(string solutionFullFileName) + { + string version; + System.IO.StreamReader solutionStreamReader = null; + string firstLine; + string format; + + try + { + solutionStreamReader = new System.IO.StreamReader(solutionFullFileName); + do + { + firstLine = solutionStreamReader.ReadLine(); + } + while (firstLine == ""); + + format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim(); + + switch(format) + { + case "7.00": + version = "VC70"; + break; + + case "8.00": + version = "VC71"; + break; + + case "9.00": + version = "VC80"; + break; + + case "10.00": + version = "VC90"; + break; + default: + throw new ApplicationException("Unknown .sln version: " + format); + } + } + finally + { + if(solutionStreamReader != null) + { + solutionStreamReader.Close(); + } + } + + return version; + } + + public static string GetVSProgID(string version) + { + string progid = null; + switch(version) + { + case "VC70": + progid = "VisualStudio.DTE.7"; + break; + + case "VC71": + progid = "VisualStudio.DTE.7.1"; + break; + + case "VC80": + progid = "VisualStudio.DTE.8.0"; + break; + + case "VC90": + progid = "VisualStudio.DTE.9.0"; + break; + default: + throw new ApplicationException("Can't handle VS version: " + version); + } + + return progid; + } + + public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir) + { + bool made_change = false; + Console.WriteLine("Looking for project {0}...", project_name); + try + { + object prjs = ViaCOM.GetProperty(sol, "Projects"); + object count = ViaCOM.GetProperty(prjs, "Count"); + for(int i = 1; i <= (int)count; ++i) + { + object[] prjItemArgs = { (object)i }; + object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs); + string name = (string)ViaCOM.GetProperty(prj, "Name"); + if (0 == string.Compare(name, project_name, ignore_case)) + { + Console.WriteLine("Found project: {0}", project_name); + Console.WriteLine("Setting working directory"); + + string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName"); + Console.WriteLine(full_project_name); + + // *NOTE:Mani Thanks to incompatibilities between different versions of the + // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to + // the VCProjectEngine types from a different version than the one built + // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built + // in VS 8.0. To avoid this problem, we can use the com object interfaces directly, + // without the type casting. Its tedious code, but it seems to work. + + // oCfgs should be assigned to a 'Project.Configurations' collection. + object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations"); + + // oCount will be assigned to the number of configs present in oCfgs. + object oCount = ViaCOM.GetProperty(oCfgs, "Count"); + + for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex) + { + object[] itemArgs = {(object)cfgIndex}; + object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs); + object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings"); + ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir); + } + + break; + } + } + made_change = true; + } + catch( Exception e ) + { + Console.WriteLine(e.Message); + Console.WriteLine("Failed to set working dir for project, {0}.", project_name); + } + + return made_change; + } + + public static bool SetStartupProject(string startup_project) + { + bool result = false; + try + { + // You need the 'unique name of the project to set StartupProjects. + // find the project by generic name. + Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project); + object prjs = ViaCOM.GetProperty(solution, "Projects"); + object count = ViaCOM.GetProperty(prjs, "Count"); + for (int i = 1; i <= (int)count; ++i) + { + object[] itemArgs = { (object)i }; + object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs); + object prjName = ViaCOM.GetProperty(prj, "Name"); + if (0 == string.Compare((string)prjName, startup_project, ignore_case)) + { + object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); + ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName")); + Console.WriteLine(" Success!"); + result = true; + break; + } + } + + if (result == false) + { + Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project); + } + } + catch (Exception e) + { + Console.WriteLine(" Failed to set the startup project!"); + Console.WriteLine(e.Message); + } + return result; + } + + public static bool SetActiveConfig(string config) + { + bool result = false; + try + { + Console.WriteLine("Trying to set active config to \"{0}\"", config); + object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); + object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations"); + object[] itemArgs = { (object)config }; + object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs); + ViaCOM.CallMethod(solCfg, "Activate", null); + Console.WriteLine(" Success!"); + result = true; + } + catch (Exception e) + { + Console.WriteLine(" Failed to set \"{0}\" as the active config.", config); + Console.WriteLine(e.Message); + } + return result; + } + } +}