From 23811df3cf466928a19e93e2587038159ec03fdf Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Sun, 19 Feb 2012 06:43:04 -0500 Subject: [PATCH 01/35] Adding to Ignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bfe820c87..c56bf2a54 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ *.rej *.bak *~ +*.DS_Store /LICENSES/ /edited-files.txt qtcreator-build/ From 925c42294f451b1118f6d8e5183364329d360ce3 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Sun, 19 Feb 2012 11:30:27 -0500 Subject: [PATCH 02/35] OS X Builds now. Fixed building on OS X. Fixed line endings. Need to find better way to do fmodwrapper thing. --- indra/newview/fmodwrapper.cpp | 22 +- indra/newview/llstartup.cpp | 2 +- indra/newview/sgversion.cpp | 3 + indra/newview/sgversion.h | 3 + indra/newview/viewer_manifest.py | 1758 +++++++++++++++--------------- 5 files changed, 899 insertions(+), 889 deletions(-) diff --git a/indra/newview/fmodwrapper.cpp b/indra/newview/fmodwrapper.cpp index d14c9134f..b544785b7 100644 --- a/indra/newview/fmodwrapper.cpp +++ b/indra/newview/fmodwrapper.cpp @@ -30,26 +30,30 @@ * $/LicenseInfo$ */ +//Hack to build Darwin. +//Need to find a better way to do this later. +#define LL_FMOD + extern "C" { -#if LL_FMODEX +#ifdef LL_FMODEX void FSOUND_Sound_Init(void); #endif -#if LL_FMOD + +#ifdef LL_FMOD void FSOUND_Init(void); #endif } void* fmodwrapper(void) -{ +{ // When building the fmodwrapper library, the linker doesn't seem to want to bring in libfmod.a unless I explicitly // reference at least one symbol in the library. This seemed like the simplest way. - void *ret = NULL; -#if LL_FMODEX - ret = (void*)&FSOUND_Sound_Init; +#ifdef LL_FMODEX + return (void*)&FSOUND_Sound_Init; #endif -#if LL_FMOD - ret = (void*)&FSOUND_Init; + +#ifdef LL_FMOD + return (void*)&FSOUND_Init; #endif - return ret; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4feeee42f..011c10cac 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3492,7 +3492,7 @@ bool update_dialog_callback(const LLSD& notification, const LLSD& response) LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -bundleid \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += LL_VERSION_BUNDLE_ID; + LLAppViewer::sUpdaterInfo->mUpdateExePath += gVersionBundleID; LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; diff --git a/indra/newview/sgversion.cpp b/indra/newview/sgversion.cpp index 07f4c251d..615064f27 100644 --- a/indra/newview/sgversion.cpp +++ b/indra/newview/sgversion.cpp @@ -28,3 +28,6 @@ const S32 gVersionBuild = LL_VERSION_BUILD; const char* gVersionChannel = LL_CHANNEL; +#if LL_DARWIN +const char* gVersionBundleID = LL_VERSION_BUNDLE_ID; +#endif \ No newline at end of file diff --git a/indra/newview/sgversion.h b/indra/newview/sgversion.h index 42231fc07..afdc8b51a 100644 --- a/indra/newview/sgversion.h +++ b/indra/newview/sgversion.h @@ -25,5 +25,8 @@ extern const S32 gVersionBuild; extern const char* gVersionChannel; +#if LL_DARWIN +extern const char* gVersionBundleID; +#endif #endif diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 2b11cd32b..b492ddaef 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1,879 +1,879 @@ -#!/usr/bin/python -# @file viewer_manifest.py -# @author Ryan Williams -# @brief Description of all installer viewer files, and methods for packaging -# them into installers for all supported platforms. -# -# $LicenseInfo:firstyear=2006&license=viewergpl$ -# -# Copyright (c) 2006-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$ -import sys -import os.path -import re -import tarfile -viewer_dir = os.path.dirname(__file__) -# add llmanifest library to our path so we don't have to muck with PYTHONPATH -sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) -from llmanifest import LLManifest, main, proper_windows_path, path_ancestors - -class ViewerManifest(LLManifest): - def construct(self): - super(ViewerManifest, self).construct() - self.exclude("*.svn*") - self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg") - self.path(src="../../etc/message.xml", dst="app_settings/message.xml") - - if self.prefix(src="app_settings"): - self.exclude("logcontrol.xml") - self.exclude("logcontrol-dev.xml") - self.path("*.pem") - self.path("*.ini") - self.path("*.xml") - self.path("*.db2") - - # include the entire shaders directory recursively - self.path("shaders") - # ... and the entire windlight directory - self.path("windlight") - # ... and the hunspell dictionaries - self.path("dictionaries") - self.end_prefix("app_settings") - - if self.prefix(src="character"): - self.path("*.llm") - self.path("*.xml") - self.path("*.tga") - self.end_prefix("character") - - # Include our fonts - if self.prefix(src="fonts"): - self.path("*.ttf") - self.path("*.txt") - self.end_prefix("fonts") - - # skins - if self.prefix(src="skins"): - self.path("paths.xml") - # include the entire textures directory recursively - if self.prefix(src="default/textures"): - self.path("*.tga") - self.path("*.j2c") - self.path("*.jpg") - self.path("*.png") - self.path("textures.xml") - self.end_prefix("default/textures") - self.path("default/xui/*/*.xml") - self.path("Default.xml") - self.path("default/*.xml") - if self.prefix(src="dark/textures"): - self.path("*.tga") - self.path("*.j2c") - self.path("*.jpg") - self.path("*.png") - self.path("textures.xml") - self.end_prefix("dark/textures") - self.path("dark.xml") - self.path("dark/*.xml") - - # Local HTML files (e.g. loading screen) - if self.prefix(src="*/html"): - self.path("*.png") - self.path("*/*/*.html") - self.path("*/*/*.gif") - self.end_prefix("*/html") - self.end_prefix("skins") - - # Files in the newview/ directory - self.path("gpu_table.txt") - - def login_channel(self): - """Channel reported for login and upgrade purposes ONLY; - used for A/B testing""" - # NOTE: Do not return the normal channel if login_channel - # is not specified, as some code may branch depending on - # whether or not this is present - return self.args.get('login_channel') - - def buildtype(self): - return self.args['buildtype'] - def standalone(self): - return self.args['standalone'] == "ON" - def grid(self): - return self.args['grid'] - def channel(self): - return self.args['channel'] - def channel_unique(self): - return self.channel().replace("Second Life", "").strip() - def channel_oneword(self): - return "".join(self.channel_unique().split()) - def channel_lowerword(self): - return self.channel_oneword().lower() - def viewer_branding_id(self): - return self.args['branding_id'] - def installer_prefix(self): - mapping={"secondlife":'SecondLife_', - "snowglobe":'Snowglobe_', - "singularity":'Singularity_'} - return mapping[self.viewer_branding_id()] - - def flags_list(self): - """ Convenience function that returns the command-line flags - for the grid""" - - # Set command line flags relating to the target grid - grid_flags = '' - if not self.default_grid(): - grid_flags = "--grid %(grid)s "\ - "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ - {'grid':self.grid()} - - # set command line flags for channel - channel_flags = '' - if self.login_channel() and self.login_channel() != self.channel(): - # Report a special channel during login, but use default - channel_flags = '--channel "%s"' % (self.login_channel()) - else: - channel_flags = '--channel "%s"' % self.channel() - - # Deal with settings - if self.default_channel() and self.default_grid(): - setting_flags = '' - elif self.default_grid(): - setting_flags = '--settings settings_%s.xml'\ - % self.channel_lowerword() - else: - setting_flags = '--settings settings_%s_%s.xml'\ - % (self.grid(), self.channel_lowerword()) - - return " ".join((channel_flags, grid_flags, setting_flags)).strip() - -class WindowsManifest(ViewerManifest): - def final_exe(self): - return self.channel_oneword() + 'Viewer.exe' - - - def construct(self): - super(WindowsManifest, self).construct() - # the final exe is complicated because we're not sure where it's coming from, - # nor do we have a fixed name for the executable - self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe()) - - # Plugin host application - self.path(os.path.join(os.pardir, - 'llplugin', 'slplugin', self.args['configuration'], "SLPlugin.exe"), - "SLPlugin.exe") - - # need to get the kdu dll from any of the build directories as well - #~ try: - #~ self.path(self.find_existing_file('../llkdu/%s/llkdu.dll' % self.args['configuration'], - #~ '../../libraries/i686-win32/lib/release/llkdu.dll'), - #~ dst='llkdu.dll') - #~ pass - #~ except: - #~ print "Skipping llkdu.dll" - #~ pass - self.path(src="licenses-win32.txt", dst="licenses.txt") - - self.path("featuretable.txt") - - # For spellchecking - if self.prefix(src=self.args['configuration'], dst=""): - self.path("libhunspell.dll") - self.end_prefix() - - # For use in crash reporting (generates minidumps) - self.path("dbghelp.dll") - - # For using FMOD for sound... DJS - #~if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - #~try: - #~self.path("fmod.dll") - #~pass - #~except: - #~print "Skipping fmod.dll - not found" - #~ pass - #~self.end_prefix() - - # For textures - #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - # self.path("openjpeg.dll") - # self.end_prefix() - - # Plugins - FilePicker - if self.prefix(src='../plugins/filepicker/%s' % self.args['configuration'], dst="llplugin"): - self.path("basic_plugin_filepicker.dll") - self.end_prefix() - - # Media plugins - QuickTime - if self.prefix(src='../plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_quicktime.dll") - self.end_prefix() - - # Media plugins - WebKit/Qt - if self.prefix(src='../plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_webkit.dll") - self.end_prefix() - - # For WebKit/Qt plugin runtimes - if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): - self.path("libeay32.dll") - self.path("qtcore4.dll") - self.path("qtgui4.dll") - self.path("qtnetwork4.dll") - self.path("qtopengl4.dll") - self.path("qtwebkit4.dll") - self.path("qtxmlpatterns4.dll") - self.path("ssleay32.dll") - self.end_prefix() - - # For WebKit/Qt plugin runtimes (image format plugins) - if self.prefix(src="../../libraries/i686-win32/lib/release/imageformats", dst="llplugin/imageformats"): - self.path("qgif4.dll") - self.path("qico4.dll") - self.path("qjpeg4.dll") - self.path("qmng4.dll") - self.path("qsvg4.dll") - self.path("qtiff4.dll") - self.end_prefix() - - if self.prefix(src="../../libraries/i686-win32/lib/release/codecs", dst="llplugin/codecs"): - self.path("qcncodecs4.dll") - self.path("qjpcodecs4.dll") - self.path("qkrcodecs4.dll") - self.path("qtwcodecs4.dll") - self.end_prefix() - - # Get llcommon and deps. If missing assume static linkage and continue. - if self.prefix(src=self.args['configuration'], dst=""): - try: - self.path('llcommon.dll') - except RuntimeError, err: - print err.message - print "Skipping llcommon.dll (assuming llcommon was linked statically)" - self.end_prefix() - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - try: - self.path('libapr-1.dll') - self.path('libaprutil-1.dll') - self.path('libapriconv-1.dll') - except RuntimeError, err: - pass - self.end_prefix() - - # For google-perftools tcmalloc allocator. - self.path("../../libraries/i686-win32/lib/release/libtcmalloc_minimal.dll", dst="libtcmalloc_minimal.dll") - - try: - if self.prefix("../../libraries/i686-win32/lib/release/msvcrt", dst=""): - self.path("*.dll") - self.path("*.manifest") - self.end_prefix() - except: - pass - - - # These need to be installed as a SxS assembly, currently a 'private' assembly. - # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx - #~ if self.prefix(src=self.args['configuration'], dst=""): - #~ if self.args['configuration'] == 'Debug': - #~ self.path("msvcr80d.dll") - #~ self.path("msvcp80d.dll") - #~ self.path("Microsoft.VC80.DebugCRT.manifest") - #~ else: - #~ self.path("msvcr80.dll") - #~ self.path("msvcp80.dll") - #~ self.path("Microsoft.VC80.CRT.manifest") - #~ self.end_prefix() - - # The config file name needs to match the exe's name. - #~ self.path(src="%s/secondlife-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config") - - # Vivox runtimes - if self.prefix(src="vivox-runtime/i686-win32", dst=""): - self.path("SLVoice.exe") - self.path("alut.dll") - self.path("vivoxsdk.dll") - self.path("ortp.dll") - self.path("wrap_oal.dll") - self.end_prefix() - - if self.args['extra_libraries'] != None: - print self.args['extra_libraries'] - path_list = self.args['extra_libraries'].split('|') - for path in path_list: - path_pair = path.rsplit('/', 1) - if self.prefix(src=path_pair[0], dst=""): - self.path(path_pair[1]) - self.end_prefix() - - # pull in the crash logger and updater from other projects - self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], dst="win_crash_logger.exe") - self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'], dst="updater.exe") - - - def nsi_file_commands(self, install=True): - def wpath(path): - if path.endswith('/') or path.endswith(os.path.sep): - path = path[:-1] - path = path.replace('/', '\\') - return path - - result = "" - dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])] - # sort deepest hierarchy first - dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) - dest_files.reverse() - out_path = None - for pkg_file in dest_files: - rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,'')) - installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file))) - pkg_file = wpath(os.path.normpath(pkg_file)) - if installed_dir != out_path: - if install: - out_path = installed_dir - result += 'SetOutPath ' + out_path + '\n' - if install: - result += 'File ' + pkg_file + '\n' - else: - result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n' - # at the end of a delete, just rmdir all the directories - if not install: - deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list] - # find all ancestors so that we don't skip any dirs that happened to have no non-dir children - deleted_dirs = [] - for d in deleted_file_dirs: - deleted_dirs.extend(path_ancestors(d)) - # sort deepest hierarchy first - deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) - deleted_dirs.reverse() - prev = None - for d in deleted_dirs: - if d != prev: # skip duplicates - result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n' - prev = d - - return result - - def package_finish(self): - # a standard map of strings for replacing in the templates - substitution_strings = { - 'version' : '.'.join(self.args['version']), - 'version_short' : '.'.join(self.args['version'][:-1]), - 'version_dashes' : '-'.join(self.args['version']), - 'final_exe' : self.final_exe(), - 'grid':self.args['grid'], - 'grid_caps':self.args['grid'].upper(), - # escape quotes becase NSIS doesn't handle them well - 'flags':self.flags_list().replace('"', '$\\"'), - 'channel':self.channel(), - 'channel_oneword':self.channel_oneword(), - 'channel_unique':self.channel_unique(), - } - - version_vars = """ - !define INSTEXE "%(final_exe)s" - !define VERSION "%(version_short)s" - !define VERSION_LONG "%(version)s" - !define VERSION_DASHES "%(version_dashes)s" - """ % substitution_strings - installer_file = "%(channel_oneword)s_%(version_dashes)s_Setup.exe" - grid_vars_template = """ - OutFile "%(installer_file)s" - !define VIEWERNAME "%(channel)s" - !define INSTFLAGS "%(flags)s" - !define INSTNAME "%(channel_oneword)s" - !define SHORTCUT "%(channel)s Viewer" - !define URLNAME "secondlife" - !define INSTALL_ICON "install_icon_singularity.ico" - !define UNINSTALL_ICON "install_icon_singularity.ico" - Caption "${VIEWERNAME} ${VERSION_LONG}" - """ - if 'installer_name' in self.args: - installer_file = self.args['installer_name'] - else: - installer_file = installer_file % substitution_strings - substitution_strings['installer_file'] = installer_file - - tempfile = "secondlife_setup_tmp.nsi" - # the following replaces strings in the nsi template - # it also does python-style % substitution - self.replace_in("installers/windows/installer_template.nsi", tempfile, { - "%%VERSION%%":version_vars, - "%%SOURCE%%":self.get_src_prefix(), - "%%GRID_VARS%%":grid_vars_template % substitution_strings, - "%%INSTALL_FILES%%":self.nsi_file_commands(True), - "%%DELETE_FILES%%":self.nsi_file_commands(False)}) - - # We use the Unicode version of NSIS, available from - # http://www.scratchpaper.com/ - try: - import _winreg as reg - NSIS_path = reg.QueryValue(reg.HKEY_LOCAL_MACHINE, r"SOFTWARE\NSIS\Unicode") + '\\makensis.exe' - self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) - except: - try: - NSIS_path = os.environ['ProgramFiles'] + '\\NSIS\\Unicode\\makensis.exe' - self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) - except: - NSIS_path = os.environ['ProgramFiles(X86)'] + '\\NSIS\\Unicode\\makensis.exe' - self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) - # self.remove(self.dst_path_of(tempfile)) - # If we're on a build machine, sign the code using our Authenticode certificate. JC - sign_py = os.path.expandvars("{SIGN_PY}") - if sign_py == "" or sign_py == "{SIGN_PY}": - sign_py = 'C:\\buildscripts\\code-signing\\sign.py' - if os.path.exists(sign_py): - self.run_command('python ' + sign_py + ' ' + self.dst_path_of(installer_file)) - else: - print "Skipping code signing,", sign_py, "does not exist" - self.created_path(self.dst_path_of(installer_file)) - self.package_file = installer_file - - -class DarwinManifest(ViewerManifest): - def construct(self): - # copy over the build result (this is a no-op if run within the xcode script) - self.path(self.args['configuration'] + "/" + self.app_name() + ".app", dst="") - - if self.prefix(src="", dst="Contents"): # everything goes in Contents - self.path(self.info_plist_name(), dst="Info.plist") - - # copy additional libs in /Contents/MacOS/ - self.path("../../libraries/universal-darwin/lib_release/libhunspell-1.2.dylib", dst="MacOS/libhunspell-1.2.dylib") - self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib") - #self.path("../../libraries/universal-darwin/lib_release/libvorbisenc.2.dylib", dst="MacOS/libvorbisenc.2.dylib") - #self.path("../../libraries/universal-darwin/lib_release/libvorbisfile.3.dylib", dst="MacOS/libvorbisfile.3.dylib") - #self.path("../../libraries/universal-darwin/lib_release/libvorbis.0.dylib", dst="MacOS/libvorbis.0.dylib") - #self.path("../../libraries/universal-darwin/lib_release/libogg.0.dylib", dst="MacOS/libogg.0.dylib") - - # most everything goes in the Resources directory - if self.prefix(src="", dst="Resources"): - super(DarwinManifest, self).construct() - - if self.prefix("cursors_mac"): - self.path("*.tif") - self.end_prefix("cursors_mac") - - self.path("licenses-mac.txt", dst="licenses.txt") - self.path("featuretable_mac.txt") - self.path("SecondLife.nib") - - # SG:TODO - self.path("../newview/res/singularity.icns", dst="singularity.icns") - - # Translations - self.path("English.lproj") - self.path("German.lproj") - self.path("Japanese.lproj") - self.path("Korean.lproj") - self.path("da.lproj") - self.path("es.lproj") - self.path("fr.lproj") - self.path("hu.lproj") - self.path("it.lproj") - self.path("nl.lproj") - self.path("pl.lproj") - self.path("pt.lproj") - self.path("ru.lproj") - self.path("tr.lproj") - self.path("uk.lproj") - self.path("zh-Hans.lproj") - - # SLVoice and vivox lols - self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib") - self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib") - self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib") - self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") - self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") - - self.path("../llcommon/" + self.args['configuration'] + "/libllcommon.dylib", "libllcommon.dylib") - - libfile = "lib%s.dylib" - libdir = "../../libraries/universal-darwin/lib_release" - - for libfile in ("libapr-1.0.3.7.dylib", - "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): - self.path(os.path.join(libdir, libfile), libfile) - - # For using FMOD for sound...but, fmod is proprietary so some might not use it... - try: - self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib") - pass - except: - print "Skipping libfmodwrapper.dylib - not found" - pass - - # our apps - try: - self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") - self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") - except: - pass - - # plugin launcher - self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app") - - # dependencies on shared libs - mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources") - slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources") - for libfile in ("libllcommon.dylib", - "libapr-1.0.3.7.dylib", - "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): - target_lib = os.path.join('../../..', libfile) - self.run_command("ln -sf %(target)r %(link)r" % - {'target': target_lib, - 'link' : os.path.join(slplugin_res_path, libfile)} - ) - #self.run_command("ln -sf %(target)r %(link)r" % - # {'target': target_lib, - # 'link' : os.path.join(mac_crash_logger_res_path, libfile)} - # ) - - # plugins - if self.prefix(src="", dst="llplugin"): - self.path("../plugins/filepicker/" + self.args['configuration'] + "/basic_plugin_filepicker.dylib", "basic_plugin_filepicker.dylib") - self.path("../plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") - self.path("../plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") - self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") - - self.end_prefix("llplugin") - - # command line arguments for connecting to the proper grid - self.put_in_file(self.flags_list(), 'arguments.txt') - - self.end_prefix("Resources") - - self.end_prefix("Contents") - - # NOTE: the -S argument to strip causes it to keep enough info for - # annotated backtraces (i.e. function names in the crash log). 'strip' with no - # arguments yields a slightly smaller binary but makes crash logs mostly useless. - # This may be desirable for the final release. Or not. - if self.buildtype().lower()=='release': - if ("package" in self.args['actions'] or - "unpacked" in self.args['actions']): - self.run_command('strip -S "%(viewer_binary)s"' % - { 'viewer_binary' : self.dst_path_of('Contents/MacOS/'+self.app_name())}) - - def app_name(self): - return "Singularity" - - def info_plist_name(self): - return "Info-Singularity.plist" - - def package_finish(self): - channel_standin = self.app_name() - if not self.default_channel_for_brand(): - channel_standin = self.channel() - - imagename=self.installer_prefix() + '_'.join(self.args['version']) - - # See Ambroff's Hack comment further down if you want to create new bundles and dmg - volname=self.app_name() + " Installer" # DO NOT CHANGE without checking Ambroff's Hack comment further down - - if self.default_channel_for_brand(): - if not self.default_grid(): - # beta case - imagename = imagename + '_' + self.args['grid'].upper() - else: - # first look, etc - imagename = imagename + '_' + self.channel_oneword().upper() - - sparsename = imagename + ".sparseimage" - finalname = imagename + ".dmg" - # make sure we don't have stale files laying about - self.remove(sparsename, finalname) - - self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % { - 'sparse':sparsename, - 'vol':volname}) - - # mount the image and get the name of the mount point and device node - hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"') - devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip() - volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() - - # Copy everything in to the mounted .dmg - - if self.default_channel_for_brand() and not self.default_grid(): - app_name = self.app_name() + " " + self.args['grid'] - else: - app_name = channel_standin.strip() - - # Hack: - # Because there is no easy way to coerce the Finder into positioning - # the app bundle in the same place with different app names, we are - # adding multiple .DS_Store files to svn. There is one for release, - # one for release candidate and one for first look. Any other channels - # will use the release .DS_Store, and will look broken. - # - Ambroff 2008-08-20 - # Added a .DS_Store for snowglobe - Merov 2009-06-17 - - # We have a single branded installer for all snowglobe channels so snowglobe logic is a bit different - if (self.app_name()=="Snowglobe"): - dmg_template = os.path.join ('installers', 'darwin', 'snowglobe-dmg') - else: - dmg_template = os.path.join( - 'installers', - 'darwin', - '%s-dmg' % "".join(self.channel_unique().split()).lower()) - - if not os.path.exists (self.src_path_of(dmg_template)): - dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') - - for s,d in {self.get_dst_prefix():app_name + ".app", - os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns", - os.path.join(dmg_template, "background.jpg"): "background.jpg", - os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): - print "Copying to dmg", s, d - self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) - - # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit) - self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"') - self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"') - self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"') - - # Create the alias file (which is a resource file) from the .r - self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"') - - # Set the alias file's alias and custom icon bits - self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"') - - # Set the disk image root's custom icon bit - self.run_command('SetFile -a C "' + volpath + '"') - - # Unmount the image - self.run_command('hdiutil detach -force "' + devfile + '"') - - print "Converting temp disk image to final disk image" - self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname}) - # get rid of the temp file - self.package_file = finalname - self.remove(sparsename) - -class LinuxManifest(ViewerManifest): - def construct(self): - super(LinuxManifest, self).construct() - self.path("licenses-linux.txt","licenses.txt") - - self.path("res/"+self.icon_name(),self.icon_name()) - if self.prefix("linux_tools", dst=""): - self.path("client-readme.txt","README-linux.txt") - self.path("client-readme-voice.txt","README-linux-voice.txt") - self.path("client-readme-joystick.txt","README-linux-joystick.txt") - self.path("wrapper.sh",self.wrapper_name()) - self.path("handle_secondlifeprotocol.sh") - self.path("register_secondlifeprotocol.sh") - self.end_prefix("linux_tools") - - # Create an appropriate gridargs.dat for this package, denoting required grid. - self.put_in_file(self.flags_list(), 'gridargs.dat') - - if self.buildtype().lower()=='release': - self.path("secondlife-stripped","bin/"+self.binary_name()) - self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin") - else: - self.path("secondlife-bin","bin/"+self.binary_name()) - self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") - - self.path("linux_tools/launch_url.sh","launch_url.sh") - self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin") - if self.prefix("res-sdl"): - self.path("*") - # recurse - self.end_prefix("res-sdl") - - # plugins - if self.prefix(src="", dst="bin/llplugin"): - self.path("../plugins/filepicker/libbasic_plugin_filepicker.so", "libbasic_plugin_filepicker.so") - self.path("../plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") - self.path("../plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") - self.end_prefix("bin/llplugin") - - self.path("featuretable_linux.txt") - - def wrapper_name(self): - return 'singularity' - - def binary_name(self): - return 'singularity-do-not-run-directly' - - def icon_name(self): - return "singularity_icon.png" - - def package_finish(self): - if 'installer_name' in self.args: - installer_name = self.args['installer_name'] - else: - installer_name_components = [self.installer_prefix(), self.args.get('arch')] - installer_name_components.extend(self.args['version']) - installer_name = "_".join(installer_name_components) - if self.default_channel(): - if not self.default_grid(): - installer_name += '_' + self.args['grid'].upper() - else: - installer_name += '_' + self.channel_oneword().upper() - - if self.args['buildtype'].lower() in ['release', 'releasesse2']: - print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" - # makes some small assumptions about our packaged dir structure - self.run_command("find %(d)r/bin %(d)r/lib* -type f | xargs --no-run-if-empty strip --strip-unneeded" % {'d': self.get_dst_prefix()} ) - self.run_command("find %(d)r/bin %(d)r/lib* -type f -not -name \\*.so | xargs --no-run-if-empty strip -s" % {'d': self.get_dst_prefix()} ) - - # Fix access permissions - self.run_command(""" - find '%(dst)s' -type d -print0 | xargs -0 --no-run-if-empty chmod 755; - find '%(dst)s' -type f -perm 0700 -print0 | xargs -0 --no-run-if-empty chmod 0755; - find '%(dst)s' -type f -perm 0500 -print0 | xargs -0 --no-run-if-empty chmod 0555; - find '%(dst)s' -type f -perm 0600 -print0 | xargs -0 --no-run-if-empty chmod 0644; - find '%(dst)s' -type f -perm 0400 -print0 | xargs -0 --no-run-if-empty chmod 0444; - true""" % {'dst':self.get_dst_prefix() }) - self.package_file = installer_name + '.tar.bz2' - - # temporarily move directory tree so that it has the right - # name in the tarfile - self.run_command("mv '%(dst)s' '%(inst)s'" % { - 'dst': self.get_dst_prefix(), - 'inst': self.build_path_of(installer_name)}) - try: - # --numeric-owner hides the username of the builder for - # security etc. - # I'm leaving this disabled for speed - #self.run_command("tar -C '%(dir)s' --numeric-owner -cjf " - # "'%(inst_path)s.tar.bz2' %(inst_name)s" % { - # 'dir': self.get_build_prefix(), - # 'inst_name': installer_name, - # 'inst_path':self.build_path_of(installer_name)}) - print '' - finally: - self.run_command("mv '%(inst)s' '%(dst)s'" % { - 'dst': self.get_dst_prefix(), - 'inst': self.build_path_of(installer_name)}) - - -class Linux_i686Manifest(LinuxManifest): - def construct(self): - super(Linux_i686Manifest, self).construct() - - self.path("../llcommon/libllcommon.so", "lib/libllcommon.so") - - if (not self.standalone()) and self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): - - try: - self.path("libkdu_v42R.so", "libkdu.so") - pass - except: - print "Skipping libkdu_v42R.so - not found" - pass - - try: - self.path("libfmod-3.75.so") - pass - except: - print "Skipping libfmod-3.75.so - not found" - pass - - self.path("libapr-1.so.0") - self.path("libaprutil-1.so.0") - self.path("libdb-4.2.so") - self.path("libcrypto.so.0.9.7") - self.path("libexpat.so.1") - self.path("libhunspell-1.2.so.0.0.0", "libhunspell-1.2.so.0") - self.path("libssl.so.0.9.7") - #self.path("libuuid.so.1") - self.path("libSDL-1.2.so.0") - self.path("libELFIO.so") - #self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3") - self.path("libalut.so") - self.path("libopenal.so.1") - self.path("libtcmalloc_minimal.so.0") - self.path("libtcmalloc_minimal.so.0.2.2") - self.end_prefix("lib") - - - # Vivox runtimes - if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): - self.path("SLVoice") - self.end_prefix() - if self.prefix(src="vivox-runtime/i686-linux", dst="lib"): - self.path("libortp.so") - self.path("libvivoxsdk.so") - self.end_prefix("lib") - - -class Linux_x86_64Manifest(LinuxManifest): - def construct(self): - super(Linux_x86_64Manifest, self).construct() - - self.path("../llcommon/libllcommon.so", "lib64/libllcommon.so") - - if (not self.standalone()) and self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): - self.path("libapr-1.so.0") - self.path("libaprutil-1.so.0") - self.path("libdb-4.2.so") - self.path("libcrypto.so.0.9.8") - self.path("libexpat.so.1") - self.path("libhunspell-1.2.so.0.0.0", "libhunspell-1.2.so.0") - self.path("libssl.so.0.9.8") - self.path("libuuid.so", "libuuid.so.1") - self.path("libSDL-1.2.so.0") - self.path("libELFIO.so") - self.path("libjpeg.so.7") - self.path("libpng12.so.0") - self.path("libopenjpeg.so.2") - self.path("libxml2.so.2") - #self.path("libz.so.1") #not needed - - # OpenAL - self.path("libopenal.so.1") - self.path("libalut.so.0") - - self.end_prefix("lib64") - - # Vivox runtimes and libs - if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): - self.path("SLVoice") - self.end_prefix("bin") - - if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"): - #self.path("libalut.so") - self.path("libortp.so") - self.path("libvivoxsdk.so") - self.end_prefix("lib32") - - # 32bit libs needed for voice - if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): - self.path("libalut.so") - self.path("libidn.so.11") - self.path("libopenal.so.1") - # self.path("libortp.so") - self.path("libuuid.so.1") - self.end_prefix("lib32") - -if __name__ == "__main__": - main() +#!/usr/bin/python +# @file viewer_manifest.py +# @author Ryan Williams +# @brief Description of all installer viewer files, and methods for packaging +# them into installers for all supported platforms. +# +# $LicenseInfo:firstyear=2006&license=viewergpl$ +# +# Copyright (c) 2006-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$ +import sys +import os.path +import re +import tarfile +viewer_dir = os.path.dirname(__file__) +# add llmanifest library to our path so we don't have to muck with PYTHONPATH +sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) +from llmanifest import LLManifest, main, proper_windows_path, path_ancestors + +class ViewerManifest(LLManifest): + def construct(self): + super(ViewerManifest, self).construct() + self.exclude("*.svn*") + self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg") + self.path(src="../../etc/message.xml", dst="app_settings/message.xml") + + if self.prefix(src="app_settings"): + self.exclude("logcontrol.xml") + self.exclude("logcontrol-dev.xml") + self.path("*.pem") + self.path("*.ini") + self.path("*.xml") + self.path("*.db2") + + # include the entire shaders directory recursively + self.path("shaders") + # ... and the entire windlight directory + self.path("windlight") + # ... and the hunspell dictionaries + self.path("dictionaries") + self.end_prefix("app_settings") + + if self.prefix(src="character"): + self.path("*.llm") + self.path("*.xml") + self.path("*.tga") + self.end_prefix("character") + + # Include our fonts + if self.prefix(src="fonts"): + self.path("*.ttf") + self.path("*.txt") + self.end_prefix("fonts") + + # skins + if self.prefix(src="skins"): + self.path("paths.xml") + # include the entire textures directory recursively + if self.prefix(src="default/textures"): + self.path("*.tga") + self.path("*.j2c") + self.path("*.jpg") + self.path("*.png") + self.path("textures.xml") + self.end_prefix("default/textures") + self.path("default/xui/*/*.xml") + self.path("Default.xml") + self.path("default/*.xml") + if self.prefix(src="dark/textures"): + self.path("*.tga") + self.path("*.j2c") + self.path("*.jpg") + self.path("*.png") + self.path("textures.xml") + self.end_prefix("dark/textures") + self.path("dark.xml") + self.path("dark/*.xml") + + # Local HTML files (e.g. loading screen) + if self.prefix(src="*/html"): + self.path("*.png") + self.path("*/*/*.html") + self.path("*/*/*.gif") + self.end_prefix("*/html") + self.end_prefix("skins") + + # Files in the newview/ directory + self.path("gpu_table.txt") + + def login_channel(self): + """Channel reported for login and upgrade purposes ONLY; + used for A/B testing""" + # NOTE: Do not return the normal channel if login_channel + # is not specified, as some code may branch depending on + # whether or not this is present + return self.args.get('login_channel') + + def buildtype(self): + return self.args['buildtype'] + def standalone(self): + return self.args['standalone'] == "ON" + def grid(self): + return self.args['grid'] + def channel(self): + return self.args['channel'] + def channel_unique(self): + return self.channel().replace("Second Life", "").strip() + def channel_oneword(self): + return "".join(self.channel_unique().split()) + def channel_lowerword(self): + return self.channel_oneword().lower() + def viewer_branding_id(self): + return self.args['branding_id'] + def installer_prefix(self): + mapping={"secondlife":'SecondLife_', + "snowglobe":'Snowglobe_', + "singularity":'Singularity_'} + return mapping[self.viewer_branding_id()] + + def flags_list(self): + """ Convenience function that returns the command-line flags + for the grid""" + + # Set command line flags relating to the target grid + grid_flags = '' + if not self.default_grid(): + grid_flags = "--grid %(grid)s "\ + "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ + {'grid':self.grid()} + + # set command line flags for channel + channel_flags = '' + if self.login_channel() and self.login_channel() != self.channel(): + # Report a special channel during login, but use default + channel_flags = '--channel "%s"' % (self.login_channel()) + else: + channel_flags = '--channel "%s"' % self.channel() + + # Deal with settings + if self.default_channel() and self.default_grid(): + setting_flags = '' + elif self.default_grid(): + setting_flags = '--settings settings_%s.xml'\ + % self.channel_lowerword() + else: + setting_flags = '--settings settings_%s_%s.xml'\ + % (self.grid(), self.channel_lowerword()) + + return " ".join((channel_flags, grid_flags, setting_flags)).strip() + +class WindowsManifest(ViewerManifest): + def final_exe(self): + return self.channel_oneword() + 'Viewer.exe' + + + def construct(self): + super(WindowsManifest, self).construct() + # the final exe is complicated because we're not sure where it's coming from, + # nor do we have a fixed name for the executable + self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe()) + + # Plugin host application + self.path(os.path.join(os.pardir, + 'llplugin', 'slplugin', self.args['configuration'], "SLPlugin.exe"), + "SLPlugin.exe") + + # need to get the kdu dll from any of the build directories as well + #~ try: + #~ self.path(self.find_existing_file('../llkdu/%s/llkdu.dll' % self.args['configuration'], + #~ '../../libraries/i686-win32/lib/release/llkdu.dll'), + #~ dst='llkdu.dll') + #~ pass + #~ except: + #~ print "Skipping llkdu.dll" + #~ pass + self.path(src="licenses-win32.txt", dst="licenses.txt") + + self.path("featuretable.txt") + + # For spellchecking + if self.prefix(src=self.args['configuration'], dst=""): + self.path("libhunspell.dll") + self.end_prefix() + + # For use in crash reporting (generates minidumps) + self.path("dbghelp.dll") + + # For using FMOD for sound... DJS + #~if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + #~try: + #~self.path("fmod.dll") + #~pass + #~except: + #~print "Skipping fmod.dll - not found" + #~ pass + #~self.end_prefix() + + # For textures + #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + # self.path("openjpeg.dll") + # self.end_prefix() + + # Plugins - FilePicker + if self.prefix(src='../plugins/filepicker/%s' % self.args['configuration'], dst="llplugin"): + self.path("basic_plugin_filepicker.dll") + self.end_prefix() + + # Media plugins - QuickTime + if self.prefix(src='../plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_quicktime.dll") + self.end_prefix() + + # Media plugins - WebKit/Qt + if self.prefix(src='../plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_webkit.dll") + self.end_prefix() + + # For WebKit/Qt plugin runtimes + if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): + self.path("libeay32.dll") + self.path("qtcore4.dll") + self.path("qtgui4.dll") + self.path("qtnetwork4.dll") + self.path("qtopengl4.dll") + self.path("qtwebkit4.dll") + self.path("qtxmlpatterns4.dll") + self.path("ssleay32.dll") + self.end_prefix() + + # For WebKit/Qt plugin runtimes (image format plugins) + if self.prefix(src="../../libraries/i686-win32/lib/release/imageformats", dst="llplugin/imageformats"): + self.path("qgif4.dll") + self.path("qico4.dll") + self.path("qjpeg4.dll") + self.path("qmng4.dll") + self.path("qsvg4.dll") + self.path("qtiff4.dll") + self.end_prefix() + + if self.prefix(src="../../libraries/i686-win32/lib/release/codecs", dst="llplugin/codecs"): + self.path("qcncodecs4.dll") + self.path("qjpcodecs4.dll") + self.path("qkrcodecs4.dll") + self.path("qtwcodecs4.dll") + self.end_prefix() + + # Get llcommon and deps. If missing assume static linkage and continue. + if self.prefix(src=self.args['configuration'], dst=""): + try: + self.path('llcommon.dll') + except RuntimeError, err: + print err.message + print "Skipping llcommon.dll (assuming llcommon was linked statically)" + self.end_prefix() + if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + try: + self.path('libapr-1.dll') + self.path('libaprutil-1.dll') + self.path('libapriconv-1.dll') + except RuntimeError, err: + pass + self.end_prefix() + + # For google-perftools tcmalloc allocator. + self.path("../../libraries/i686-win32/lib/release/libtcmalloc_minimal.dll", dst="libtcmalloc_minimal.dll") + + try: + if self.prefix("../../libraries/i686-win32/lib/release/msvcrt", dst=""): + self.path("*.dll") + self.path("*.manifest") + self.end_prefix() + except: + pass + + + # These need to be installed as a SxS assembly, currently a 'private' assembly. + # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx + #~ if self.prefix(src=self.args['configuration'], dst=""): + #~ if self.args['configuration'] == 'Debug': + #~ self.path("msvcr80d.dll") + #~ self.path("msvcp80d.dll") + #~ self.path("Microsoft.VC80.DebugCRT.manifest") + #~ else: + #~ self.path("msvcr80.dll") + #~ self.path("msvcp80.dll") + #~ self.path("Microsoft.VC80.CRT.manifest") + #~ self.end_prefix() + + # The config file name needs to match the exe's name. + #~ self.path(src="%s/secondlife-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config") + + # Vivox runtimes + if self.prefix(src="vivox-runtime/i686-win32", dst=""): + self.path("SLVoice.exe") + self.path("alut.dll") + self.path("vivoxsdk.dll") + self.path("ortp.dll") + self.path("wrap_oal.dll") + self.end_prefix() + + if self.args['extra_libraries'] != None: + print self.args['extra_libraries'] + path_list = self.args['extra_libraries'].split('|') + for path in path_list: + path_pair = path.rsplit('/', 1) + if self.prefix(src=path_pair[0], dst=""): + self.path(path_pair[1]) + self.end_prefix() + + # pull in the crash logger and updater from other projects + self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], dst="win_crash_logger.exe") + self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'], dst="updater.exe") + + + def nsi_file_commands(self, install=True): + def wpath(path): + if path.endswith('/') or path.endswith(os.path.sep): + path = path[:-1] + path = path.replace('/', '\\') + return path + + result = "" + dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])] + # sort deepest hierarchy first + dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) + dest_files.reverse() + out_path = None + for pkg_file in dest_files: + rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,'')) + installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file))) + pkg_file = wpath(os.path.normpath(pkg_file)) + if installed_dir != out_path: + if install: + out_path = installed_dir + result += 'SetOutPath ' + out_path + '\n' + if install: + result += 'File ' + pkg_file + '\n' + else: + result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n' + # at the end of a delete, just rmdir all the directories + if not install: + deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list] + # find all ancestors so that we don't skip any dirs that happened to have no non-dir children + deleted_dirs = [] + for d in deleted_file_dirs: + deleted_dirs.extend(path_ancestors(d)) + # sort deepest hierarchy first + deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) + deleted_dirs.reverse() + prev = None + for d in deleted_dirs: + if d != prev: # skip duplicates + result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n' + prev = d + + return result + + def package_finish(self): + # a standard map of strings for replacing in the templates + substitution_strings = { + 'version' : '.'.join(self.args['version']), + 'version_short' : '.'.join(self.args['version'][:-1]), + 'version_dashes' : '-'.join(self.args['version']), + 'final_exe' : self.final_exe(), + 'grid':self.args['grid'], + 'grid_caps':self.args['grid'].upper(), + # escape quotes becase NSIS doesn't handle them well + 'flags':self.flags_list().replace('"', '$\\"'), + 'channel':self.channel(), + 'channel_oneword':self.channel_oneword(), + 'channel_unique':self.channel_unique(), + } + + version_vars = """ + !define INSTEXE "%(final_exe)s" + !define VERSION "%(version_short)s" + !define VERSION_LONG "%(version)s" + !define VERSION_DASHES "%(version_dashes)s" + """ % substitution_strings + installer_file = "%(channel_oneword)s_%(version_dashes)s_Setup.exe" + grid_vars_template = """ + OutFile "%(installer_file)s" + !define VIEWERNAME "%(channel)s" + !define INSTFLAGS "%(flags)s" + !define INSTNAME "%(channel_oneword)s" + !define SHORTCUT "%(channel)s Viewer" + !define URLNAME "secondlife" + !define INSTALL_ICON "install_icon_singularity.ico" + !define UNINSTALL_ICON "install_icon_singularity.ico" + Caption "${VIEWERNAME} ${VERSION_LONG}" + """ + if 'installer_name' in self.args: + installer_file = self.args['installer_name'] + else: + installer_file = installer_file % substitution_strings + substitution_strings['installer_file'] = installer_file + + tempfile = "secondlife_setup_tmp.nsi" + # the following replaces strings in the nsi template + # it also does python-style % substitution + self.replace_in("installers/windows/installer_template.nsi", tempfile, { + "%%VERSION%%":version_vars, + "%%SOURCE%%":self.get_src_prefix(), + "%%GRID_VARS%%":grid_vars_template % substitution_strings, + "%%INSTALL_FILES%%":self.nsi_file_commands(True), + "%%DELETE_FILES%%":self.nsi_file_commands(False)}) + + # We use the Unicode version of NSIS, available from + # http://www.scratchpaper.com/ + try: + import _winreg as reg + NSIS_path = reg.QueryValue(reg.HKEY_LOCAL_MACHINE, r"SOFTWARE\NSIS\Unicode") + '\\makensis.exe' + self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) + except: + try: + NSIS_path = os.environ['ProgramFiles'] + '\\NSIS\\Unicode\\makensis.exe' + self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) + except: + NSIS_path = os.environ['ProgramFiles(X86)'] + '\\NSIS\\Unicode\\makensis.exe' + self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) + # self.remove(self.dst_path_of(tempfile)) + # If we're on a build machine, sign the code using our Authenticode certificate. JC + sign_py = os.path.expandvars("{SIGN_PY}") + if sign_py == "" or sign_py == "{SIGN_PY}": + sign_py = 'C:\\buildscripts\\code-signing\\sign.py' + if os.path.exists(sign_py): + self.run_command('python ' + sign_py + ' ' + self.dst_path_of(installer_file)) + else: + print "Skipping code signing,", sign_py, "does not exist" + self.created_path(self.dst_path_of(installer_file)) + self.package_file = installer_file + + +class DarwinManifest(ViewerManifest): + def construct(self): + # copy over the build result (this is a no-op if run within the xcode script) + self.path(self.args['configuration'] + "/" + self.app_name() + ".app", dst="") + + if self.prefix(src="", dst="Contents"): # everything goes in Contents + self.path(self.info_plist_name(), dst="Info.plist") + + # copy additional libs in /Contents/MacOS/ + self.path("../../libraries/universal-darwin/lib_release/libhunspell-1.2.dylib", dst="MacOS/libhunspell-1.2.dylib") + self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libvorbisenc.2.dylib", dst="MacOS/libvorbisenc.2.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libvorbisfile.3.dylib", dst="MacOS/libvorbisfile.3.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libvorbis.0.dylib", dst="MacOS/libvorbis.0.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libogg.0.dylib", dst="MacOS/libogg.0.dylib") + + # most everything goes in the Resources directory + if self.prefix(src="", dst="Resources"): + super(DarwinManifest, self).construct() + + if self.prefix("cursors_mac"): + self.path("*.tif") + self.end_prefix("cursors_mac") + + self.path("licenses-mac.txt", dst="licenses.txt") + self.path("featuretable_mac.txt") + self.path("SecondLife.nib") + + # SG:TODO + self.path("../newview/res/singularity.icns", dst="singularity.icns") + + # Translations + self.path("English.lproj") + self.path("German.lproj") + self.path("Japanese.lproj") + self.path("Korean.lproj") + self.path("da.lproj") + self.path("es.lproj") + self.path("fr.lproj") + self.path("hu.lproj") + self.path("it.lproj") + self.path("nl.lproj") + self.path("pl.lproj") + self.path("pt.lproj") + self.path("ru.lproj") + self.path("tr.lproj") + self.path("uk.lproj") + self.path("zh-Hans.lproj") + + # SLVoice and vivox lols + self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib") + self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib") + self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib") + self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") + self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") + + self.path("../llcommon/" + self.args['configuration'] + "/libllcommon.dylib", "libllcommon.dylib") + + libfile = "lib%s.dylib" + libdir = "../../libraries/universal-darwin/lib_release" + + for libfile in ("libapr-1.0.3.7.dylib", + "libaprutil-1.0.3.8.dylib", + "libexpat.0.5.0.dylib"): + self.path(os.path.join(libdir, libfile), libfile) + + # For using FMOD for sound...but, fmod is proprietary so some might not use it... + try: + self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib") + pass + except: + print "Skipping libfmodwrapper.dylib - not found" + pass + + # our apps + try: + self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") + self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + except: + pass + + # plugin launcher + self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app") + + # dependencies on shared libs + mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources") + slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources") + for libfile in ("libllcommon.dylib", + "libapr-1.0.3.7.dylib", + "libaprutil-1.0.3.8.dylib", + "libexpat.0.5.0.dylib"): + target_lib = os.path.join('../../..', libfile) + self.run_command("ln -sf %(target)r %(link)r" % + {'target': target_lib, + 'link' : os.path.join(slplugin_res_path, libfile)} + ) + #self.run_command("ln -sf %(target)r %(link)r" % + # {'target': target_lib, + # 'link' : os.path.join(mac_crash_logger_res_path, libfile)} + # ) + + # plugins + if self.prefix(src="", dst="llplugin"): + self.path("../plugins/filepicker/" + self.args['configuration'] + "/basic_plugin_filepicker.dylib", "basic_plugin_filepicker.dylib") + self.path("../plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") + self.path("../plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") + self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") + + self.end_prefix("llplugin") + + # command line arguments for connecting to the proper grid + self.put_in_file(self.flags_list(), 'arguments.txt') + + self.end_prefix("Resources") + + self.end_prefix("Contents") + + # NOTE: the -S argument to strip causes it to keep enough info for + # annotated backtraces (i.e. function names in the crash log). 'strip' with no + # arguments yields a slightly smaller binary but makes crash logs mostly useless. + # This may be desirable for the final release. Or not. + if self.buildtype().lower()=='release': + if ("package" in self.args['actions'] or + "unpacked" in self.args['actions']): + self.run_command('strip -S "%(viewer_binary)s"' % + { 'viewer_binary' : self.dst_path_of('Contents/MacOS/'+self.app_name())}) + + def app_name(self): + return "Singularity" + + def info_plist_name(self): + return "Info-Singularity.plist" + + def package_finish(self): + channel_standin = self.app_name() + if not self.default_channel_for_brand(): + channel_standin = self.channel() + + imagename=self.installer_prefix() + '_'.join(self.args['version']) + + # See Ambroff's Hack comment further down if you want to create new bundles and dmg + volname=self.app_name() + " Installer" # DO NOT CHANGE without checking Ambroff's Hack comment further down + + if self.default_channel_for_brand(): + if not self.default_grid(): + # beta case + imagename = imagename + '_' + self.args['grid'].upper() + else: + # first look, etc + imagename = imagename + '_' + self.channel_oneword().upper() + + sparsename = imagename + ".sparseimage" + finalname = imagename + ".dmg" + # make sure we don't have stale files laying about + self.remove(sparsename, finalname) + + self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % { + 'sparse':sparsename, + 'vol':volname}) + + # mount the image and get the name of the mount point and device node + hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"') + devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip() + volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() + + # Copy everything in to the mounted .dmg + + if self.default_channel_for_brand() and not self.default_grid(): + app_name = self.app_name() + " " + self.args['grid'] + else: + app_name = channel_standin.strip() + + # Hack: + # Because there is no easy way to coerce the Finder into positioning + # the app bundle in the same place with different app names, we are + # adding multiple .DS_Store files to svn. There is one for release, + # one for release candidate and one for first look. Any other channels + # will use the release .DS_Store, and will look broken. + # - Ambroff 2008-08-20 + # Added a .DS_Store for snowglobe - Merov 2009-06-17 + + # We have a single branded installer for all snowglobe channels so snowglobe logic is a bit different + if (self.app_name()=="Snowglobe"): + dmg_template = os.path.join ('installers', 'darwin', 'snowglobe-dmg') + else: + dmg_template = os.path.join( + 'installers', + 'darwin', + '%s-dmg' % "".join(self.channel_unique().split()).lower()) + + if not os.path.exists (self.src_path_of(dmg_template)): + dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') + + for s,d in {self.get_dst_prefix():app_name + ".app", + os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns", + os.path.join(dmg_template, "background.jpg"): "background.jpg", + os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): + print "Copying to dmg", s, d + self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) + + # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit) + self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"') + self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"') + self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"') + + # Create the alias file (which is a resource file) from the .r + self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"') + + # Set the alias file's alias and custom icon bits + self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"') + + # Set the disk image root's custom icon bit + self.run_command('SetFile -a C "' + volpath + '"') + + # Unmount the image + self.run_command('hdiutil detach -force "' + devfile + '"') + + print "Converting temp disk image to final disk image" + self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname}) + # get rid of the temp file + self.package_file = finalname + self.remove(sparsename) + +class LinuxManifest(ViewerManifest): + def construct(self): + super(LinuxManifest, self).construct() + self.path("licenses-linux.txt","licenses.txt") + + self.path("res/"+self.icon_name(),self.icon_name()) + if self.prefix("linux_tools", dst=""): + self.path("client-readme.txt","README-linux.txt") + self.path("client-readme-voice.txt","README-linux-voice.txt") + self.path("client-readme-joystick.txt","README-linux-joystick.txt") + self.path("wrapper.sh",self.wrapper_name()) + self.path("handle_secondlifeprotocol.sh") + self.path("register_secondlifeprotocol.sh") + self.end_prefix("linux_tools") + + # Create an appropriate gridargs.dat for this package, denoting required grid. + self.put_in_file(self.flags_list(), 'gridargs.dat') + + if self.buildtype().lower()=='release': + self.path("secondlife-stripped","bin/"+self.binary_name()) + self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin") + else: + self.path("secondlife-bin","bin/"+self.binary_name()) + self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") + + self.path("linux_tools/launch_url.sh","launch_url.sh") + self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin") + if self.prefix("res-sdl"): + self.path("*") + # recurse + self.end_prefix("res-sdl") + + # plugins + if self.prefix(src="", dst="bin/llplugin"): + self.path("../plugins/filepicker/libbasic_plugin_filepicker.so", "libbasic_plugin_filepicker.so") + self.path("../plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") + self.path("../plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") + self.end_prefix("bin/llplugin") + + self.path("featuretable_linux.txt") + + def wrapper_name(self): + return 'singularity' + + def binary_name(self): + return 'singularity-do-not-run-directly' + + def icon_name(self): + return "singularity_icon.png" + + def package_finish(self): + if 'installer_name' in self.args: + installer_name = self.args['installer_name'] + else: + installer_name_components = [self.installer_prefix(), self.args.get('arch')] + installer_name_components.extend(self.args['version']) + installer_name = "_".join(installer_name_components) + if self.default_channel(): + if not self.default_grid(): + installer_name += '_' + self.args['grid'].upper() + else: + installer_name += '_' + self.channel_oneword().upper() + + if self.args['buildtype'].lower() in ['release', 'releasesse2']: + print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" + # makes some small assumptions about our packaged dir structure + self.run_command("find %(d)r/bin %(d)r/lib* -type f | xargs --no-run-if-empty strip --strip-unneeded" % {'d': self.get_dst_prefix()} ) + self.run_command("find %(d)r/bin %(d)r/lib* -type f -not -name \\*.so | xargs --no-run-if-empty strip -s" % {'d': self.get_dst_prefix()} ) + + # Fix access permissions + self.run_command(""" + find '%(dst)s' -type d -print0 | xargs -0 --no-run-if-empty chmod 755; + find '%(dst)s' -type f -perm 0700 -print0 | xargs -0 --no-run-if-empty chmod 0755; + find '%(dst)s' -type f -perm 0500 -print0 | xargs -0 --no-run-if-empty chmod 0555; + find '%(dst)s' -type f -perm 0600 -print0 | xargs -0 --no-run-if-empty chmod 0644; + find '%(dst)s' -type f -perm 0400 -print0 | xargs -0 --no-run-if-empty chmod 0444; + true""" % {'dst':self.get_dst_prefix() }) + self.package_file = installer_name + '.tar.bz2' + + # temporarily move directory tree so that it has the right + # name in the tarfile + self.run_command("mv '%(dst)s' '%(inst)s'" % { + 'dst': self.get_dst_prefix(), + 'inst': self.build_path_of(installer_name)}) + try: + # --numeric-owner hides the username of the builder for + # security etc. + # I'm leaving this disabled for speed + #self.run_command("tar -C '%(dir)s' --numeric-owner -cjf " + # "'%(inst_path)s.tar.bz2' %(inst_name)s" % { + # 'dir': self.get_build_prefix(), + # 'inst_name': installer_name, + # 'inst_path':self.build_path_of(installer_name)}) + print '' + finally: + self.run_command("mv '%(inst)s' '%(dst)s'" % { + 'dst': self.get_dst_prefix(), + 'inst': self.build_path_of(installer_name)}) + + +class Linux_i686Manifest(LinuxManifest): + def construct(self): + super(Linux_i686Manifest, self).construct() + + self.path("../llcommon/libllcommon.so", "lib/libllcommon.so") + + if (not self.standalone()) and self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): + + try: + self.path("libkdu_v42R.so", "libkdu.so") + pass + except: + print "Skipping libkdu_v42R.so - not found" + pass + + try: + self.path("libfmod-3.75.so") + pass + except: + print "Skipping libfmod-3.75.so - not found" + pass + + self.path("libapr-1.so.0") + self.path("libaprutil-1.so.0") + self.path("libdb-4.2.so") + self.path("libcrypto.so.0.9.7") + self.path("libexpat.so.1") + self.path("libhunspell-1.2.so.0.0.0", "libhunspell-1.2.so.0") + self.path("libssl.so.0.9.7") + #self.path("libuuid.so.1") + self.path("libSDL-1.2.so.0") + self.path("libELFIO.so") + #self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3") + self.path("libalut.so") + self.path("libopenal.so.1") + self.path("libtcmalloc_minimal.so.0") + self.path("libtcmalloc_minimal.so.0.2.2") + self.end_prefix("lib") + + + # Vivox runtimes + if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): + self.path("SLVoice") + self.end_prefix() + if self.prefix(src="vivox-runtime/i686-linux", dst="lib"): + self.path("libortp.so") + self.path("libvivoxsdk.so") + self.end_prefix("lib") + + +class Linux_x86_64Manifest(LinuxManifest): + def construct(self): + super(Linux_x86_64Manifest, self).construct() + + self.path("../llcommon/libllcommon.so", "lib64/libllcommon.so") + + if (not self.standalone()) and self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): + self.path("libapr-1.so.0") + self.path("libaprutil-1.so.0") + self.path("libdb-4.2.so") + self.path("libcrypto.so.0.9.8") + self.path("libexpat.so.1") + self.path("libhunspell-1.2.so.0.0.0", "libhunspell-1.2.so.0") + self.path("libssl.so.0.9.8") + self.path("libuuid.so", "libuuid.so.1") + self.path("libSDL-1.2.so.0") + self.path("libELFIO.so") + self.path("libjpeg.so.7") + self.path("libpng12.so.0") + self.path("libopenjpeg.so.2") + self.path("libxml2.so.2") + #self.path("libz.so.1") #not needed + + # OpenAL + self.path("libopenal.so.1") + self.path("libalut.so.0") + + self.end_prefix("lib64") + + # Vivox runtimes and libs + if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): + self.path("SLVoice") + self.end_prefix("bin") + + if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"): + #self.path("libalut.so") + self.path("libortp.so") + self.path("libvivoxsdk.so") + self.end_prefix("lib32") + + # 32bit libs needed for voice + if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): + self.path("libalut.so") + self.path("libidn.so.11") + self.path("libopenal.so.1") + # self.path("libortp.so") + self.path("libuuid.so.1") + self.end_prefix("lib32") + +if __name__ == "__main__": + main() From a4363de59e2130aafe161552ffa2fcf77a9a6390 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Sun, 19 Feb 2012 15:59:47 -0500 Subject: [PATCH 03/35] Updated APR and Zlib prebuilts. --- indra/cmake/APR.cmake | 8 +-- indra/newview/viewer_manifest.py | 8 +-- install.xml | 114 +++++++++++++++---------------- 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake index d1f089891..5c434f4bf 100644 --- a/indra/cmake/APR.cmake +++ b/indra/cmake/APR.cmake @@ -29,12 +29,12 @@ else (STANDALONE) ) elseif (DARWIN) set(APR_LIBRARIES - debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.0.3.7.dylib - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.3.7.dylib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.0.dylib + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.dylib ) set(APRUTIL_LIBRARIES - debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.0.3.8.dylib - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.3.8.dylib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.0.dylib + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.dylib ) set(APRICONV_LIBRARIES iconv) else (WINDOWS) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index b492ddaef..8f49f94a9 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -514,8 +514,8 @@ class DarwinManifest(ViewerManifest): libfile = "lib%s.dylib" libdir = "../../libraries/universal-darwin/lib_release" - for libfile in ("libapr-1.0.3.7.dylib", - "libaprutil-1.0.3.8.dylib", + for libfile in ("libapr-1.0.dylib", + "libaprutil-1.0.dylib", "libexpat.0.5.0.dylib"): self.path(os.path.join(libdir, libfile), libfile) @@ -541,8 +541,8 @@ class DarwinManifest(ViewerManifest): mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources") slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources") for libfile in ("libllcommon.dylib", - "libapr-1.0.3.7.dylib", - "libaprutil-1.0.3.8.dylib", + "libapr-1.0.dylib", + "libaprutil-1.0.dylib", "libexpat.0.5.0.dylib"): target_lib = os.path.join('../../..', libfile) self.run_command("ln -sf %(target)r %(link)r" % diff --git a/install.xml b/install.xml index d7ce8c54d..23be3cc8d 100644 --- a/install.xml +++ b/install.xml @@ -29,7 +29,7 @@ - freeglut + freeglut copyright Copyright (c) 1999-2000 Pawel W. Olszta. @@ -90,9 +90,9 @@ darwin md5sum - 115d8ac44a91efdb173e9b3e478c46b6 + 2486db13c5ed9340855da3c1c48772af url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.3.7-darwin-20090805.tar.bz2 + https://github.com/downloads/LightDrake/SingularityViewer/apr_suite-1.4.2-darwin-20110217.tar.bz2 linux @@ -172,7 +172,7 @@ md5sum a2cde4f24bdcc260b661e139846b8acd url - http://imprudenceviewer.org/download/libs/imprudence-artwork-20101026.tar.bz2 + http://imprudenceviewer.org/download/libs/imprudence-artwork-20101026.tar.bz2 @@ -200,14 +200,14 @@ md5sum 2cad51575b429be4fdadb5d63da1c739 url - https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-darwin-20110604.tar.bz2 + https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-darwin-20110604.tar.bz2 linux md5sum a2d2fff5cc5555ffd9865daedfcd0dd5 url - https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-linux-20110604.tar.bz2 + https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-linux-20110604.tar.bz2 windows @@ -218,46 +218,46 @@ - curl - - copyright - Copyright (c) 1996 - 2008, Daniel Stenberg, <daniel@haxx.se>. - description - Client-side URL transfer library. Handles moving data across the net in many different protocols. Used to GET/POST/PUT/DELETE web resources. - license - curl - packages - - darwin - - md5sum - 525f6b18ea5af8fbd691c2ac1769056c - url - https://github.com/downloads/Shyotl/SingularityViewer/curl-7.20.1-darwin-20100606.tar.bz2 - - linux - - md5sum - 6244eec15fb26f9577785625fdb38f78 - url - https://github.com/downloads/Shyotl/SingularityViewer/curl-7.20.1-linux-20100527.tar.bz2 - - linux64 - - md5sum - 8a28849f4b9d99601dbc8db9d6a2f9ba - url - https://github.com/downloads/Shyotl/SingularityViewer/curl-7.16.4a-linux64-20090303.tar.bz2 - - windows - - md5sum - 60ed73408c4050ff9c96f26771fd6b46 - url - https://github.com/downloads/siana/SingularityViewer/curl-7.21.1-windows-20110504.tar.bz2 - - - + curl + + copyright + Copyright (c) 1996 - 2008, Daniel Stenberg, <daniel@haxx.se>. + description + Client-side URL transfer library. Handles moving data across the net in many different protocols. Used to GET/POST/PUT/DELETE web resources. + license + curl + packages + + darwin + + md5sum + 525f6b18ea5af8fbd691c2ac1769056c + url + https://github.com/downloads/Shyotl/SingularityViewer/curl-7.20.1-darwin-20100606.tar.bz2 + + linux + + md5sum + 6244eec15fb26f9577785625fdb38f78 + url + https://github.com/downloads/Shyotl/SingularityViewer/curl-7.20.1-linux-20100527.tar.bz2 + + linux64 + + md5sum + 8a28849f4b9d99601dbc8db9d6a2f9ba + url + https://github.com/downloads/Shyotl/SingularityViewer/curl-7.16.4a-linux64-20090303.tar.bz2 + + windows + + md5sum + 60ed73408c4050ff9c96f26771fd6b46 + url + https://github.com/downloads/siana/SingularityViewer/curl-7.21.1-windows-20110504.tar.bz2 + + + dbghelp copyright @@ -546,14 +546,14 @@ md5sum b190d8a0dce8dd8b514d2adb2c74b8d8 url - http://sldev.free.fr/libraries/google-perftools-1.8.3-linux-20110924.tar.bz2 + http://sldev.free.fr/libraries/google-perftools-1.8.3-linux-20110924.tar.bz2 windows md5sum 4f787437a5e063ccde6637dfb1ebc01d url - https://bitbucket.org/Ansariel/phoenix-prebuilts/downloads/google_perftools-1.8-windows-20111005.tar.bz2 + https://bitbucket.org/Ansariel/phoenix-prebuilts/downloads/google_perftools-1.8-windows-20111005.tar.bz2 @@ -995,7 +995,7 @@ anguage Infrstructure (CLI) international standard md5sum 38abfe002ba073b6824016db98269972 url - http://imprudenceviewer.org/download/libs/ndofdev-linux32-0.3.1-20100817.tar.bz2 + http://imprudenceviewer.org/download/libs/ndofdev-linux32-0.3.1-20100817.tar.bz2 linux64 @@ -1028,14 +1028,14 @@ anguage Infrstructure (CLI) international standard md5sum 5a154313bc30eacd8cfa1acd852ecd3e url - https://github.com/downloads/siana/SingularityViewer/ogg_vorbis-1.2.2-1.3.2-darwin-20110616.tar.bz2 + https://github.com/downloads/siana/SingularityViewer/ogg_vorbis-1.2.2-1.3.2-darwin-20110616.tar.bz2 linux md5sum 712b1d30790e9de83fea84ec3bc8fab0 url - https://github.com/downloads/siana/SingularityViewer/ogg_vorbis-1.2.2-1.3.2-linux-20110616.tar.bz2 + https://github.com/downloads/siana/SingularityViewer/ogg_vorbis-1.2.2-1.3.2-linux-20110616.tar.bz2 linux64 @@ -1227,10 +1227,10 @@ anguage Infrstructure (CLI) international standard 32bitcompatibilitylibs copyright - Copyrights: Libidn: Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Simon Josefsson. License GPL v3.0. - Freealut, libuuid, openal-soft: see copyright and license of the - according main packages. + Copyrights: Libidn: Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Simon Josefsson. License GPL v3.0. + Freealut, libuuid, openal-soft: see copyright and license of the + according main packages. description 32bit libraries needed for using voice @@ -1300,9 +1300,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - c844e1b05723ce078dbbd5aea9cdd3ad + 58ef62004b508b234039f6a313d852eb url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.1.4-darwin-20080818.tar.bz2 + https://github.com/downloads/LightDrake/SingularityViewer/zlib-1.2.5-darwin-20110211.tar.bz2 linux From 665569dfc7ae6e01ce7d5788b32414804d5ae989 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Sun, 19 Feb 2012 17:07:42 -0500 Subject: [PATCH 04/35] I forgot why I made these. --- indra/cmake/00-Common.cmake | 6 +++--- indra/cmake/Boost.cmake | 2 +- indra/cmake/DirectX.cmake | 4 ++-- indra/cmake/LLCommon.cmake | 1 + indra/cmake/LLPlugin.cmake | 4 ++-- indra/cmake/Python.cmake | 1 - 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 1f9854be8..18cc4c695 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -158,10 +158,10 @@ if (LINUX) add_definitions(-D_FORTIFY_SOURCE=2) endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") endif (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - - #Lets actualy get a numerical version of gxx's version + + #Lets actually get a numerical version of gxx's version STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION ${CXX_VERSION}) - + #gcc 4.3 and above don't like the LL boost if(${CXX_VERSION} GREATER 429) add_definitions(-Wno-parentheses) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 0cd10bd6c..1275d0547 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -10,7 +10,7 @@ if (STANDALONE) set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-mt) set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt) set(BOOST_REGEX_LIBRARY boost_regex-mt) - set(BOOST_SYSTEM_LIBRARY boost_system-mt) + set(BOOST_SYSTEM_LIBRARY boost_system-mt) else (STANDALONE) use_prebuilt_binary(boost) set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) diff --git a/indra/cmake/DirectX.cmake b/indra/cmake/DirectX.cmake index 5f538c80a..e45575595 100644 --- a/indra/cmake/DirectX.cmake +++ b/indra/cmake/DirectX.cmake @@ -3,7 +3,7 @@ if (VIEWER AND WINDOWS) find_path(DIRECTX_INCLUDE_DIR dxdiag.h "$ENV{DXSDK_DIR}/Include" - "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Include" + "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2008)/Include" @@ -25,7 +25,7 @@ if (VIEWER AND WINDOWS) find_path(DIRECTX_LIBRARY_DIR dxguid.lib "$ENV{DXSDK_DIR}/Lib/x86" - "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Lib/x86" + "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2010)/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2008)/Lib/x86" diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index 58316a489..b1bb1b6a9 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -14,6 +14,7 @@ endif (DARWIN) set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/cwdebug ${LIBS_OPEN_DIR}/llcommon + ${APRUTIL_INCLUDE_DIR} ${APR_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) diff --git a/indra/cmake/LLPlugin.cmake b/indra/cmake/LLPlugin.cmake index 7ee404b9b..399cb332d 100644 --- a/indra/cmake/LLPlugin.cmake +++ b/indra/cmake/LLPlugin.cmake @@ -8,7 +8,7 @@ set(LLPLUGIN_INCLUDE_DIRS if (LINUX) # In order to support using ld.gold on linux, we need to explicitely # specify all libraries that llplugin uses. - set(LLPLUGIN_LIBRARIES llplugin pthread) + set(LLPLUGIN_LIBRARIES llplugin pthread) else (LINUX) - set(LLPLUGIN_LIBRARIES llplugin) + set(LLPLUGIN_LIBRARIES llplugin) endif (LINUX) diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index a84ab64aa..748c8c2be 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -19,7 +19,6 @@ if (WINDOWS) [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] - ) elseif (EXISTS /etc/debian_version) # On Debian and Ubuntu, avoid Python 2.4 if possible. From c6d6eed7d33121ac2bbd466ac2e49cccd6f6d921 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Sun, 19 Feb 2012 19:43:53 -0500 Subject: [PATCH 05/35] This works for now. Need to do more testing. --- indra/newview/app_settings/settings.xml | 54 ++- indra/newview/lltranslate.cpp | 469 ++++++++++++++++++------ indra/newview/lltranslate.h | 372 ++++++++++++++----- indra/newview/llviewermessage.cpp | 26 +- 4 files changed, 696 insertions(+), 225 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2b521fed4..7553e8816 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,16 +1,15 @@ - Include - - settings_ascent.xml - settings_ascent_coa.xml - settings_sh.xml - settings_rlv.xml - - - SianaRenderDeferredInvisiprim - + Include + + settings_ascent.xml + settings_ascent_coa.xml + settings_sh.xml + settings_rlv.xml + + SianaRenderDeferredInvisiprim + Comment Support invisiprims in deferred mode Persist @@ -7525,12 +7524,45 @@ Comment Translate incoming chat messages Persist - 0 + 1 Type Boolean Value 0 + TranslationService + + Comment + Translation API to use. (google|bing) + Persist + 1 + Type + String + Value + bing + + GoogleTranslateAPIKey + + Comment + Google Translate API key + Persist + 1 + Type + String + Value + + + BingTranslateAPIKey + + Comment + Bing AppID to use with the Microsoft Translator API + Persist + 1 + Type + String + Value + + LastFeatureVersion Comment diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 5a537ae95..fcff3a0c7 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -2,136 +2,401 @@ * @file lltranslate.cpp * @brief Functions for translating text via Google Translate. * -* $LicenseInfo:firstyear=2009&license=viewergpl$ -* -* Copyright (c) 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$ -*/ + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ #include "llviewerprecompiledheaders.h" -#include "llbufferstream.h" #include "lltranslate.h" + +#include + +#include "llbufferstream.h" +#include "lltrans.h" #include "llui.h" -#include "sgversion.h" +#include "llviewercontrol.h" #include "llweb.h" -// -#include "llviewercontrol.h" -// +#include "sgversion.h" -// These two are concatenated with the language specifiers to form a complete Google Translate URL -const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="; -const char* LLTranslate::m_GoogleLangSpec = "&langpair="; -float LLTranslate::m_GoogleTimeout = 10; +#include "jsoncpp/reader.h" -LLSD LLTranslate::m_Header; -// These constants are for the GET header. -const char* LLTranslate::m_AcceptHeader = "Accept"; -const char* LLTranslate::m_AcceptType = "text/plain"; -const char* LLTranslate::m_AgentHeader = "User-Agent"; - -// These constants are in the JSON returned from Google -const char* LLTranslate::m_GoogleData = "responseData"; -const char* LLTranslate::m_GoogleTranslation = "translatedText"; -const char* LLTranslate::m_GoogleLanguage = "detectedSourceLanguage"; - -//static -void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &fromLang, const std::string &toLang, const std::string &mesg) +// virtual +void LLGoogleTranslationHandler::getTranslateURL( + std::string &url, + const std::string &from_lang, + const std::string &to_lang, + const std::string &text) const { - std::string url; - getTranslateUrl(url, fromLang, toLang, mesg); - -// - std::string user_agent = gCurrentVersion; -// - - if (!m_Header.size()) + url = std::string("https://www.googleapis.com/language/translate/v2?key=") + + getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang; + if (!from_lang.empty()) { - m_Header.insert(m_AcceptHeader, LLSD(m_AcceptType)); - m_Header.insert(m_AgentHeader, LLSD(user_agent)); - } - - LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout); -} - -//static -void LLTranslate::getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &mesg) -{ - std::string escaped_mesg = LLWeb::curlEscape(mesg); - - translateUrl = m_GoogleURL - + escaped_mesg + m_GoogleLangSpec - + fromLang // 'from' language; empty string for auto - + "%7C" // | - + toLang; // 'to' language -} - -//static -void LLTranslate::stringReplaceAll(std::string& context, const std::string& from, const std::string& to) -{ - size_t lookHere = 0; - size_t foundHere; - - while((foundHere = context.find(from, lookHere)) - != std::string::npos) { - context.replace(foundHere, from.size(), to); - lookHere = foundHere + to.size(); + url += "&source=" + from_lang; } } -//static -BOOL LLTranslate::parseGoogleTranslate(const std::string result, std::string &translation, std::string &detectedLanguage) +// virtual +void LLGoogleTranslationHandler::getKeyVerificationURL( + std::string& url, + const std::string& key) const +{ + url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=") + + key + "&target=en"; +} + +// virtual +bool LLGoogleTranslationHandler::parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const { Json::Value root; Json::Reader reader; - BOOL parsingSuccessful = reader.parse(result, root ); - if ( !parsingSuccessful ) + + if (!reader.parse(body, root)) { - LL_WARNS("JSON") << reader.getFormatedErrorMessages() << LL_ENDL; - return FALSE; + err_msg = reader.getFormatedErrorMessages(); + return false; } - translation = root[m_GoogleData].get(m_GoogleTranslation, "").asString(); - detectedLanguage = root[m_GoogleData].get(m_GoogleLanguage, "").asString(); - return TRUE; + if (!root.isObject()) // empty response? should not happen + { + return false; + } + + if (status != STATUS_OK) + { + // Request failed. Extract error message from the response. + parseErrorResponse(root, status, err_msg); + return false; + } + + // Request succeeded, extract translation from the response. + return parseTranslation(root, translation, detected_lang); +} + +// virtual +bool LLGoogleTranslationHandler::isConfigured() const +{ + return !getAPIKey().empty(); +} + +// static +void LLGoogleTranslationHandler::parseErrorResponse( + const Json::Value& root, + int& status, + std::string& err_msg) +{ + const Json::Value& error = root.get("error", 0); + if (!error.isObject() || !error.isMember("message") || !error.isMember("code")) + { + return; + } + + err_msg = error["message"].asString(); + status = error["code"].asInt(); +} + +// static +bool LLGoogleTranslationHandler::parseTranslation( + const Json::Value& root, + std::string& translation, + std::string& detected_lang) +{ + // JsonCpp is prone to aborting the program on failed assertions, + // so be super-careful and verify the response format. + const Json::Value& data = root.get("data", 0); + if (!data.isObject() || !data.isMember("translations")) + { + return false; + } + + const Json::Value& translations = data["translations"]; + if (!translations.isArray() || translations.size() == 0) + { + return false; + } + + const Json::Value& first = translations[0U]; + if (!first.isObject() || !first.isMember("translatedText")) + { + return false; + } + + translation = first["translatedText"].asString(); + detected_lang = first.get("detectedSourceLanguage", "").asString(); + return true; +} + +// static +std::string LLGoogleTranslationHandler::getAPIKey() +{ + return gSavedSettings.getString("GoogleTranslateAPIKey"); +} + +// virtual +void LLBingTranslationHandler::getTranslateURL( + std::string &url, + const std::string &from_lang, + const std::string &to_lang, + const std::string &text) const +{ + url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=") + + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang; + if (!from_lang.empty()) + { + url += "&from=" + from_lang; + } +} + +// virtual +void LLBingTranslationHandler::getKeyVerificationURL( + std::string& url, + const std::string& key) const +{ + url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=") + + key; +} + +// virtual +bool LLBingTranslationHandler::parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const +{ + if (status != STATUS_OK) + { + static const std::string MSG_BEGIN_MARKER = "Message: "; + size_t begin = body.find(MSG_BEGIN_MARKER); + if (begin != std::string::npos) + { + begin += MSG_BEGIN_MARKER.size(); + } + else + { + begin = 0; + err_msg.clear(); + } + size_t end = body.find("

", begin); + err_msg = body.substr(begin, end-begin); + LLStringUtil::replaceString(err_msg, " ", ""); // strip CR + return false; + } + + // Sample response: Hola + size_t begin = body.find(">"); + if (begin == std::string::npos || begin >= (body.size() - 1)) + { + begin = 0; + } + else + { + ++begin; + } + + size_t end = body.find("", begin); + + detected_lang = ""; // unsupported by this API + translation = body.substr(begin, end-begin); + LLStringUtil::replaceString(translation, " ", ""); // strip CR + return true; +} + +// virtual +bool LLBingTranslationHandler::isConfigured() const +{ + return !getAPIKey().empty(); +} + +// static +std::string LLBingTranslationHandler::getAPIKey() +{ + return gSavedSettings.getString("BingTranslateAPIKey"); +} + +LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang) +: mFromLang(from_lang) +, mToLang(to_lang) +, mHandler(LLTranslate::getPreferredHandler()) +{ +} + +// virtual +void LLTranslate::TranslationReceiver::completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + + const std::string body = strstrm.str(); + std::string translation, detected_lang, err_msg; + int status = http_status; + LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL; + LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL; + if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg)) + { + // Fix up the response + LLStringUtil::replaceString(translation, "<", "<"); + LLStringUtil::replaceString(translation, ">",">"); + LLStringUtil::replaceString(translation, ""","\""); + LLStringUtil::replaceString(translation, "'","'"); + LLStringUtil::replaceString(translation, "&","&"); + LLStringUtil::replaceString(translation, "'","'"); + + handleResponse(translation, detected_lang); + } + else + { + if (err_msg.empty()) + { + err_msg = LLTrans::getString("TranslationResponseParseError"); + } + + llwarns << "Translation request failed: " << err_msg << llendl; + handleFailure(status, err_msg); + } +} + +LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service) +: mService(service) +{ +} + +LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const +{ + return mService; +} + +// virtual +void LLTranslate::KeyVerificationReceiver::completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + bool ok = (http_status == 200); + setVerificationStatus(ok); +} + +//static +void LLTranslate::translateMessage( + TranslationReceiverPtr &receiver, + const std::string &from_lang, + const std::string &to_lang, + const std::string &mesg) +{ + std::string url; + receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg); + + LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL; + sendRequest(url, receiver); +} + +// static +void LLTranslate::verifyKey( + KeyVerificationReceiverPtr& receiver, + const std::string& key) +{ + std::string url; + const LLTranslationAPIHandler& handler = getHandler(receiver->getService()); + handler.getKeyVerificationURL(url, key); + + LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL; + sendRequest(url, receiver); } //static std::string LLTranslate::getTranslateLanguage() { - std::string language = "en"; - if (LLUI::sConfigGroup) + std::string language = gSavedSettings.getString("TranslateLanguage"); + if (language.empty() || language == "default") { - language = LLUI::sConfigGroup->getString("TranslateLanguage"); - if (language.empty() || language == "default") - { - language = LLUI::getLanguage(); - } + language = LLUI::getLanguage(); } language = language.substr(0,2); return language; } +// static +bool LLTranslate::isTranslationConfigured() +{ + return getPreferredHandler().isConfigured(); +} + +// static +const LLTranslationAPIHandler& LLTranslate::getPreferredHandler() +{ + EService service = SERVICE_BING; + + std::string service_str = gSavedSettings.getString("TranslationService"); + if (service_str == "google") + { + service = SERVICE_GOOGLE; + } + + return getHandler(service); +} + +// static +const LLTranslationAPIHandler& LLTranslate::getHandler(EService service) +{ + static LLGoogleTranslationHandler google; + static LLBingTranslationHandler bing; + + if (service == SERVICE_GOOGLE) + { + return google; + } + + return bing; +} + +// static +void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder) +{ + static const float REQUEST_TIMEOUT = 5; + static LLSD sHeader; + + if (!sHeader.size()) + { + std::string user_agent = llformat("%s %d.%d.%d (%d)", + gVersionChannel, + gVersionMajor, + gVersionMinor, + gVersionPatch, + gVersionBuild); + + sHeader.insert("Accept", "text/plain"); + sHeader.insert("User-Agent", user_agent); + } + + LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); +} diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 2723c43ff..870cc1fae 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -2,33 +2,27 @@ * @file lltranslate.h * @brief Human language translation class and JSON response receiver. * -* $LicenseInfo:firstyear=2009&license=viewergpl$ -* -* Copyright (c) 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$ -*/ + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ #ifndef LL_LLTRANSLATE_H #define LL_LLTRANSLATE_H @@ -37,89 +31,273 @@ #include "llbufferstream.h" #include "jsoncpp/reader.h" -class LLTranslate +namespace Json { -public : - class TranslationReceiver: public LLHTTPClient::Responder - { - protected: - TranslationReceiver(const std::string &fromLang, const std::string &toLang) - : m_fromLang(fromLang), - m_toLang(toLang) - { - } + class Value; +} - virtual void handleResponse(const std::string &translation, const std::string &recognizedLang) {} - virtual void handleFailure() {}; +/** + * Handler of an HTTP machine translation service. + * + * Derived classes know the service URL + * and how to parse the translation result. + */ +class LLTranslationAPIHandler +{ +public: + /** + * Get URL for translation of the given string. + * + * Sending HTTP GET request to the URL will initiate translation. + * + * @param[out] url Place holder for the result. + * @param from_lang Source language. Leave empty for auto-detection. + * @param to_lang Target language. + * @param text Text to translate. + */ + virtual void getTranslateURL( + std::string &url, + const std::string &from_lang, + const std::string &to_lang, + const std::string &text) const = 0; - public: - ~TranslationReceiver() - { - } + /** + * Get URL to verify the given API key. + * + * Sending request to the URL verifies the key. + * Positive HTTP response (code 200) means that the key is valid. + * + * @param[out] url Place holder for the URL. + * @param[in] key Key to verify. + */ + virtual void getKeyVerificationURL( + std::string &url, + const std::string &key) const = 0; - virtual void error(U32 status, const std::string& reason) - { - LL_WARNS("Translate") << "URL Request error: " << reason << LL_ENDL; - handleFailure(); - } + /** + * Parse translation response. + * + * @param[in,out] status HTTP status. May be modified while parsing. + * @param body Response text. + * @param[out] translation Translated text. + * @param[out] detected_lang Detected source language. May be empty. + * @param[out] err_msg Error message (in case of error). + */ + virtual bool parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const = 0; - virtual void completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - LLBufferStream istr(channels, buffer.get()); + /** + * @return if the handler is configured to function properly + */ + virtual bool isConfigured() const = 0; - std::stringstream strstrm; - strstrm << istr.rdbuf(); - const std::string result = strstrm.str(); + virtual ~LLTranslationAPIHandler() {} - std::string translation; - std::string detectedLanguage; +protected: + static const int STATUS_OK = 200; +}; - if (!parseGoogleTranslate(result, translation, detectedLanguage)) - { - handleFailure(); - return; - } +/// Google Translate v2 API handler. +class LLGoogleTranslationHandler : public LLTranslationAPIHandler +{ + LOG_CLASS(LLGoogleTranslationHandler); - // Fix up the response - stringReplaceAll( translation, "<","<"); - stringReplaceAll( translation, ">",">"); - stringReplaceAll( translation, ""","\""); - stringReplaceAll( translation, "'","'"); - stringReplaceAll( translation, "&","&"); - stringReplaceAll( translation, "'","'"); - - handleResponse(translation, detectedLanguage); - } - - protected: - const std::string m_toLang; - const std::string m_fromLang; - }; - - static void translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &fromLang, const std::string &toLang, const std::string &mesg); - static float m_GoogleTimeout; - static std::string getTranslateLanguage(); +public: + /*virtual*/ void getTranslateURL( + std::string &url, + const std::string &from_lang, + const std::string &to_lang, + const std::string &text) const; + /*virtual*/ void getKeyVerificationURL( + std::string &url, + const std::string &key) const; + /*virtual*/ bool parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const; + /*virtual*/ bool isConfigured() const; private: - static void getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &text); - static void stringReplaceAll(std::string& context, const std::string& from, const std::string& to); - static BOOL parseGoogleTranslate(const std::string result, std::string &translation, std::string &detectedLanguage); + static void parseErrorResponse( + const Json::Value& root, + int& status, + std::string& err_msg); + static bool parseTranslation( + const Json::Value& root, + std::string& translation, + std::string& detected_lang); + static std::string getAPIKey(); +}; - static LLSD m_Header; - static const char* m_GoogleURL; - static const char* m_GoogleLangSpec; - static const char* m_AcceptHeader; - static const char* m_AcceptType; - static const char* m_AgentHeader; - static const char* m_UserAgent; +/// Microsoft Translator v2 API handler. +class LLBingTranslationHandler : public LLTranslationAPIHandler +{ + LOG_CLASS(LLBingTranslationHandler); - static const char* m_GoogleData; - static const char* m_GoogleTranslation; - static const char* m_GoogleLanguage; +public: + /*virtual*/ void getTranslateURL( + std::string &url, + const std::string &from_lang, + const std::string &to_lang, + const std::string &text) const; + /*virtual*/ void getKeyVerificationURL( + std::string &url, + const std::string &key) const; + /*virtual*/ bool parseResponse( + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const; + /*virtual*/ bool isConfigured() const; +private: + static std::string getAPIKey(); +}; + +/** + * Entry point for machine translation services. + * + * Basically, to translate a string, we need to know the URL + * of a translation service, have a valid API for the service + * and be given the target language. + * + * Callers specify the string to translate and the target language, + * LLTranslate takes care of the rest. + * + * API keys for translation are taken from saved settings. + */ +class LLTranslate +{ + LOG_CLASS(LLTranslate); + +public : + + typedef enum e_service { + SERVICE_BING, + SERVICE_GOOGLE, + } EService; + + /** + * Subclasses are supposed to handle translation results (e.g. show them in chat) + */ + class TranslationReceiver: public LLHTTPClient::Responder + { + public: + + /** + * Using mHandler, parse incoming response. + * + * Calls either handleResponse() or handleFailure() + * depending on the HTTP status code and parsing success. + * + * @see handleResponse() + * @see handleFailure() + * @see mHandler + */ + /*virtual*/ void completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + + protected: + friend class LLTranslate; + + /// Remember source and target languages for subclasses to be able to filter inappropriate results. + TranslationReceiver(const std::string& from_lang, const std::string& to_lang); + + /// Override point to handle successful translation. + virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0; + + /// Override point to handle unsuccessful translation. + virtual void handleFailure(int status, const std::string& err_msg) = 0; + + std::string mFromLang; + std::string mToLang; + const LLTranslationAPIHandler& mHandler; + }; + + /** + * Subclasses are supposed to handle API key verification result. + */ + class KeyVerificationReceiver: public LLHTTPClient::Responder + { + public: + EService getService() const; + + protected: + /** + * Save the translation service the key belongs to. + * + * Subclasses need to know it. + * + * @see getService() + */ + KeyVerificationReceiver(EService service); + + /** + * Parse verification response. + * + * Calls setVerificationStatus() with the verification status, + * which is true if HTTP status code is 200. + * + * @see setVerificationStatus() + */ + /*virtual*/ void completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + + /** + * Override point for subclasses to handle key verification status. + */ + virtual void setVerificationStatus(bool ok) = 0; + + EService mService; + }; + + typedef boost::intrusive_ptr TranslationReceiverPtr; + typedef boost::intrusive_ptr KeyVerificationReceiverPtr; + + /** + * Translate given text. + * + * @param receiver Object to pass translation result to. + * @param from_lang Source language. Leave empty for auto-detection. + * @param to_lang Target language. + * @param mesg Text to translate. + */ + static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg); + + /** + * Verify given API key of a translation service. + * + * @param receiver Object to pass verification result to. + * @param key Key to verify. + */ + static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key); + + /** + * @return translation target language + */ + static std::string getTranslateLanguage(); + + /** + * @return true if translation is configured properly. + */ + static bool isTranslationConfigured(); + +private: + static const LLTranslationAPIHandler& getPreferredHandler(); + static const LLTranslationAPIHandler& getHandler(EService service); + static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder); }; #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 97ac3eb05..a060efd09 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2957,23 +2957,23 @@ void process_decline_callingcard(LLMessageSystem* msg, void**) class ChatTranslationReceiver : public LLTranslate::TranslationReceiver { public : - ChatTranslationReceiver(const std::string &fromLang, const std::string &toLang, LLChat *chat, + ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, LLChat *chat, const BOOL history) - : LLTranslate::TranslationReceiver(fromLang, toLang), + : LLTranslate::TranslationReceiver(from_lang, to_lang), m_chat(chat), m_history(history) { } - static boost::intrusive_ptr build(const std::string &fromLang, const std::string &toLang, LLChat *chat, const BOOL history) + static boost::intrusive_ptr build(const std::string &from_lang, const std::string &to_lang, LLChat *chat, const BOOL history) { - return boost::intrusive_ptr(new ChatTranslationReceiver(fromLang, toLang, chat, history)); + return boost::intrusive_ptr(new ChatTranslationReceiver(from_lang, to_lang, chat, history)); } protected: void handleResponse(const std::string &translation, const std::string &detectedLanguage) { - if (m_toLang != detectedLanguage) + if (mToLang != detectedLanguage) m_chat->mText += " (" + translation + ")"; add_floater_chat(*m_chat, m_history); @@ -2981,14 +2981,12 @@ protected: delete m_chat; } - void handleFailure() + void handleFailure(int status, const std::string& err_msg) { - LLTranslate::TranslationReceiver::handleFailure(); + llwarns << "Translation failed for mesg " << m_chat << " toLang " << mToLang << " fromLang " << mFromLang << llendl; m_chat->mText += " (?)"; - add_floater_chat(*m_chat, m_history); - delete m_chat; } @@ -3017,14 +3015,12 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist if (translate && chat.mSourceType != CHAT_SOURCE_SYSTEM) { - // fromLang hardcoded to "" (autodetection) pending implementation of - // SVC-4879 - const std::string &fromLang = ""; - const std::string &toLang = LLTranslate::getTranslateLanguage(); + const std::string &from_lang = ""; + const std::string &to_lang = LLTranslate::getTranslateLanguage(); LLChat *newChat = new LLChat(chat); - LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(fromLang, toLang, newChat, history); - LLTranslate::translateMessage(result, fromLang, toLang, mesg); + LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, newChat, history); + LLTranslate::translateMessage(result, from_lang, to_lang, mesg); } else { From 5c7debecc81e17e933ad6c117129648f43cf702e Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 20 Feb 2012 03:47:06 +0100 Subject: [PATCH 06/35] Extra info from j2c decoder in case of cache corruption --- indra/llimagej2coj/llimagej2coj.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 23f67919f..afcd914f4 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -168,7 +168,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // dereference the array. if(!image || !image->numcomps) { - llwarns << "ERROR -> decodeImpl: failed to decode image!" << llendl; + llwarns << "failed to decode image!" << llendl; if (image) { opj_image_destroy(image); @@ -183,6 +183,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod { if (image->comps[i].factor != base.getRawDiscardLevel()) { + llwarns << "Expected discard level not reached!" << llendl; // if we didn't get the discard level we're expecting, fail opj_image_destroy(image); base.decodeFailed(); From ea7396d2cf3b15e6954e4d09ce8dbc7849dd7df1 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 20 Feb 2012 05:05:53 +0100 Subject: [PATCH 07/35] Crashfix audio panel in skin --- indra/newview/skins/default/colors_base.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/colors_base.xml b/indra/newview/skins/default/colors_base.xml index d71dbe7aa..493c64096 100644 --- a/indra/newview/skins/default/colors_base.xml +++ b/indra/newview/skins/default/colors_base.xml @@ -99,7 +99,7 @@ - + @@ -195,11 +195,12 @@ + - + From 8e71cf8e6e169399e301f6fc7d3541fd86499be0 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 20 Feb 2012 05:05:57 +0100 Subject: [PATCH 08/35] Revert "Replace all NotifyCautionBoxColor's and AlertCautionBoxColor's that were using tan with black, like Emerald skin's NotifyCautionBoxColor." This reverts commit 0fef1407e3477a35041eb5111af4bb4a0cd913c3. --- indra/newview/skins/Pony-Aquablue/colors_base.xml | 4 ++-- indra/newview/skins/Pony-Purple/colors_base.xml | 4 ++-- indra/newview/skins/dark/colors_base.xml | 2 +- indra/newview/skins/darkgred/colors_base.xml | 4 ++-- indra/newview/skins/default/colors_base.xml | 4 ++-- indra/newview/skins/emerald/colors_base.xml | 2 +- indra/newview/skins/gemini/colors_base.xml | 4 ++-- indra/newview/skins/gred/colors_base.xml | 4 ++-- indra/newview/skins/kdarknv/colors.xml | 4 ++-- indra/newview/skins/kdarknv/colors_base.xml | 4 ++-- indra/newview/skins/kliteat/colors_base.xml | 4 ++-- indra/newview/skins/openlife/colors.xml | 4 ++-- indra/newview/skins/openlife/colors_base.xml | 4 ++-- indra/newview/skins/pslgreen/colors_base.xml | 2 +- indra/newview/skins/pslpurple/colors_base.xml | 2 +- indra/newview/skins/ruby/colors_base.xml | 4 ++-- indra/newview/skins/sapphire/colors_base.xml | 2 +- indra/newview/skins/silver/colors_base.xml | 4 ++-- indra/newview/skins/wisdom/colors_base.xml | 4 ++-- 19 files changed, 33 insertions(+), 33 deletions(-) diff --git a/indra/newview/skins/Pony-Aquablue/colors_base.xml b/indra/newview/skins/Pony-Aquablue/colors_base.xml index 9f8689260..b48208f68 100644 --- a/indra/newview/skins/Pony-Aquablue/colors_base.xml +++ b/indra/newview/skins/Pony-Aquablue/colors_base.xml @@ -99,7 +99,7 @@ - + @@ -195,7 +195,7 @@ - + diff --git a/indra/newview/skins/Pony-Purple/colors_base.xml b/indra/newview/skins/Pony-Purple/colors_base.xml index b359f55db..8cde4c258 100644 --- a/indra/newview/skins/Pony-Purple/colors_base.xml +++ b/indra/newview/skins/Pony-Purple/colors_base.xml @@ -98,7 +98,7 @@ - + @@ -195,7 +195,7 @@ - + diff --git a/indra/newview/skins/dark/colors_base.xml b/indra/newview/skins/dark/colors_base.xml index 2d8802b0f..032351a88 100644 --- a/indra/newview/skins/dark/colors_base.xml +++ b/indra/newview/skins/dark/colors_base.xml @@ -96,7 +96,7 @@ - + diff --git a/indra/newview/skins/darkgred/colors_base.xml b/indra/newview/skins/darkgred/colors_base.xml index 7404c0598..d7132d44d 100644 --- a/indra/newview/skins/darkgred/colors_base.xml +++ b/indra/newview/skins/darkgred/colors_base.xml @@ -96,7 +96,7 @@ - + @@ -192,7 +192,7 @@ - + diff --git a/indra/newview/skins/default/colors_base.xml b/indra/newview/skins/default/colors_base.xml index 493c64096..eafb95481 100644 --- a/indra/newview/skins/default/colors_base.xml +++ b/indra/newview/skins/default/colors_base.xml @@ -99,7 +99,7 @@ - + @@ -200,7 +200,7 @@ - + diff --git a/indra/newview/skins/emerald/colors_base.xml b/indra/newview/skins/emerald/colors_base.xml index 18eea5cd3..57f34271a 100644 --- a/indra/newview/skins/emerald/colors_base.xml +++ b/indra/newview/skins/emerald/colors_base.xml @@ -194,7 +194,7 @@ - + diff --git a/indra/newview/skins/gemini/colors_base.xml b/indra/newview/skins/gemini/colors_base.xml index cab6c8270..4f5c5df9a 100644 --- a/indra/newview/skins/gemini/colors_base.xml +++ b/indra/newview/skins/gemini/colors_base.xml @@ -98,7 +98,7 @@ - + @@ -196,7 +196,7 @@ - + diff --git a/indra/newview/skins/gred/colors_base.xml b/indra/newview/skins/gred/colors_base.xml index 91f728ecf..6ecb33e97 100644 --- a/indra/newview/skins/gred/colors_base.xml +++ b/indra/newview/skins/gred/colors_base.xml @@ -96,7 +96,7 @@ - + @@ -193,7 +193,7 @@ - + diff --git a/indra/newview/skins/kdarknv/colors.xml b/indra/newview/skins/kdarknv/colors.xml index 4c129ebbc..2a87bd898 100644 --- a/indra/newview/skins/kdarknv/colors.xml +++ b/indra/newview/skins/kdarknv/colors.xml @@ -87,7 +87,7 @@ - + @@ -181,4 +181,4 @@ - + \ No newline at end of file diff --git a/indra/newview/skins/kdarknv/colors_base.xml b/indra/newview/skins/kdarknv/colors_base.xml index 3f7cac358..477527766 100644 --- a/indra/newview/skins/kdarknv/colors_base.xml +++ b/indra/newview/skins/kdarknv/colors_base.xml @@ -99,7 +99,7 @@ - + @@ -188,7 +188,7 @@ - + diff --git a/indra/newview/skins/kliteat/colors_base.xml b/indra/newview/skins/kliteat/colors_base.xml index 3f7cac358..477527766 100644 --- a/indra/newview/skins/kliteat/colors_base.xml +++ b/indra/newview/skins/kliteat/colors_base.xml @@ -99,7 +99,7 @@ - + @@ -188,7 +188,7 @@ - + diff --git a/indra/newview/skins/openlife/colors.xml b/indra/newview/skins/openlife/colors.xml index cdfd54701..2008d0804 100644 --- a/indra/newview/skins/openlife/colors.xml +++ b/indra/newview/skins/openlife/colors.xml @@ -96,7 +96,7 @@ - + @@ -182,7 +182,7 @@ - + diff --git a/indra/newview/skins/openlife/colors_base.xml b/indra/newview/skins/openlife/colors_base.xml index 94c67c241..39f897639 100644 --- a/indra/newview/skins/openlife/colors_base.xml +++ b/indra/newview/skins/openlife/colors_base.xml @@ -96,7 +96,7 @@ - + @@ -176,7 +176,7 @@ - + diff --git a/indra/newview/skins/pslgreen/colors_base.xml b/indra/newview/skins/pslgreen/colors_base.xml index 2494452fa..10647478b 100644 --- a/indra/newview/skins/pslgreen/colors_base.xml +++ b/indra/newview/skins/pslgreen/colors_base.xml @@ -96,7 +96,7 @@ - + diff --git a/indra/newview/skins/pslpurple/colors_base.xml b/indra/newview/skins/pslpurple/colors_base.xml index 2494452fa..10647478b 100644 --- a/indra/newview/skins/pslpurple/colors_base.xml +++ b/indra/newview/skins/pslpurple/colors_base.xml @@ -96,7 +96,7 @@ - + diff --git a/indra/newview/skins/ruby/colors_base.xml b/indra/newview/skins/ruby/colors_base.xml index 6ab840c02..f55f4c2e5 100644 --- a/indra/newview/skins/ruby/colors_base.xml +++ b/indra/newview/skins/ruby/colors_base.xml @@ -96,7 +96,7 @@ - + @@ -192,7 +192,7 @@ - + diff --git a/indra/newview/skins/sapphire/colors_base.xml b/indra/newview/skins/sapphire/colors_base.xml index 587f47bf5..0b5e343e1 100644 --- a/indra/newview/skins/sapphire/colors_base.xml +++ b/indra/newview/skins/sapphire/colors_base.xml @@ -96,7 +96,7 @@ - + diff --git a/indra/newview/skins/silver/colors_base.xml b/indra/newview/skins/silver/colors_base.xml index ada05d3ed..7ae59a490 100644 --- a/indra/newview/skins/silver/colors_base.xml +++ b/indra/newview/skins/silver/colors_base.xml @@ -98,7 +98,7 @@ - + @@ -199,7 +199,7 @@ - + diff --git a/indra/newview/skins/wisdom/colors_base.xml b/indra/newview/skins/wisdom/colors_base.xml index 5bdc1f360..cfb056c21 100644 --- a/indra/newview/skins/wisdom/colors_base.xml +++ b/indra/newview/skins/wisdom/colors_base.xml @@ -99,7 +99,7 @@ - + @@ -191,7 +191,7 @@ - + From 9477a5f32fdab94b8e1d6bc5649c617b13b17791 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 20 Feb 2012 05:38:57 +0100 Subject: [PATCH 09/35] Fix code bug making notifications unreadable colour --- indra/newview/llnotify.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 20145004f..c942aee44 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -242,6 +242,30 @@ LLNotifyBox::LLNotifyBox(LLNotificationPtr notification, // it appears below the caution textbox y = y - caution_height; } + else if (mIsCaution && mIsTip) + { + + const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); + + // Tokenization on \n is handled by LLTextBox + + const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title. + + text = new LLTextEditor(std::string("box"), LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16), MAX_LENGTH, mMessage, sFont, FALSE); + text->setWordWrap(TRUE); + text->setTabStop(FALSE); + text->setMouseOpaque(FALSE); + text->setBorderVisible(FALSE); + text->setTakesNonScrollClicks(FALSE); + text->setHideScrollbarForShortDocs(TRUE); + text->setReadOnlyBgColor ( LLColor4::transparent ); // the background color of the box is manually + // rendered under the text box, therefore we want + // the actual text box to be transparent + text->setReadOnlyFgColor ( gColors.getColor("NotifyCautionWarnColor") ); //sets caution text color for tip notifications + text->setEnabled(FALSE); // makes it read-only + text->setTabStop(FALSE); // can't tab to it (may be a problem for scrolling via keyboard) + addChild(text); + } else { From 89f35779b4b3e20d8aa233a01c2a3aa89832d80f Mon Sep 17 00:00:00 2001 From: TighMacFanatic Date: Mon, 20 Feb 2012 16:37:34 -0500 Subject: [PATCH 10/35] Fixed Windlight presets not loading user created files. --- indra/newview/llfloaterwindlight.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp index 5d69cc246..e2c96db76 100644 --- a/indra/newview/llfloaterwindlight.cpp +++ b/indra/newview/llfloaterwindlight.cpp @@ -1070,5 +1070,13 @@ void LLFloaterWindLight::populateSkyPresetsList() mSkyPresetCombo->add(*it); } + LLWLParamManager::preset_name_list_t user_presets; + LLWLParamManager::getInstance()->getUserPresetNames(user_presets); + + for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it) + { + mSkyPresetCombo->add(*it); + } + mSkyPresetCombo->selectByValue(LLEnvManagerNew::instance().getSkyPresetName()); } From 638832455215ff5710d3febf8825aee7c779d316 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Tue, 21 Feb 2012 09:27:10 -0500 Subject: [PATCH 11/35] Revert "This works for now. Need to do more testing." This reverts commit c6d6eed7d33121ac2bbd466ac2e49cccd6f6d921. --- indra/newview/app_settings/settings.xml | 54 +-- indra/newview/lltranslate.cpp | 465 +++++------------------- indra/newview/lltranslate.h | 368 +++++-------------- indra/newview/llviewermessage.cpp | 26 +- 4 files changed, 221 insertions(+), 692 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7553e8816..2b521fed4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,15 +1,16 @@ - Include - - settings_ascent.xml - settings_ascent_coa.xml - settings_sh.xml - settings_rlv.xml - - SianaRenderDeferredInvisiprim - + Include + + settings_ascent.xml + settings_ascent_coa.xml + settings_sh.xml + settings_rlv.xml + + + SianaRenderDeferredInvisiprim + Comment Support invisiprims in deferred mode Persist @@ -7524,45 +7525,12 @@ Comment Translate incoming chat messages Persist - 1 + 0 Type Boolean Value 0 - TranslationService - - Comment - Translation API to use. (google|bing) - Persist - 1 - Type - String - Value - bing - - GoogleTranslateAPIKey - - Comment - Google Translate API key - Persist - 1 - Type - String - Value - - - BingTranslateAPIKey - - Comment - Bing AppID to use with the Microsoft Translator API - Persist - 1 - Type - String - Value - - LastFeatureVersion Comment diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index fcff3a0c7..5a537ae95 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -2,401 +2,136 @@ * @file lltranslate.cpp * @brief Functions for translating text via Google Translate. * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 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 "llviewerprecompiledheaders.h" -#include "lltranslate.h" - -#include - #include "llbufferstream.h" -#include "lltrans.h" +#include "lltranslate.h" #include "llui.h" -#include "llviewercontrol.h" +#include "sgversion.h" #include "llweb.h" -#include "sgversion.h" +// +#include "llviewercontrol.h" +// -#include "jsoncpp/reader.h" +// These two are concatenated with the language specifiers to form a complete Google Translate URL +const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="; +const char* LLTranslate::m_GoogleLangSpec = "&langpair="; +float LLTranslate::m_GoogleTimeout = 10; -// virtual -void LLGoogleTranslationHandler::getTranslateURL( - std::string &url, - const std::string &from_lang, - const std::string &to_lang, - const std::string &text) const +LLSD LLTranslate::m_Header; +// These constants are for the GET header. +const char* LLTranslate::m_AcceptHeader = "Accept"; +const char* LLTranslate::m_AcceptType = "text/plain"; +const char* LLTranslate::m_AgentHeader = "User-Agent"; + +// These constants are in the JSON returned from Google +const char* LLTranslate::m_GoogleData = "responseData"; +const char* LLTranslate::m_GoogleTranslation = "translatedText"; +const char* LLTranslate::m_GoogleLanguage = "detectedSourceLanguage"; + +//static +void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &fromLang, const std::string &toLang, const std::string &mesg) { - url = std::string("https://www.googleapis.com/language/translate/v2?key=") - + getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang; - if (!from_lang.empty()) + std::string url; + getTranslateUrl(url, fromLang, toLang, mesg); + +// + std::string user_agent = gCurrentVersion; +// + + if (!m_Header.size()) { - url += "&source=" + from_lang; - } -} - -// virtual -void LLGoogleTranslationHandler::getKeyVerificationURL( - std::string& url, - const std::string& key) const -{ - url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=") - + key + "&target=en"; -} - -// virtual -bool LLGoogleTranslationHandler::parseResponse( - int& status, - const std::string& body, - std::string& translation, - std::string& detected_lang, - std::string& err_msg) const -{ - Json::Value root; - Json::Reader reader; - - if (!reader.parse(body, root)) - { - err_msg = reader.getFormatedErrorMessages(); - return false; + m_Header.insert(m_AcceptHeader, LLSD(m_AcceptType)); + m_Header.insert(m_AgentHeader, LLSD(user_agent)); } - if (!root.isObject()) // empty response? should not happen - { - return false; - } - - if (status != STATUS_OK) - { - // Request failed. Extract error message from the response. - parseErrorResponse(root, status, err_msg); - return false; - } - - // Request succeeded, extract translation from the response. - return parseTranslation(root, translation, detected_lang); -} - -// virtual -bool LLGoogleTranslationHandler::isConfigured() const -{ - return !getAPIKey().empty(); -} - -// static -void LLGoogleTranslationHandler::parseErrorResponse( - const Json::Value& root, - int& status, - std::string& err_msg) -{ - const Json::Value& error = root.get("error", 0); - if (!error.isObject() || !error.isMember("message") || !error.isMember("code")) - { - return; - } - - err_msg = error["message"].asString(); - status = error["code"].asInt(); -} - -// static -bool LLGoogleTranslationHandler::parseTranslation( - const Json::Value& root, - std::string& translation, - std::string& detected_lang) -{ - // JsonCpp is prone to aborting the program on failed assertions, - // so be super-careful and verify the response format. - const Json::Value& data = root.get("data", 0); - if (!data.isObject() || !data.isMember("translations")) - { - return false; - } - - const Json::Value& translations = data["translations"]; - if (!translations.isArray() || translations.size() == 0) - { - return false; - } - - const Json::Value& first = translations[0U]; - if (!first.isObject() || !first.isMember("translatedText")) - { - return false; - } - - translation = first["translatedText"].asString(); - detected_lang = first.get("detectedSourceLanguage", "").asString(); - return true; -} - -// static -std::string LLGoogleTranslationHandler::getAPIKey() -{ - return gSavedSettings.getString("GoogleTranslateAPIKey"); -} - -// virtual -void LLBingTranslationHandler::getTranslateURL( - std::string &url, - const std::string &from_lang, - const std::string &to_lang, - const std::string &text) const -{ - url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=") - + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang; - if (!from_lang.empty()) - { - url += "&from=" + from_lang; - } -} - -// virtual -void LLBingTranslationHandler::getKeyVerificationURL( - std::string& url, - const std::string& key) const -{ - url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=") - + key; -} - -// virtual -bool LLBingTranslationHandler::parseResponse( - int& status, - const std::string& body, - std::string& translation, - std::string& detected_lang, - std::string& err_msg) const -{ - if (status != STATUS_OK) - { - static const std::string MSG_BEGIN_MARKER = "Message: "; - size_t begin = body.find(MSG_BEGIN_MARKER); - if (begin != std::string::npos) - { - begin += MSG_BEGIN_MARKER.size(); - } - else - { - begin = 0; - err_msg.clear(); - } - size_t end = body.find("

", begin); - err_msg = body.substr(begin, end-begin); - LLStringUtil::replaceString(err_msg, " ", ""); // strip CR - return false; - } - - // Sample response: Hola - size_t begin = body.find(">"); - if (begin == std::string::npos || begin >= (body.size() - 1)) - { - begin = 0; - } - else - { - ++begin; - } - - size_t end = body.find("", begin); - - detected_lang = ""; // unsupported by this API - translation = body.substr(begin, end-begin); - LLStringUtil::replaceString(translation, " ", ""); // strip CR - return true; -} - -// virtual -bool LLBingTranslationHandler::isConfigured() const -{ - return !getAPIKey().empty(); -} - -// static -std::string LLBingTranslationHandler::getAPIKey() -{ - return gSavedSettings.getString("BingTranslateAPIKey"); -} - -LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang) -: mFromLang(from_lang) -, mToLang(to_lang) -, mHandler(LLTranslate::getPreferredHandler()) -{ -} - -// virtual -void LLTranslate::TranslationReceiver::completedRaw( - U32 http_status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) -{ - LLBufferStream istr(channels, buffer.get()); - std::stringstream strstrm; - strstrm << istr.rdbuf(); - - const std::string body = strstrm.str(); - std::string translation, detected_lang, err_msg; - int status = http_status; - LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL; - LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL; - if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg)) - { - // Fix up the response - LLStringUtil::replaceString(translation, "<", "<"); - LLStringUtil::replaceString(translation, ">",">"); - LLStringUtil::replaceString(translation, ""","\""); - LLStringUtil::replaceString(translation, "'","'"); - LLStringUtil::replaceString(translation, "&","&"); - LLStringUtil::replaceString(translation, "'","'"); - - handleResponse(translation, detected_lang); - } - else - { - if (err_msg.empty()) - { - err_msg = LLTrans::getString("TranslationResponseParseError"); - } - - llwarns << "Translation request failed: " << err_msg << llendl; - handleFailure(status, err_msg); - } -} - -LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service) -: mService(service) -{ -} - -LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const -{ - return mService; -} - -// virtual -void LLTranslate::KeyVerificationReceiver::completedRaw( - U32 http_status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) -{ - bool ok = (http_status == 200); - setVerificationStatus(ok); + LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout); } //static -void LLTranslate::translateMessage( - TranslationReceiverPtr &receiver, - const std::string &from_lang, - const std::string &to_lang, - const std::string &mesg) +void LLTranslate::getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &mesg) { - std::string url; - receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg); + std::string escaped_mesg = LLWeb::curlEscape(mesg); - LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL; - sendRequest(url, receiver); + translateUrl = m_GoogleURL + + escaped_mesg + m_GoogleLangSpec + + fromLang // 'from' language; empty string for auto + + "%7C" // | + + toLang; // 'to' language } -// static -void LLTranslate::verifyKey( - KeyVerificationReceiverPtr& receiver, - const std::string& key) +//static +void LLTranslate::stringReplaceAll(std::string& context, const std::string& from, const std::string& to) { - std::string url; - const LLTranslationAPIHandler& handler = getHandler(receiver->getService()); - handler.getKeyVerificationURL(url, key); + size_t lookHere = 0; + size_t foundHere; - LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL; - sendRequest(url, receiver); + while((foundHere = context.find(from, lookHere)) + != std::string::npos) { + context.replace(foundHere, from.size(), to); + lookHere = foundHere + to.size(); + } +} + +//static +BOOL LLTranslate::parseGoogleTranslate(const std::string result, std::string &translation, std::string &detectedLanguage) +{ + Json::Value root; + Json::Reader reader; + BOOL parsingSuccessful = reader.parse(result, root ); + if ( !parsingSuccessful ) + { + LL_WARNS("JSON") << reader.getFormatedErrorMessages() << LL_ENDL; + return FALSE; + } + + translation = root[m_GoogleData].get(m_GoogleTranslation, "").asString(); + detectedLanguage = root[m_GoogleData].get(m_GoogleLanguage, "").asString(); + return TRUE; } //static std::string LLTranslate::getTranslateLanguage() { - std::string language = gSavedSettings.getString("TranslateLanguage"); - if (language.empty() || language == "default") + std::string language = "en"; + if (LLUI::sConfigGroup) { - language = LLUI::getLanguage(); + language = LLUI::sConfigGroup->getString("TranslateLanguage"); + if (language.empty() || language == "default") + { + language = LLUI::getLanguage(); + } } language = language.substr(0,2); return language; } -// static -bool LLTranslate::isTranslationConfigured() -{ - return getPreferredHandler().isConfigured(); -} - -// static -const LLTranslationAPIHandler& LLTranslate::getPreferredHandler() -{ - EService service = SERVICE_BING; - - std::string service_str = gSavedSettings.getString("TranslationService"); - if (service_str == "google") - { - service = SERVICE_GOOGLE; - } - - return getHandler(service); -} - -// static -const LLTranslationAPIHandler& LLTranslate::getHandler(EService service) -{ - static LLGoogleTranslationHandler google; - static LLBingTranslationHandler bing; - - if (service == SERVICE_GOOGLE) - { - return google; - } - - return bing; -} - -// static -void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder) -{ - static const float REQUEST_TIMEOUT = 5; - static LLSD sHeader; - - if (!sHeader.size()) - { - std::string user_agent = llformat("%s %d.%d.%d (%d)", - gVersionChannel, - gVersionMajor, - gVersionMinor, - gVersionPatch, - gVersionBuild); - - sHeader.insert("Accept", "text/plain"); - sHeader.insert("User-Agent", user_agent); - } - - LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); -} diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 870cc1fae..2723c43ff 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -2,27 +2,33 @@ * @file lltranslate.h * @brief Human language translation class and JSON response receiver. * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ +* $LicenseInfo:firstyear=2009&license=viewergpl$ +* +* Copyright (c) 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_LLTRANSLATE_H #define LL_LLTRANSLATE_H @@ -31,273 +37,89 @@ #include "llbufferstream.h" #include "jsoncpp/reader.h" -namespace Json -{ - class Value; -} - -/** - * Handler of an HTTP machine translation service. - * - * Derived classes know the service URL - * and how to parse the translation result. - */ -class LLTranslationAPIHandler -{ -public: - /** - * Get URL for translation of the given string. - * - * Sending HTTP GET request to the URL will initiate translation. - * - * @param[out] url Place holder for the result. - * @param from_lang Source language. Leave empty for auto-detection. - * @param to_lang Target language. - * @param text Text to translate. - */ - virtual void getTranslateURL( - std::string &url, - const std::string &from_lang, - const std::string &to_lang, - const std::string &text) const = 0; - - /** - * Get URL to verify the given API key. - * - * Sending request to the URL verifies the key. - * Positive HTTP response (code 200) means that the key is valid. - * - * @param[out] url Place holder for the URL. - * @param[in] key Key to verify. - */ - virtual void getKeyVerificationURL( - std::string &url, - const std::string &key) const = 0; - - /** - * Parse translation response. - * - * @param[in,out] status HTTP status. May be modified while parsing. - * @param body Response text. - * @param[out] translation Translated text. - * @param[out] detected_lang Detected source language. May be empty. - * @param[out] err_msg Error message (in case of error). - */ - virtual bool parseResponse( - int& status, - const std::string& body, - std::string& translation, - std::string& detected_lang, - std::string& err_msg) const = 0; - - /** - * @return if the handler is configured to function properly - */ - virtual bool isConfigured() const = 0; - - virtual ~LLTranslationAPIHandler() {} - -protected: - static const int STATUS_OK = 200; -}; - -/// Google Translate v2 API handler. -class LLGoogleTranslationHandler : public LLTranslationAPIHandler -{ - LOG_CLASS(LLGoogleTranslationHandler); - -public: - /*virtual*/ void getTranslateURL( - std::string &url, - const std::string &from_lang, - const std::string &to_lang, - const std::string &text) const; - /*virtual*/ void getKeyVerificationURL( - std::string &url, - const std::string &key) const; - /*virtual*/ bool parseResponse( - int& status, - const std::string& body, - std::string& translation, - std::string& detected_lang, - std::string& err_msg) const; - /*virtual*/ bool isConfigured() const; - -private: - static void parseErrorResponse( - const Json::Value& root, - int& status, - std::string& err_msg); - static bool parseTranslation( - const Json::Value& root, - std::string& translation, - std::string& detected_lang); - static std::string getAPIKey(); -}; - -/// Microsoft Translator v2 API handler. -class LLBingTranslationHandler : public LLTranslationAPIHandler -{ - LOG_CLASS(LLBingTranslationHandler); - -public: - /*virtual*/ void getTranslateURL( - std::string &url, - const std::string &from_lang, - const std::string &to_lang, - const std::string &text) const; - /*virtual*/ void getKeyVerificationURL( - std::string &url, - const std::string &key) const; - /*virtual*/ bool parseResponse( - int& status, - const std::string& body, - std::string& translation, - std::string& detected_lang, - std::string& err_msg) const; - /*virtual*/ bool isConfigured() const; -private: - static std::string getAPIKey(); -}; - -/** - * Entry point for machine translation services. - * - * Basically, to translate a string, we need to know the URL - * of a translation service, have a valid API for the service - * and be given the target language. - * - * Callers specify the string to translate and the target language, - * LLTranslate takes care of the rest. - * - * API keys for translation are taken from saved settings. - */ class LLTranslate { - LOG_CLASS(LLTranslate); - public : - - typedef enum e_service { - SERVICE_BING, - SERVICE_GOOGLE, - } EService; - - /** - * Subclasses are supposed to handle translation results (e.g. show them in chat) - */ class TranslationReceiver: public LLHTTPClient::Responder { - public: + protected: + TranslationReceiver(const std::string &fromLang, const std::string &toLang) + : m_fromLang(fromLang), + m_toLang(toLang) + { + } - /** - * Using mHandler, parse incoming response. - * - * Calls either handleResponse() or handleFailure() - * depending on the HTTP status code and parsing success. - * - * @see handleResponse() - * @see handleFailure() - * @see mHandler - */ - /*virtual*/ void completedRaw( - U32 http_status, + virtual void handleResponse(const std::string &translation, const std::string &recognizedLang) {} + virtual void handleFailure() {}; + + public: + ~TranslationReceiver() + { + } + + virtual void error(U32 status, const std::string& reason) + { + LL_WARNS("Translate") << "URL Request error: " << reason << LL_ENDL; + handleFailure(); + } + + virtual void completedRaw( + U32 status, const std::string& reason, const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); + const LLIOPipe::buffer_ptr_t& buffer) + { + LLBufferStream istr(channels, buffer.get()); + + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string result = strstrm.str(); + + std::string translation; + std::string detectedLanguage; + + if (!parseGoogleTranslate(result, translation, detectedLanguage)) + { + handleFailure(); + return; + } + + // Fix up the response + stringReplaceAll( translation, "<","<"); + stringReplaceAll( translation, ">",">"); + stringReplaceAll( translation, ""","\""); + stringReplaceAll( translation, "'","'"); + stringReplaceAll( translation, "&","&"); + stringReplaceAll( translation, "'","'"); + + handleResponse(translation, detectedLanguage); + } protected: - friend class LLTranslate; - - /// Remember source and target languages for subclasses to be able to filter inappropriate results. - TranslationReceiver(const std::string& from_lang, const std::string& to_lang); - - /// Override point to handle successful translation. - virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0; - - /// Override point to handle unsuccessful translation. - virtual void handleFailure(int status, const std::string& err_msg) = 0; - - std::string mFromLang; - std::string mToLang; - const LLTranslationAPIHandler& mHandler; + const std::string m_toLang; + const std::string m_fromLang; }; - /** - * Subclasses are supposed to handle API key verification result. - */ - class KeyVerificationReceiver: public LLHTTPClient::Responder - { - public: - EService getService() const; - - protected: - /** - * Save the translation service the key belongs to. - * - * Subclasses need to know it. - * - * @see getService() - */ - KeyVerificationReceiver(EService service); - - /** - * Parse verification response. - * - * Calls setVerificationStatus() with the verification status, - * which is true if HTTP status code is 200. - * - * @see setVerificationStatus() - */ - /*virtual*/ void completedRaw( - U32 http_status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); - - /** - * Override point for subclasses to handle key verification status. - */ - virtual void setVerificationStatus(bool ok) = 0; - - EService mService; - }; - - typedef boost::intrusive_ptr TranslationReceiverPtr; - typedef boost::intrusive_ptr KeyVerificationReceiverPtr; - - /** - * Translate given text. - * - * @param receiver Object to pass translation result to. - * @param from_lang Source language. Leave empty for auto-detection. - * @param to_lang Target language. - * @param mesg Text to translate. - */ - static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg); - - /** - * Verify given API key of a translation service. - * - * @param receiver Object to pass verification result to. - * @param key Key to verify. - */ - static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key); - - /** - * @return translation target language - */ + static void translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &fromLang, const std::string &toLang, const std::string &mesg); + static float m_GoogleTimeout; static std::string getTranslateLanguage(); - /** - * @return true if translation is configured properly. - */ - static bool isTranslationConfigured(); - private: - static const LLTranslationAPIHandler& getPreferredHandler(); - static const LLTranslationAPIHandler& getHandler(EService service); - static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder); + static void getTranslateUrl(std::string &translateUrl, const std::string &fromLang, const std::string &toLang, const std::string &text); + static void stringReplaceAll(std::string& context, const std::string& from, const std::string& to); + static BOOL parseGoogleTranslate(const std::string result, std::string &translation, std::string &detectedLanguage); + + static LLSD m_Header; + static const char* m_GoogleURL; + static const char* m_GoogleLangSpec; + static const char* m_AcceptHeader; + static const char* m_AcceptType; + static const char* m_AgentHeader; + static const char* m_UserAgent; + + static const char* m_GoogleData; + static const char* m_GoogleTranslation; + static const char* m_GoogleLanguage; }; #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a060efd09..97ac3eb05 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2957,23 +2957,23 @@ void process_decline_callingcard(LLMessageSystem* msg, void**) class ChatTranslationReceiver : public LLTranslate::TranslationReceiver { public : - ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, LLChat *chat, + ChatTranslationReceiver(const std::string &fromLang, const std::string &toLang, LLChat *chat, const BOOL history) - : LLTranslate::TranslationReceiver(from_lang, to_lang), + : LLTranslate::TranslationReceiver(fromLang, toLang), m_chat(chat), m_history(history) { } - static boost::intrusive_ptr build(const std::string &from_lang, const std::string &to_lang, LLChat *chat, const BOOL history) + static boost::intrusive_ptr build(const std::string &fromLang, const std::string &toLang, LLChat *chat, const BOOL history) { - return boost::intrusive_ptr(new ChatTranslationReceiver(from_lang, to_lang, chat, history)); + return boost::intrusive_ptr(new ChatTranslationReceiver(fromLang, toLang, chat, history)); } protected: void handleResponse(const std::string &translation, const std::string &detectedLanguage) { - if (mToLang != detectedLanguage) + if (m_toLang != detectedLanguage) m_chat->mText += " (" + translation + ")"; add_floater_chat(*m_chat, m_history); @@ -2981,12 +2981,14 @@ protected: delete m_chat; } - void handleFailure(int status, const std::string& err_msg) + void handleFailure() { - llwarns << "Translation failed for mesg " << m_chat << " toLang " << mToLang << " fromLang " << mFromLang << llendl; + LLTranslate::TranslationReceiver::handleFailure(); m_chat->mText += " (?)"; + add_floater_chat(*m_chat, m_history); + delete m_chat; } @@ -3015,12 +3017,14 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist if (translate && chat.mSourceType != CHAT_SOURCE_SYSTEM) { - const std::string &from_lang = ""; - const std::string &to_lang = LLTranslate::getTranslateLanguage(); + // fromLang hardcoded to "" (autodetection) pending implementation of + // SVC-4879 + const std::string &fromLang = ""; + const std::string &toLang = LLTranslate::getTranslateLanguage(); LLChat *newChat = new LLChat(chat); - LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, newChat, history); - LLTranslate::translateMessage(result, from_lang, to_lang, mesg); + LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(fromLang, toLang, newChat, history); + LLTranslate::translateMessage(result, fromLang, toLang, mesg); } else { From 803011582cb98435042cb534d44032977e33111c Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Tue, 21 Feb 2012 10:53:47 -0500 Subject: [PATCH 12/35] Further OS X changes. --- indra/cmake/Variables.cmake | 4 +-- indra/newview/CMakeLists.txt | 55 ++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 964c9d684..0428ae87d 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -78,15 +78,15 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") #SDK Compiler and Deployment targets for XCode if (${XCODE_VERSION} VERSION_LESS 4.0.0) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk) set(CMAKE_XCODE_ATTIBUTE_GCC_VERSION "4.2") else (${XCODE_VERSION} VERSION_LESS 4.0.0) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk) set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42") endif (${XCODE_VERSION} VERSION_LESS 4.0.0) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) - # NOTE: To attempt an i386/PPC Universal build, add this on the configure line: # -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc' # Build only for i386 by default, system default on MacOSX 10.6 is x86_64 diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 66b5b4b3a..014a63461 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1338,39 +1338,40 @@ if (OPENAL) endif (OPENAL) if (FMOD OR FMODEX) - if(FMODEX) - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") - endif(FMODEX) - if(FMOD) + if (FMODEX) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") + endif (FMODEX) + if (FMOD) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") - endif(FMOD) + endif (FMOD) - if (NOT WINDOWS) + if (DARWIN) set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) - if(FMOD AND FMODEX) - set(fmodwrapper_needed_LIBRARIES "${FMODEX_LIBRARY} ${FMOD_LIBRARY}") - else(FMOD AND FMODEX) - if(FMODEX) - set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY}) - endif(FMODEX) - if(FMOD) - set(fmodwrapper_needed_LIBRARIES "${FMOD_LIBRARY}") - endif(FMOD) - endif(FMOD AND FMODEX) - if (DARWIN) - list(APPEND fmodwrapper_needed_LIBRARIES ${CARBON_LIBRARY}) - set_target_properties( - fmodwrapper - PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Resources" - LINK_FLAGS "-unexported_symbols_list \"${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp\"" - ) - endif (DARWIN) + if (FMODEX) + set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY} ${CARBON_LIBRARY}) + endif (FMODEX) + if (FMOD) + set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) + endif (FMOD) + set_target_properties( + fmodwrapper + PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Resources" + LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" + ) set(FMODWRAPPER_LIBRARY fmodwrapper) target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) - endif (NOT WINDOWS) + else (DARWIN) + # fmodwrapper unnecessary on linux or windows, for fmod and fmodex + if (FMODEX) + set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) + endif (FMODEX) + if (FMOD) + set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) + endif (FMOD) + endif (DARWIN) endif (FMOD OR FMODEX) set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") From 3250725aaec50444a1ef85a956291b224bcd3d3e Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Tue, 21 Feb 2012 10:56:27 -0500 Subject: [PATCH 13/35] Annoying Crash Fix. This fixes that thing where saving scripts in deleted object makes viewer go FFFFFF. --- indra/newview/llpreviewscript.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 6682a6e8c..b4b8ef4d2 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2301,6 +2301,13 @@ void LLLiveLSLEditor::saveIfNeeded() return; } +// [RLVa:KB] - Checked: 2010-11-25 (RLVa-1.2.2b) | Modified: RLVa-1.2.2b + if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachment(object->getRootEdit())) ) + { + return; + } +// [/RLVa:KB] + // get the latest info about it. We used to be losing the script // name on save, because the viewer object version of the item, // and the editor version would get out of synch. Here's a good @@ -2607,14 +2614,6 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save) { LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a - const LLViewerObject* pObject = gObjectList.findObject(self->mObjectID); - if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.isLockedAttachment(pObject->getRootEdit())) ) - { - return; - } -// [/RLVa:KB] - self->mCloseAfterSave = close_after_save; self->saveIfNeeded(); } From edbc22961e197bed9c0840b3527736e9fbd89960 Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Wed, 22 Feb 2012 05:49:38 -0500 Subject: [PATCH 14/35] Revert "Further OS X changes." This reverts commit 803011582cb98435042cb534d44032977e33111c. --- indra/cmake/Variables.cmake | 4 +-- indra/newview/CMakeLists.txt | 55 ++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 0428ae87d..964c9d684 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -78,15 +78,15 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") #SDK Compiler and Deployment targets for XCode if (${XCODE_VERSION} VERSION_LESS 4.0.0) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk) set(CMAKE_XCODE_ATTIBUTE_GCC_VERSION "4.2") else (${XCODE_VERSION} VERSION_LESS 4.0.0) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk) set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42") endif (${XCODE_VERSION} VERSION_LESS 4.0.0) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) + # NOTE: To attempt an i386/PPC Universal build, add this on the configure line: # -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc' # Build only for i386 by default, system default on MacOSX 10.6 is x86_64 diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 014a63461..66b5b4b3a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1338,40 +1338,39 @@ if (OPENAL) endif (OPENAL) if (FMOD OR FMODEX) - if (FMODEX) - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") - endif (FMODEX) - if (FMOD) + if(FMODEX) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") + endif(FMODEX) + if(FMOD) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") - endif (FMOD) + endif(FMOD) - if (DARWIN) + if (NOT WINDOWS) set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) - if (FMODEX) - set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY} ${CARBON_LIBRARY}) - endif (FMODEX) - if (FMOD) - set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) - endif (FMOD) - set_target_properties( - fmodwrapper - PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Resources" - LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" - ) + if(FMOD AND FMODEX) + set(fmodwrapper_needed_LIBRARIES "${FMODEX_LIBRARY} ${FMOD_LIBRARY}") + else(FMOD AND FMODEX) + if(FMODEX) + set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY}) + endif(FMODEX) + if(FMOD) + set(fmodwrapper_needed_LIBRARIES "${FMOD_LIBRARY}") + endif(FMOD) + endif(FMOD AND FMODEX) + if (DARWIN) + list(APPEND fmodwrapper_needed_LIBRARIES ${CARBON_LIBRARY}) + set_target_properties( + fmodwrapper + PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Resources" + LINK_FLAGS "-unexported_symbols_list \"${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp\"" + ) + endif (DARWIN) set(FMODWRAPPER_LIBRARY fmodwrapper) target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) - else (DARWIN) - # fmodwrapper unnecessary on linux or windows, for fmod and fmodex - if (FMODEX) - set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) - endif (FMODEX) - if (FMOD) - set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) - endif (FMOD) - endif (DARWIN) + endif (NOT WINDOWS) endif (FMOD OR FMODEX) set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") From e207f2e025cc8e71ca41b18e643adce18a0dd12d Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 23 Feb 2012 02:29:59 +0100 Subject: [PATCH 15/35] Fix scroll buttons on dark skin --- indra/newview/skins/dark/textures/preview.png | Bin 16592 -> 19933 bytes .../textures/scrollbutton_up_out_blue.tga | Bin 0 -> 929 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 indra/newview/skins/dark/textures/scrollbutton_up_out_blue.tga diff --git a/indra/newview/skins/dark/textures/preview.png b/indra/newview/skins/dark/textures/preview.png index 2cac82923b8ba4f30612138d1c3dbc7fe82e91c2..a9f2b8b0277ae14b8facfae422bbdfe4e7485a73 100644 GIT binary patch literal 19933 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 Yu+ril*i?(Ldu>VJwh;fOt*nCo0oP+^NB{r; literal 16592 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 diff --git a/indra/newview/skins/dark/textures/scrollbutton_up_out_blue.tga b/indra/newview/skins/dark/textures/scrollbutton_up_out_blue.tga new file mode 100644 index 0000000000000000000000000000000000000000..9112d187e274597c18ea426281d2ff329f1ef62e GIT binary patch literal 929 zcmZuw%W7It6uoT{kxrUV=nu4WM;WD5C@u6wzec@E5fq=qQAXlKM8OYGR78B>Ga7v2 z`yFF626eXTI$$zrFWj@w+UM+b&R%;TNqQq4zjNtadZ&D)QmH;2{)zc8fM`O`+ru!d z)oNHSmsqdY*lae~ZnxO&cG&Ot!V=TZb?%$b=O~p*U@QqRola3K7E!HM(QG!+?RGI3 z3@{pvge9h*>)e-2CNUn5NdQ4WkV>V*;_dA%>h(HWt(FL)C8nRj+!u{TF&qwG2ngsT zb2ghrp-@1%T*l4Kjj+V@bDjG_p%8k#-U|VN+wF$QWP;gjhQ(rm)oO*!W)qf}ey$sh zMqFQCqtodKf)nP^Znt4D7_e9@V5D*qaj$&xShb`@!;y}3R& zevt(al5zMHoG~A-*Na#zhHyBHe!u_!@N_yYD0q&{NCjo_`Fx1S9(xAP@j)SqzdyA`y`oZ~mIY{r$aYFq!3(E0qeAoU!LvNb-@J9En8Y zxs`;#4-XHbRoF6APiE68iKq|(8;NvmCerY_Je7h^SX1iDUO!qrCyLc-CA_pegqLKC mF^cc$;_#=RUssx*;}iVx?dRn$^>_8xFYkYURDZtwApHf@Ta_gM literal 0 HcmV?d00001 From d721fd65b3f62a436be8ba8ea62b1a55a806914f Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 23 Feb 2012 03:03:15 +0100 Subject: [PATCH 16/35] Bugfix repackager --- repackage.sh => scripts/repackage.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) rename repackage.sh => scripts/repackage.sh (95%) diff --git a/repackage.sh b/scripts/repackage.sh similarity index 95% rename from repackage.sh rename to scripts/repackage.sh index c8f6b401c..5b1097273 100755 --- a/repackage.sh +++ b/scripts/repackage.sh @@ -51,6 +51,7 @@ esac case "$2" in --commoninclude|--common-include|--common) + echo "Using common include directory" INCPATH="libraries/include" shift ;; @@ -68,11 +69,11 @@ if [ -z "$FILEOUT" ]; then fi mkdir "$TMP" -cd "$TMP" case "$FILEIN" in http\:\/\/*|https\:\/\/*) echo " Downloading..." + cd "$TMP" wget "$FILEIN" -O package.tar.bz2 echo " Unpacking..." tar -xjvf package.tar.bz2 @@ -85,6 +86,7 @@ case "$FILEIN" in usage fi echo " Unpacking..." + cd "$TMP" tar -xjvf "$FILEIN" ;; esac @@ -99,7 +101,7 @@ if [ -d lib/release ]; then fi if [ -d include ]; then mkdir -p $INCPATH - mv -f include/* $LIBPATH + mv -f include/* $INCPATH fi echo " Packing..." From 93f6ea1a078c184de44b8cae3cb3bbb9b089a753 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 23 Feb 2012 03:05:31 +0100 Subject: [PATCH 17/35] Pure linden boost on windows --- install.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/install.xml b/install.xml index d7ce8c54d..29b471209 100644 --- a/install.xml +++ b/install.xml @@ -200,21 +200,21 @@ md5sum 2cad51575b429be4fdadb5d63da1c739 url - https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-darwin-20110604.tar.bz2 + https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-darwin-20110604.tar.bz2
linux md5sum a2d2fff5cc5555ffd9865daedfcd0dd5 url - https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-linux-20110604.tar.bz2 + https://github.com/downloads/siana/SingularityViewer/boost-1.45.0-linux-20110604.tar.bz2 windows md5sum - 17f89b854959b4d728be832d9c8184e4 + ce5ce1050d039ef5c233c4f684437b16 url - https://github.com/downloads/NickyPerian/imprudence/boost_1_45_VC100_libs_inc_patch4073.tar.bz2 + https://bitbucket.org/Siana/singularityviewer/downloads/boost-1.45.0-windows-20120222.tar.bz2
From a632010b955af1154ef607cfd122baf31219c642 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 23 Feb 2012 15:35:50 +0100 Subject: [PATCH 18/35] Boost: target Windows XP strictly --- indra/cmake/00-Common.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 18cc4c695..87f8da720 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -70,6 +70,10 @@ if (WINDOWS) /Oy- ) + # configure win32 API for windows XP+ compatibility + set(WINVER "0x0501" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)") + add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}") + if(MSVC80 OR MSVC90 OR MSVC10) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" From 10af9d64f2c72122fd9e072a324730b57518998a Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Fri, 24 Feb 2012 03:26:06 +0100 Subject: [PATCH 19/35] One day this will be a memory stat --- indra/newview/CMakeLists.txt | 2 ++ indra/newview/app_settings/settings.xml | 11 +++++++++ indra/newview/llfloaterstats.cpp | 13 ++++++++++- indra/newview/llviewerstats.cpp | 1 + indra/newview/llviewerstats.h | 1 + indra/newview/sgmemstat.cpp | 31 +++++++++++++++++++++++++ indra/newview/sgmemstat.h | 31 +++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 indra/newview/sgmemstat.cpp create mode 100644 indra/newview/sgmemstat.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 99c5b8c38..7954b6e8d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -76,6 +76,7 @@ include_directories( ) set(viewer_SOURCE_FILES + sgmemstat.cpp sgversion.cpp llviewerobjectbackup.cpp slfloatermediafilter.cpp @@ -564,6 +565,7 @@ set(viewer_HEADER_FILES CMakeLists.txt ViewerInstall.cmake + sgmemstat.h sgversion.h llviewerobjectbackup.h slfloatermediafilter.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2b521fed4..ecd22b0ae 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4205,6 +4205,17 @@ Value -1
+ DebugStatModeMalloc + + Comment + Mode of stat in Statistics floater + Persist + 1 + Type + S32 + Value + -1 + DebugStatModeFormattedMem Comment diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index 4d8fd7099..84c637f2c 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -45,6 +45,7 @@ #include "pipeline.h" #include "llviewerobjectlist.h" #include "llviewertexturelist.h" +#include "sgmemstat.h" const S32 LL_SCROLL_BORDER = 1; @@ -99,7 +100,17 @@ void LLFloaterStats::buildStats() stat_barp->mLabelSpacing = 200.f; stat_barp->mPerSec = FALSE; stat_barp->mDisplayMean = FALSE; - + + if(SGMemStat::haveStat()) { + stat_barp = stat_viewp->addStat("Allocated memory", &(LLViewerStats::getInstance()->mMallocStat), "DebugStatModeMalloc"); + stat_barp->setUnitLabel(" MB"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 4000.f; + stat_barp->mTickSpacing = 100.f; + stat_barp->mLabelSpacing = 200.f; + stat_barp->mPerSec = FALSE; + stat_barp->mDisplayMean = FALSE; + } stat_viewp = new LLStatView("advanced stat view", "Advanced", "OpenDebugStatAdvanced", rect); addStatView(stat_viewp); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 11cb1a868..baf728781 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -213,6 +213,7 @@ LLViewerStats::LLViewerStats() : mObjectKBitStat("objectkbitstat"), mAssetKBitStat("assetkbitstat"), mTextureKBitStat("texturekbitstat"), + mMallocStat("mallocstat"), mVFSPendingOperations("vfspendingoperations"), mObjectsDrawnStat("objectsdrawnstat"), mObjectsCulledStat("objectsculledstat"), diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 7f0f2d8cf..ec91b7efd 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -59,6 +59,7 @@ public: LLStat mActualInKBitStat; // From the packet ring (when faking a bad connection) LLStat mActualOutKBitStat; // From the packet ring (when faking a bad connection) LLStat mTrianglesDrawnStat; + LLStat mMallocStat; // Simulator stats LLStat mSimTimeDilation; diff --git a/indra/newview/sgmemstat.cpp b/indra/newview/sgmemstat.cpp new file mode 100644 index 000000000..27f3cc7cb --- /dev/null +++ b/indra/newview/sgmemstat.cpp @@ -0,0 +1,31 @@ +/* Copyright (C) 2012 Siana Gearz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA */ + +#include "llviewerprecompiledheaders.h" +#include "sgmemstat.h" + +bool SGMemStat::haveStat() { + return false; +} + +F32 SGMemStat::getMalloc() { + return 0.f; +} + +U32 SGMemStat::getNumObjects() { + return 0; +} diff --git a/indra/newview/sgmemstat.h b/indra/newview/sgmemstat.h new file mode 100644 index 000000000..8a89e3b0d --- /dev/null +++ b/indra/newview/sgmemstat.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2012 Siana Gearz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA */ + +#ifndef SGMEMSTAT_H +#define SGMEMSTAT_H + +namespace SGMemStat{ + +bool haveStat(); + +F32 getMalloc(); + +U32 getNumObjects(); + +} + +#endif From 0bdf54e6d92e8eeea168df19d0848b74ee180654 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Fri, 24 Feb 2012 03:27:24 +0100 Subject: [PATCH 20/35] This fixes Copy+Wear from object --- indra/newview/llfloateropenobject.cpp | 42 ++++++++++++++++++--------- indra/newview/llinventorybridge.cpp | 21 ++++++++++++-- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 102856d6e..24f976e3c 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -157,38 +157,54 @@ void LLFloaterOpenObject::moveToInventory(bool wear) { parent_category_id = gInventory.getRootFolderID(); } - + LLCategoryCreate* cat_data = new LLCategoryCreate(object_id, wear); - + LLUUID category_id = gInventory.createNewCategory(parent_category_id, - LLFolderType::FT_NONE, - name, - callbackCreateInventoryCategory, - (void*)cat_data); + LLFolderType::FT_NONE, + name, + callbackCreateInventoryCategory, + (void*)cat_data); //If we get a null category ID, we are using a capability in createNewCategory and we will //handle the following in the callbackCreateInventoryCategory routine. if ( category_id.notNull() ) { - LLSD result; - result["folder_id"] = category_id; - //Reduce redundant code by just calling the callback. Dur. - callbackCreateInventoryCategory(result,cat_data); + delete cat_data; + + LLCatAndWear* data = new LLCatAndWear; + data->mCatID = category_id; + data->mWear = wear; + data->mFolderResponded = false; + + // Copy and/or move the items into the newly created folder. + // Ignore any "you're going to break this item" messages. + BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE, + callbackMoveInventory, + (void*)data); + if (!success) + { + delete data; + data = NULL; + + LLNotificationsUtil::add("OpenObjectCannotCopy"); + } } } + // static void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLSD& result, void* data) { LLCategoryCreate* cat_data = (LLCategoryCreate*)data; - + LLUUID category_id = result["folder_id"].asUUID(); LLCatAndWear* wear_data = new LLCatAndWear; wear_data->mCatID = category_id; wear_data->mWear = cat_data->mWear; wear_data->mFolderResponded = true; - + // Copy and/or move the items into the newly created folder. // Ignore any "you're going to break this item" messages. BOOL success = move_inv_category_world_to_agent(cat_data->mObjectID, category_id, TRUE, @@ -212,7 +228,7 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data) if (result == 0) { LLInventoryView::showAgentInventory(); - LLInventoryView* view = LLInventoryView::getActiveInventory(); + LLInventoryView* view = LLInventoryView::getActiveInventory(); if (view) { view->getPanel()->setSelection(cat->mCatID, TAKE_FOCUS_NO); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 993f8b583..dab9d42c9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1806,7 +1806,7 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) // Move/copy all inventory items from the Contents folder of an in-world // object to the agent's inventory, inside a given category. -BOOL move_inv_category_world_to_agent(const LLUUID& object_id, +BOOL move_inv_category_world_to_agent(const LLUUID& object_id, const LLUUID& category_id, BOOL drop, void (*callback)(S32, void*), @@ -1833,7 +1833,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, llinfos << "Object contents not found for drop." << llendl; return FALSE; } - + BOOL accept = TRUE; BOOL is_move = FALSE; @@ -4544,7 +4544,10 @@ void LLOutfitObserver::done() class LLOutfitFetch : public LLInventoryFetchDescendentsObserver { public: - LLOutfitFetch(const LLUUID& id, bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {} + LLOutfitFetch(const LLUUID& id, bool copy_items, bool append) : + LLInventoryFetchDescendentsObserver(id), + mCopyItems(copy_items), + mAppend(append) {} ~LLOutfitFetch() {} virtual void done(); protected: @@ -4559,6 +4562,18 @@ void LLOutfitFetch::done() // happen. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; + + // Avoid passing a NULL-ref as mCompleteFolders.front() down to + // gInventory.collectDescendents() + if( mComplete.empty() ) + { + llwarns << "LLOutfitFetch::done with empty mCompleteFolders" << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } + gInventory.collectDescendents(mComplete.front(), cat_array, item_array, From 840cb29f840c61e327cbc6cbce3cefe422b37a94 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Sat, 25 Feb 2012 17:18:02 +0100 Subject: [PATCH 21/35] potential voice crash fix --- LICENSES/dbusglib.txt | 550 -------------------------------- indra/newview/llvoiceclient.cpp | 1 + 2 files changed, 1 insertion(+), 550 deletions(-) delete mode 100644 LICENSES/dbusglib.txt diff --git a/LICENSES/dbusglib.txt b/LICENSES/dbusglib.txt deleted file mode 100644 index 71b0eeed0..000000000 --- a/LICENSES/dbusglib.txt +++ /dev/null @@ -1,550 +0,0 @@ -The D-Bus glib bindings are licensed to you under your choice of the Academic -Free License version 2.1, or the GNU General Public License version 2. Both -licenses are included here. Some of the standalone binaries are under the GPL -only; in particular, but not limted to, tests/decode-gcov.c. Each source code -file is marked with the proper copyright information. - - - -The Academic Free License -v. 2.1 - -This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work: - -Licensed under the Academic Free License version 2.1 - -1) Grant of Copyright License. Licensor hereby grants You a -world-wide, royalty-free, non-exclusive, perpetual, sublicenseable -license to do the following: - -a) to reproduce the Original Work in copies; - -b) to prepare derivative works ("Derivative Works") based upon the Original Work; - -c) to distribute copies of the Original Work and Derivative Works to the public; - -d) to perform the Original Work publicly; and - -e) to display the Original Work publicly. - -2) Grant of Patent License. Licensor hereby grants You a world-wide, -royalty-free, non-exclusive, perpetual, sublicenseable license, under -patent claims owned or controlled by the Licensor that are embodied in -the Original Work as furnished by the Licensor, to make, use, sell and -offer for sale the Original Work and Derivative Works. - -3) Grant of Source Code License. The term "Source Code" means the -preferred form of the Original Work for making modifications to it and -all available documentation describing how to modify the Original -Work. Licensor hereby agrees to provide a machine-readable copy of the -Source Code of the Original Work along with each copy of the Original -Work that Licensor distributes. Licensor reserves the right to satisfy -this obligation by placing a machine-readable copy of the Source Code -in an information repository reasonably calculated to permit -inexpensive and convenient access by You for as long as Licensor -continues to distribute the Original Work, and by publishing the -address of that information repository in a notice immediately -following the copyright notice that applies to the Original Work. - -4) Exclusions From License Grant. Neither the names of Licensor, nor -the names of any contributors to the Original Work, nor any of their -trademarks or service marks, may be used to endorse or promote -products derived from this Original Work without express prior written -permission of the Licensor. Nothing in this License shall be deemed to -grant any rights to trademarks, copyrights, patents, trade secrets or -any other intellectual property of Licensor except as expressly stated -herein. No patent license is granted to make, use, sell or offer to -sell embodiments of any patent claims other than the licensed claims -defined in Section 2. No right is granted to the trademarks of -Licensor even if such marks are included in the Original Work. Nothing -in this License shall be interpreted to prohibit Licensor from -licensing under different terms from this License any Original Work -that Licensor otherwise would have a right to license. - -5) This section intentionally omitted. - -6) Attribution Rights. You must retain, in the Source Code of any -Derivative Works that You create, all copyright, patent or trademark -notices from the Source Code of the Original Work, as well as any -notices of licensing and any descriptive text identified therein as an -"Attribution Notice." You must cause the Source Code for any -Derivative Works that You create to carry a prominent Attribution -Notice reasonably calculated to inform recipients that You have -modified the Original Work. - -7) Warranty of Provenance and Disclaimer of Warranty. Licensor -warrants that the copyright in and to the Original Work and the patent -rights granted herein by Licensor are owned by the Licensor or are -sublicensed to You under the terms of this License with the permission -of the contributor(s) of those copyrights and patent rights. Except as -expressly stated in the immediately proceeding sentence, the Original -Work is provided under this License on an "AS IS" BASIS and WITHOUT -WARRANTY, either express or implied, including, without limitation, -the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL -WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential -part of this License. No license to Original Work is granted hereunder -except under this disclaimer. - -8) Limitation of Liability. Under no circumstances and under no legal -theory, whether in tort (including negligence), contract, or -otherwise, shall the Licensor be liable to any person for any direct, -indirect, special, incidental, or consequential damages of any -character arising as a result of this License or the use of the -Original Work including, without limitation, damages for loss of -goodwill, work stoppage, computer failure or malfunction, or any and -all other commercial damages or losses. This limitation of liability -shall not apply to liability for death or personal injury resulting -from Licensor's negligence to the extent applicable law prohibits such -limitation. Some jurisdictions do not allow the exclusion or -limitation of incidental or consequential damages, so this exclusion -and limitation may not apply to You. - -9) Acceptance and Termination. If You distribute copies of the -Original Work or a Derivative Work, You must make a reasonable effort -under the circumstances to obtain the express assent of recipients to -the terms of this License. Nothing else but this License (or another -written agreement between Licensor and You) grants You permission to -create Derivative Works based upon the Original Work or to exercise -any of the rights granted in Section 1 herein, and any attempt to do -so except under the terms of this License (or another written -agreement between Licensor and You) is expressly prohibited by -U.S. copyright law, the equivalent laws of other countries, and by -international treaty. Therefore, by exercising any of the rights -granted to You in Section 1 herein, You indicate Your acceptance of -this License and all of its terms and conditions. - -10) Termination for Patent Action. This License shall terminate -automatically and You may no longer exercise any of the rights granted -to You by this License as of the date You commence an action, -including a cross-claim or counterclaim, against Licensor or any -licensee alleging that the Original Work infringes a patent. This -termination provision shall not apply for an action alleging patent -infringement by combinations of the Original Work with other software -or hardware. - -11) Jurisdiction, Venue and Governing Law. Any action or suit relating -to this License may be brought only in the courts of a jurisdiction -wherein the Licensor resides or in which Licensor conducts its primary -business, and under the laws of that jurisdiction excluding its -conflict-of-law provisions. The application of the United Nations -Convention on Contracts for the International Sale of Goods is -expressly excluded. Any use of the Original Work outside the scope of -this License or after its termination shall be subject to the -requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 -et seq., the equivalent laws of other countries, and international -treaty. This section shall survive the termination of this License. - -12) Attorneys Fees. In any action to enforce the terms of this License -or seeking damages relating thereto, the prevailing party shall be -entitled to recover its costs and expenses, including, without -limitation, reasonable attorneys' fees and costs incurred in -connection with such action, including any appeal of such action. This -section shall survive the termination of this License. - -13) Miscellaneous. This License represents the complete agreement -concerning the subject matter hereof. If any provision of this License -is held to be unenforceable, such provision shall be reformed only to -the extent necessary to make it enforceable. - -14) Definition of "You" in This License. "You" throughout this -License, whether in upper or lower case, means an individual or a -legal entity exercising rights under, and complying with all of the -terms of, this License. For legal entities, "You" includes any entity -that controls, is controlled by, or is under common control with -you. For purposes of this definition, "control" means (i) the power, -direct or indirect, to cause the direction or management of such -entity, whether by contract or otherwise, or (ii) ownership of fifty -percent (50%) or more of the outstanding shares, or (iii) beneficial -ownership of such entity. - -15) Right to Use. You may use the Original Work in all ways not -otherwise restricted or conditioned by this License or by law, and -Licensor promises not to interfere with or be responsible for such -uses by You. - -This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights -reserved. Permission is hereby granted to copy and distribute this -license without modification. This license may not be modified without -the express written permission of its copyright owner. - - --- -END OF ACADEMIC FREE LICENSE. The following is intended to describe the essential -differences between the Academic Free License (AFL) version 1.0 and other -open source licenses: - -The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache -licenses in many respects but it is intended to solve a few problems with -those licenses. - -* The AFL is written so as to make it clear what software is being -licensed (by the inclusion of a statement following the copyright notice -in the software). This way, the license functions better than a template -license. The BSD, MIT and UoI/NCSA licenses apply to unidentified software. - -* The AFL contains a complete copyright grant to the software. The BSD -and Apache licenses are vague and incomplete in that respect. - -* The AFL contains a complete patent grant to the software. The BSD, MIT, -UoI/NCSA and Apache licenses rely on an implied patent license and contain -no explicit patent grant. - -* The AFL makes it clear that no trademark rights are granted to the -licensor's trademarks. The Apache license contains such a provision, but the -BSD, MIT and UoI/NCSA licenses do not. - -* The AFL includes the warranty by the licensor that it either owns the -copyright or that it is distributing the software under a license. None of -the other licenses contain that warranty. All other warranties are disclaimed, -as is the case for the other licenses. - -* The AFL is itself copyrighted (with the right granted to copy and distribute -without modification). This ensures that the owner of the copyright to the -license will control changes. The Apache license contains a copyright notice, -but the BSD, MIT and UoI/NCSA licenses do not. --- -START OF GNU GENERAL PUBLIC LICENSE --- - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 7a96fe309..0362adaf4 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1118,6 +1118,7 @@ LLVoiceClient::LLVoiceClient() mMuteMic = false; mSessionTerminateRequested = false; mRelogRequested = false; + mConnected = false; mCommandCookie = 0; mCurrentParcelLocalID = 0; mLoginRetryCount = 0; From baad415f0da61c0917ecf334580b7d5d6e524d82 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Wed, 29 Feb 2012 13:50:04 +0100 Subject: [PATCH 22/35] Correcting broken link icon, killing unused files --- indra/newview/CMakeLists.txt | 2 - indra/newview/emerald.cpp | 593 ------------------ indra/newview/emerald.h | 107 ---- indra/newview/llinventoryicon.cpp | 2 +- .../{Inv_Invalid.png => inv_invalid.png} | Bin .../{inv_link_Item.tga => inv_link_item.tga} | Bin ...em_broken.tga => inv_link_item_broken.tga} | Bin 7 files changed, 1 insertion(+), 703 deletions(-) delete mode 100644 indra/newview/emerald.cpp delete mode 100644 indra/newview/emerald.h rename indra/newview/skins/default/textures/{Inv_Invalid.png => inv_invalid.png} (100%) rename indra/newview/skins/default/textures/{inv_link_Item.tga => inv_link_item.tga} (100%) rename indra/newview/skins/default/textures/{inv_link_Item_broken.tga => inv_link_item_broken.tga} (100%) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7954b6e8d..640763df4 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -99,7 +99,6 @@ set(viewer_SOURCE_FILES ascentprefsvan.cpp dhparam.cpp dsaparam.cpp - emerald.cpp emeraldboobutils.cpp dofloaterhex.cpp dohexeditor.cpp @@ -584,7 +583,6 @@ set(viewer_HEADER_FILES ascentprefschat.h ascentprefssys.h ascentprefsvan.h - emerald.h emeraldboobutils.h dofloaterhex.h dohexeditor.h diff --git a/indra/newview/emerald.cpp b/indra/newview/emerald.cpp deleted file mode 100644 index c2a31a65f..000000000 --- a/indra/newview/emerald.cpp +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright (c)2009 Thomas Shikami -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -#include "llviewerprecompiledheaders.h" -#include "emerald.h" -#include -#include - -#include -#include -#include - -//-- Ascii85 encoder and decoder - -typedef unsigned int U32; - -static void encodeU32(unsigned int in, char *out) -{ - out[4] = char(in % 85) + char(33); - in /= 85; - out[3] = char(in % 85) + char(33); - in /= 85; - out[2] = char(in % 85) + char(33); - in /= 85; - out[1] = char(in % 85) + char(33); - in /= 85; - out[0] = char(in % 85) + char(33); -} - -static unsigned int decodeU32(const char *in) -{ - U32 out; - - out = U32(in[0] - 33); - out *= 85; - out += U32(in[1] - 33); - out *= 85; - out += U32(in[2] - 33); - out *= 85; - out += U32(in[3] - 33); - out *= 85; - out += U32(in[4] - 33); - - return out; -} - -// static -std::string EAscii85::encode(const std::vector &in) -{ - std::ostringstream out; - U32 tuple; - int count; - char block[6]; - block[5] = '\0'; - - out << "<~"; - - count = 0; - tuple = 0; - for(size_t i = 0; i < in.size(); i++) - { - tuple <<= 8; - tuple += in[i]; - if(++count == 4) - { - if(tuple == 0) - { - out << "z"; - } - else - { - encodeU32(tuple, block); - out << block; - } - count = 0; - } - } - - switch(count) - { - case 1: - tuple <<= 8; - tuple += 255; - // pass through - case 2: - tuple <<= 8; - tuple += 255; - // pass through - case 3: - tuple <<= 8; - tuple += 255; - } - - encodeU32(tuple, block); - - switch(count) - { - case 1: - block[2] = '\0'; - break; - case 2: - block[3] = '\0'; - break; - case 3: - block[4] = '\0'; - break; - } - - if(count > 0) - out << block; - - out << "~>"; - - return out.str(); -} - -// static -std::vector EAscii85::decode(const std::string &in) -{ - std::vector out; - size_t len; - int count = 0; - char block[6]; - block[5] = '\0'; - U32 tuple; - - // approximate length - len = in.length() / 5 * 4; - - out.clear(); - - if(in.length() < 4) return out; - - std::string::const_iterator i = in.begin(); - - if(*i != '<') return out; - i++; - if(*i != '~') return out; - i++; - - out.reserve(len); - - for(; i != in.end(); i++) - { - char c = *i; - - if(c >= '!' && c < 'v') - { - block[count++] = c; - } - - switch(c) - { - case 'z': - if(count == 1) - { - for(count = 0; count < 4; count++) - out.push_back(0); - count = 0; - } - break; - case '~': - if(count > 1) - { - switch(count) - { - case 2: - block[2] = 'u'; - case 3: - block[3] = 'u'; - case 4: - block[4] = 'u'; - } - tuple = decodeU32(block); - for(;count > 1; count--) - { - out.push_back(char(tuple >> 24)); - tuple <<= 8; - } - count = 0; - } - } - - if(count == 5) - { - tuple = decodeU32(block); - for(count = 0; count < 4; count++) - { - out.push_back(char(tuple >> 24)); - tuple <<= 8; - } - count = 0; - } - } - - return out; -} - -//-- AES wrapper - -class EAESEncrypt::EncryptImpl { -public: - EncryptImpl(const unsigned char *key, const unsigned char *iv); - ~EncryptImpl(); - - std::vector encrypt(const std::string &in); - - EVP_CIPHER_CTX ctx; -}; - -EAESEncrypt::EAESEncrypt(const unsigned char *key, const unsigned char *iv) -{ - mEncryptImpl = new EAESEncrypt::EncryptImpl(key, iv); -} - -EAESEncrypt::EAESEncrypt(const std::vector &key, const std::vector &iv) -{ - mEncryptImpl = new EAESEncrypt::EncryptImpl(&key[0], &iv[0]); -} - -EAESEncrypt::~EAESEncrypt() -{ - delete mEncryptImpl; -} - -std::vector EAESEncrypt::encrypt(const std::string &in) -{ - return mEncryptImpl->encrypt(in); -} - -EAESEncrypt::EncryptImpl::EncryptImpl(const unsigned char *key, const unsigned char *iv) -{ - EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); -} - -EAESEncrypt::EncryptImpl::~EncryptImpl() -{ - EVP_CIPHER_CTX_cleanup(&ctx); -} - -std::vector EAESEncrypt::EncryptImpl::encrypt(const std::string &in) -{ - std::vector out; - int outlen; - int tmplen; - - out.resize(in.length() + 32); - - EVP_EncryptUpdate(&ctx, &out[0], &outlen, reinterpret_cast(in.c_str()), in.length()); - EVP_EncryptFinal_ex(&ctx, &out[outlen], &tmplen); - - out.resize(outlen + tmplen); - - return out; -} - -class EAESDecrypt::DecryptImpl { -public: - DecryptImpl(const unsigned char *key, const unsigned char *iv); - ~DecryptImpl(); - - std::string decrypt(const std::vector &in); - - EVP_CIPHER_CTX ctx; -}; - -EAESDecrypt::EAESDecrypt(const unsigned char *key, const unsigned char *iv) -{ - mDecryptImpl = new EAESDecrypt::DecryptImpl(key, iv); -} - -EAESDecrypt::EAESDecrypt(const std::vector &key, const std::vector &iv) -{ - mDecryptImpl = new EAESDecrypt::DecryptImpl(&key[0], &iv[0]); -} - -EAESDecrypt::~EAESDecrypt() -{ - delete mDecryptImpl; -} - -EAESDecrypt::DecryptImpl::DecryptImpl(const unsigned char *key, const unsigned char *iv) -{ - EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv); -} - -EAESDecrypt::DecryptImpl::~DecryptImpl() -{ - EVP_CIPHER_CTX_cleanup(&ctx); -} - -std::string EAESDecrypt::decrypt(const std::vector &in) -{ - return mDecryptImpl->decrypt(in); -} - -std::string EAESDecrypt::DecryptImpl::decrypt(const std::vector &in) -{ - std::vector out; - int outlen; - int tmplen; - - if(in.size() == 0) return ""; - - out.resize(in.size() + 32); - - EVP_DecryptUpdate(&ctx, &out[0], &outlen, &in[0], in.size()); - EVP_DecryptFinal_ex(&ctx, &out[outlen], &tmplen); - - out.resize(outlen + tmplen); - - if(out.empty()) - return ""; - - return std::string(reinterpret_cast(&out[0]), out.size()); -} - -EGenKey::EGenKey(const std::string &password, const unsigned char *salt) -{ - EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, - reinterpret_cast(password.c_str()), password.length(), - 1000, mKey, mIv); -} - -EGenKey::~EGenKey() -{ - memset(mKey, 0, 16); - memset(mIv, 0, 16); -} - -DH *get_dh2048(); - -class BigNum -{ -public: - BigNum(const std::vector &bin) - { - mBN = BN_bin2bn(&(bin[0]), bin.size(), NULL); - } - - BigNum() - { - mBN = BN_new(); - } - - BigNum(const BigNum &other) - { - mBN = BN_dup(*other); - } - - BigNum(BIGNUM *bn) - { - mBN = BN_dup(bn); - } - - ~BigNum() - { - BN_clear_free(mBN); - mBN = NULL; - } - - friend BIGNUM* operator*(const BigNum&); - - BigNum& operator=(const std::vector &bin) - { - mBN = BN_bin2bn(&(bin[0]), bin.size(), mBN); - return *this; - } - - BigNum& operator=(const BigNum& other) - { - BN_copy(mBN, *other); - return *this; - } - - void to(std::vector &dest) - { - dest.resize(BN_num_bytes(mBN)); - BN_bn2bin(mBN, &(dest[0])); - } - - BIGNUM* to(BIGNUM *ret) - { - return BN_copy(ret, mBN); - } - - BIGNUM* dup() - { - return BN_dup(mBN); - } - - static BIGNUM* dup(const std::vector &bin) - { - return BN_bin2bn(&(bin[0]), bin.size(), NULL); - } - -private: - BIGNUM *mBN; -}; - -BIGNUM* operator*(const BigNum& o) { return o.mBN; } - -class EDH::DHImpl -{ -public: - DH *mDH; -}; - -EDH::EDH(const std::vector &priv_key) -{ - mDHImpl = new DHImpl(); - - mDHImpl->mDH = get_dh2048(); - mDHImpl->mDH->priv_key = BigNum::dup(priv_key); - - DH_generate_key(mDHImpl->mDH); -} - -EDH::EDH() -{ - mDHImpl = new DHImpl(); - - mDHImpl->mDH = get_dh2048(); - - DH_generate_key(mDHImpl->mDH); -} - -EDH::~EDH() -{ - if(mDHImpl) - { - if(mDHImpl->mDH) - { - mDHImpl->mDH->priv_key = NULL; - mDHImpl->mDH->pub_key = NULL; - DH_free(mDHImpl->mDH); - mDHImpl->mDH = NULL; - } - delete mDHImpl; - mDHImpl = NULL; - } -} - -void EDH::secretTo(std::vector &secret) -{ - BigNum(mDHImpl->mDH->priv_key).to(secret); -} - -void EDH::publicTo(std::vector &pub) -{ - BigNum(mDHImpl->mDH->pub_key).to(pub); -} - -std::vector EDH::computeKey(const std::vector &other_pub) -{ - std::vector temp; - BigNum pub(other_pub); - temp.resize(DH_size(mDHImpl->mDH)); - - DH_compute_key(&(temp[0]), *pub, mDHImpl->mDH); - - return temp; -} - -DSA *get_dsa2048(); - -class EDSA::DSAImpl -{ -public: - DSA *mDSA; -}; - -EDSA::EDSA() -{ - mDSAImpl = new DSAImpl(); - mDSAImpl->mDSA = get_dsa2048(); -} - -EDSA::EDSA(const std::vector &secret) -{ - mDSAImpl = new DSAImpl(); - - const unsigned char *buf = &(secret[0]); - - mDSAImpl->mDSA = d2i_DSAPrivateKey(NULL, &buf, secret.size()); -} - -std::vector EDSA::generateSecret() -{ - DSA_generate_key(mDSAImpl->mDSA); - - std::vector temp; - - int size = i2d_DSAPrivateKey(mDSAImpl->mDSA, NULL); - - temp.resize(size); - - unsigned char *buf = &(temp[0]); - - i2d_DSAPrivateKey(mDSAImpl->mDSA, &buf); - - return temp; -} - -std::vector EDSA::getPublic() -{ - std::vector temp; - - mDSAImpl->mDSA->write_params = 0; - - int size = i2d_DSAPublicKey(mDSAImpl->mDSA, NULL); - - temp.resize(size); - - unsigned char *buf = &(temp[0]); - - i2d_DSAPublicKey(mDSAImpl->mDSA, &buf); - - return temp; -} - -void EDSA::setPublic(const std::vector &pub) -{ - const unsigned char *buf = &(pub[0]); - - d2i_DSAPublicKey(&mDSAImpl->mDSA, &buf, pub.size()); -} - -bool EDSA::verify(const std::vector &dgst, const std::vector &sig) -{ - bool result = false; - - if(DSA_verify(0, &(dgst[0]), dgst.size(), &(sig[0]), sig.size(), mDSAImpl->mDSA) == 1) - { - result = true; - } - - return result; -} - -// static -bool EDSA::verify(const std::vector &dgst, const std::vector &sig, const std::vector &pub) -{ - const unsigned char *buf = &(pub[0]); - DSA *dsa; - bool result = false; - - dsa = get_dsa2048(); - - d2i_DSAPublicKey(&dsa, &buf, pub.size()); - - if(DSA_verify(0, &(dgst[0]), dgst.size(), &(sig[0]), sig.size(), dsa) == 1) - { - result = true; - } - - DSA_free(dsa); - - return result; -} - -std::vector EDSA::sign(const std::vector &dgst) -{ - std::vector sig; - unsigned int size = DSA_size(mDSAImpl->mDSA); - - sig.resize(size); - - DSA_sign(0, &(dgst[0]), dgst.size(), &(sig[0]), &size, mDSAImpl->mDSA); - - sig.resize(size); - - return sig; -} - -EDSA::~EDSA() -{ - delete mDSAImpl; - mDSAImpl = NULL; -} diff --git a/indra/newview/emerald.h b/indra/newview/emerald.h deleted file mode 100644 index a4d2126c6..000000000 --- a/indra/newview/emerald.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c)2009 Thomas Shikami -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -#include -#include - -class EAscii85 { -private: - EAscii85() { } -public: - static std::string encode(const std::vector &in); - static std::vector decode(const std::string &in); -}; - -class EAESEncrypt { -public: - EAESEncrypt(const unsigned char *key, const unsigned char *iv); - EAESEncrypt(const std::vector &key, const std::vector &iv); - ~EAESEncrypt(); - - std::vector encrypt(const std::string &in); - -private: - EAESEncrypt(const EAESEncrypt&) {} - - class EncryptImpl; - - EncryptImpl *mEncryptImpl; -}; - -class EAESDecrypt { -public: - EAESDecrypt(const unsigned char *key, const unsigned char *iv); - EAESDecrypt(const std::vector &key, const std::vector &iv); - ~EAESDecrypt(); - - std::string decrypt(const std::vector &in); - -private: - EAESDecrypt(const EAESDecrypt&) {} - class DecryptImpl; - - DecryptImpl *mDecryptImpl; -}; - -class EGenKey { -public: - EGenKey(const std::string &password, const unsigned char *salt = 0); - ~EGenKey(); - - const unsigned char *key() const { return mKey; } - const unsigned char *iv() const { return mIv; } - -private: - unsigned char mKey[16]; - unsigned char mIv[16]; -}; - -class EDH { -public: - EDH(const std::vector &secret); - EDH(); - ~EDH(); - - void secretTo(std::vector &secret); - void publicTo(std::vector &pub); - std::vector computeKey(const std::vector &other_pub); - -private: - EDH(const EDH&) {} - - class DHImpl; - - DHImpl *mDHImpl; -}; - -class EDSA { -public: - EDSA(const std::vector &secret); - EDSA(); - ~EDSA(); - - std::vector getPublic(); - void setPublic(const std::vector &pub); - std::vector generateSecret(); - static bool verify(const std::vector &dgst, const std::vector &sig, const std::vector &pub); - bool verify(const std::vector &dgst, const std::vector &sig); - std::vector sign(const std::vector &dgst); - -private: - EDSA(const EDSA&) {} - - class DSAImpl; - - DSAImpl *mDSAImpl; -}; diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index aefc0b4ab..9d55023d6 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -88,7 +88,7 @@ LLIconDictionary::LLIconDictionary() addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("inv_link_folder.tga")); addEntry(LLInventoryIcon::ICONNAME_MESH, new IconEntry("inv_item_mesh.tga")); - addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid.png")); + addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("inv_invalid.png")); addEntry(LLInventoryIcon::ICONNAME_NONE, new IconEntry("NONE")); } diff --git a/indra/newview/skins/default/textures/Inv_Invalid.png b/indra/newview/skins/default/textures/inv_invalid.png similarity index 100% rename from indra/newview/skins/default/textures/Inv_Invalid.png rename to indra/newview/skins/default/textures/inv_invalid.png diff --git a/indra/newview/skins/default/textures/inv_link_Item.tga b/indra/newview/skins/default/textures/inv_link_item.tga similarity index 100% rename from indra/newview/skins/default/textures/inv_link_Item.tga rename to indra/newview/skins/default/textures/inv_link_item.tga diff --git a/indra/newview/skins/default/textures/inv_link_Item_broken.tga b/indra/newview/skins/default/textures/inv_link_item_broken.tga similarity index 100% rename from indra/newview/skins/default/textures/inv_link_Item_broken.tga rename to indra/newview/skins/default/textures/inv_link_item_broken.tga From a7d70878b7c23467cd04548690e4a84584dd0fe8 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Wed, 29 Feb 2012 16:03:11 +0100 Subject: [PATCH 23/35] Log threadcount together with memory --- indra/llcommon/llthread.cpp | 5 ++++- indra/llcommon/llthread.h | 4 +++- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llviewerdisplay.cpp | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 8ae458c1c..85d88f01d 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -67,6 +67,7 @@ U32 ll_thread_local local_thread_ID = 0; #endif U32 LLThread::sIDIter = 0; +LLAtomicS32 LLThread::sCount = 0; LL_COMMON_API void assert_main_thread() { @@ -125,6 +126,8 @@ LLThread::LLThread(std::string const& name) : mThreadLocalData(NULL) { mID = ++sIDIter; + sCount++; + llassert(sCount <= 50); mRunCondition = new LLCondition; } @@ -175,7 +178,7 @@ void LLThread::shutdown() } mAPRThreadp = NULL; } - + sCount--; delete mRunCondition; mRunCondition = 0; } diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index f0e4f39f5..9ab7829c6 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -73,6 +73,7 @@ class LL_COMMON_API LLThread { private: static U32 sIDIter; + static LLAtomicS32 sCount; public: typedef enum e_thread_status @@ -90,6 +91,7 @@ public: bool isStopped() const { return (STOPPED == mStatus); } static U32 currentID(); // Return ID of current thread + static S32 getCount() { return sCount; } static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. public: @@ -129,7 +131,7 @@ protected: apr_thread_t *mAPRThreadp; volatile EThreadStatus mStatus; U32 mID; - + friend void LLThreadLocalData::create(LLThread* threadp); LLThreadLocalData* mThreadLocalData; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ecd22b0ae..f9b809665 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8156,7 +8156,7 @@ Type F32 Value - 600.0 + 30.0 MemoryPrivatePoolEnabled diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index a78f98f2d..949235013 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -228,6 +228,7 @@ void display_stats() gMemoryAllocated = LLMemory::getCurrentRSS(); U32 memory = (U32)(gMemoryAllocated / (1024*1024)); llinfos << llformat("MEMORY: %d MB", memory) << llendl; + llinfos << "THREADS: "<< LLThread::getCount() << llendl; LLMemory::logMemoryInfo(TRUE) ; gRecentMemoryTime.reset(); } From ecc396219d69a1c0a51b32d9b577451a68fa2acf Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Wed, 29 Feb 2012 17:22:24 +0100 Subject: [PATCH 24/35] I can't shake the feeling that timesliced cache clearing is botched. Better safe, byebye. --- indra/newview/lltexturecache.cpp | 183 ++++++++----------------------- indra/newview/lltexturecache.h | 43 +++----- 2 files changed, 61 insertions(+), 165 deletions(-) diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index b239823af..60ced2e4d 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -2,31 +2,25 @@ * @file lltexturecache.cpp * @brief Object which handles local texture caching * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. * - * 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 + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -251,9 +245,9 @@ bool LLTextureCacheLocalFileWorker::doRead() } } #else - if (!mDataSize || mDataSize > local_size/* - mOffset*/) + if (!mDataSize || mDataSize > local_size - mOffset) { - mDataSize = local_size/* - mOffset*/; + mDataSize = local_size - mOffset; } mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); @@ -333,6 +327,7 @@ bool LLTextureCacheRemoteWorker::doRead() // First state / stage : find out if the file is local if (mState == INIT) { +#if 0 std::string filename = mCache->getLocalFileName(mID); // Is it a JPEG2000 file? { @@ -367,20 +362,24 @@ bool LLTextureCacheRemoteWorker::doRead() } // Determine the next stage: if we found a file, then LOCAL else CACHE mState = (local_size > 0 ? LOCAL : CACHE); + + llassert_always(mState == CACHE) ; +#else + mState = CACHE; +#endif } // Second state / stage : if the file is local, load it and leave if (!done && (mState == LOCAL)) { llassert(local_size != 0); // we're assuming there is a non empty local file here... - if (!mDataSize || mDataSize > local_size/* - mOffset*/) + if (!mDataSize || mDataSize > local_size - mOffset) { - mDataSize = local_size/* - mOffset*/; + mDataSize = local_size - mOffset; } // Allocate read buffer mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); - S32 bytes_read = LLAPRFile::readEx(local_filename, - mReadData, mOffset, mDataSize); + S32 bytes_read = LLAPRFile::readEx(local_filename, mReadData, mOffset, mDataSize); if (bytes_read != mDataSize) { llwarns << "Error reading file from local cache: " << local_filename @@ -513,19 +512,9 @@ bool LLTextureCacheRemoteWorker::doRead() } else { - if (mImageSize > TEXTURE_CACHE_ENTRY_SIZE) - { - LL_DEBUGS("TextureCache") << "LLTextureCacheWorker: no body for texture: " << mID << LL_ENDL; - FREE_MEM(LLImageBase::getPrivatePool(), mReadData); - mReadData = NULL; - mDataSize = -1; // failed - done = true; - } - else - { // No body, we're done. mDataSize = llmax(TEXTURE_CACHE_ENTRY_SIZE - mOffset, 0); - } + lldebugs << "No body file for: " << filename << llendl; } // Nothing else to do at that point... done = true; @@ -759,7 +748,6 @@ LLTextureCache::~LLTextureCache() { clearDeleteList(); writeUpdatedEntries(); - purgeTextureFilesTimeSliced(true); // VWR-3878 - NB - force-flush all pending file deletes } ////////////////////////////////////////////////////////////////////////////// @@ -1427,21 +1415,22 @@ void LLTextureCache::readHeaderCache() } } } - if (num_entries - empty_entries > sCacheMaxEntries) + if (num_entries > sCacheMaxEntries) { // Special case: cache size was reduced, need to remove entries // Note: After we prune entries, we will call this again and create the LRU U32 entries_to_purge = (num_entries - empty_entries) - sCacheMaxEntries; llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; - // We can exit the following loop with the given condition, since if we'd reach the end of the lru set we'd have: - // purge_list.size() = lru.size() = num_entries - empty_entries = entries_to_purge + sCacheMaxEntries >= entries_to_purge - // So, it's certain that iter will never reach lru.end() first. - std::set::iterator iter = lru.begin(); - while (purge_list.size() < entries_to_purge) + if (entries_to_purge > 0) + { + for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) { purge_list.insert(iter->second); - ++iter; + if (purge_list.size() >= entries_to_purge) + break; } + } + llassert_always(purge_list.size() >= entries_to_purge); } else { @@ -1555,18 +1544,11 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) void LLTextureCache::purgeTextures(bool validate) { - mDoPurge = FALSE; - if (mReadOnly) { return; } - if (!validate && mTexturesSizeTotal <= sCacheMaxTexturesSize) - { - return; - } - if (!mThreaded) { // *FIX:Mani - watchdog off. @@ -1582,15 +1564,12 @@ void LLTextureCache::purgeTextures(bool validate) U32 num_entries = openAndReadEntries(entries); if (!num_entries) { - LLAppViewer::instance()->resumeMainloopTimeout(); return; // nothing to purge } - LL_INFOS("TextureCache") << "TEXTURE CACHE: Purging." << LL_ENDL; - // Use mTexturesSizeMap to collect UUIDs of textures with bodies typedef std::set > time_idx_set_t; - time_idx_set_t time_idx_set; + std::set > time_idx_set; for (size_map_t::iterator iter1 = mTexturesSizeMap.begin(); iter1 != mTexturesSizeMap.end(); ++iter1) { @@ -1606,9 +1585,6 @@ void LLTextureCache::purgeTextures(bool validate) else { llerrs << "mTexturesSizeMap / mHeaderIDMap corrupted." << llendl ; - //clearCorruptedCache(); - //LLAppViewer::instance()->resumeMainloopTimeout(); - //return; } } } @@ -1661,8 +1637,7 @@ void LLTextureCache::purgeTextures(bool validate) { purge_count++; LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; - mFilesToDelete.insert(std::make_pair(entries[idx].mID, filename)); - removeEntry(idx, entries[idx], filename, false); // remove the entry but not the file + removeEntry(idx, entries[idx], filename) ; cache_size -= entries[idx].mBodySize; } } @@ -1674,80 +1649,11 @@ void LLTextureCache::purgeTextures(bool validate) // *FIX:Mani - watchdog back on. LLAppViewer::instance()->resumeMainloopTimeout(); - mSlicedPurgeTimer.reset(); - LL_INFOS("TextureCache") << "TEXTURE CACHE:" << " PURGED: " << purge_count << " ENTRIES: " << num_entries - << " CACHE SIZE: " << mTexturesSizeTotal / (1024 * 1024) << " MB" + << " CACHE SIZE: " << mTexturesSizeTotal / 1024*1024 << " MB" << llendl; - -} - -void LLTextureCache::purgeTextureFilesTimeSliced(bool force) -{ - const F32 delay_between_passes = 2.0f; // seconds - const F32 max_time_per_pass = 0.1f; // seconds - - if (!force && mSlicedPurgeTimer.getElapsedTimeF32() <= delay_between_passes) - { - return; - } - - if (!mFilesToDelete.empty()) - { - LL_INFOS("TextureCache") << "time sliced purging with " << mFilesToDelete.size() - << " files scheduled for deletion" << LL_ENDL; - - LLMutexLock lock(&mHeaderMutex); - mSlicedPurgeTimer.reset(); - U32 purged = 0; - std::string filename; - - for (LLTextureCache::purge_map_t::iterator iter = mFilesToDelete.begin(); iter != mFilesToDelete.end(); ) - { - LLTextureCache::purge_map_t::iterator curiter = iter++; - // Only remove files for textures that have not been cached again - // since we selected them for removal ! - if (mHeaderIDMap.find(curiter->first) == mHeaderIDMap.end()) - { - filename = curiter->second; - if(LLAPRFile::isExist(filename)) - LLAPRFile::remove(filename); - } - else - { - LL_DEBUGS("TextureCache") << curiter->second - << " selected for removal, but texture cached again since !" - << LL_ENDL; - } - mFilesToDelete.erase(curiter); - purged++; - - if (!force && mSlicedPurgeTimer.getElapsedTimeF32() > max_time_per_pass) - { - break; - } - } - - if (mFilesToDelete.empty()) - { - LL_INFOS("TextureCache") << "time sliced purge finished with " << purged - << " files deleted in " - << mSlicedPurgeTimer.getElapsedTimeF32() - << "s" << LL_ENDL; - } - else - { - LL_INFOS("TextureCache") << "time sliced purge: " << purged - << " files deleted in " - << mSlicedPurgeTimer.getElapsedTimeF32() - << "s (" << mFilesToDelete.size() - << " files left for next pass)" << LL_ENDL; - } - - mSlicedPurgeTimer.reset(); - } } ////////////////////////////////////////////////////////////////////////////// @@ -1888,11 +1794,12 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio } if (mDoPurge) { + // NOTE: This may cause an occasional hiccup, + // but it really needs to be done on the control thread + // (i.e. here) purgeTextures(false); + mDoPurge = FALSE; } - - purgeTextureFilesTimeSliced(); // VWR-3878 - NB - purge textures from cache in a non-hiccup-way - LLMutexLock lock(&mWorkersMutex); LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, data, datasize, 0, @@ -1951,7 +1858,7 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id) } //called after mHeaderMutex is locked. -void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename, bool remove_file) +void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) { bool file_maybe_exists = true; // Always attempt to remove when idx is invalid. @@ -1969,16 +1876,16 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename, b } } - mTexturesSizeTotal -= entry.mBodySize; entry.mImageSize = -1; entry.mBodySize = 0; mHeaderIDMap.erase(entry.mID); mTexturesSizeMap.erase(entry.mID); + mTexturesSizeTotal -= entry.mBodySize; mFreeList.insert(idx); } - if (remove_file && file_maybe_exists) + if (file_maybe_exists) { LLAPRFile::remove(filename); } diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 54f52df6a..991d8598b 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -2,31 +2,25 @@ * @file lltexturecache.h * @brief Object for managing texture cachees. * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. * - * 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 + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -154,7 +148,6 @@ private: void clearCorruptedCache(); void purgeAllTextures(bool purge_directories); void purgeTextures(bool validate); - void purgeTextureFilesTimeSliced(bool force = false); LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset); void closeHeaderEntriesFile(); void readEntriesHeader(); @@ -166,7 +159,7 @@ private: void writeEntriesAndClose(const std::vector& entries); void readEntryFromHeaderImmediately(S32& idx, Entry& entry) ; void writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool write_header = false) ; - void removeEntry(S32 idx, Entry& entry, std::string& filename, bool remove_file = true); + void removeEntry(S32 idx, Entry& entry, std::string& filename); void removeCachedTexture(const LLUUID& id) ; S32 getHeaderCacheEntry(const LLUUID& id, Entry& entry); S32 setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize); @@ -192,10 +185,6 @@ private: typedef std::vector, bool> > responder_list_t; responder_list_t mCompletedList; - typedef std::map purge_map_t; - purge_map_t mFilesToDelete; - LLTimer mSlicedPurgeTimer; - BOOL mReadOnly; // HEADERS (Include first mip) From ab26e1008fafa4ac2e12f9d4cf526717d2c0f6aa Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Wed, 29 Feb 2012 19:05:19 +0100 Subject: [PATCH 25/35] RLVa crash fix, thx Kitty! --- indra/newview/rlvcommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index 5943f4af8..1fe03bb54 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -467,7 +467,7 @@ bool RlvUtil::sendChatReply(S32 nChannel, const std::string& strUTF8Text) gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlockFast(_PREHASH_ChatData); - gMessageSystem->addStringFast(_PREHASH_Message, strUTF8Text); + gMessageSystem->addStringFast(_PREHASH_Message, utf8str_truncate(strUTF8Text, MAX_MSG_STR_LEN)); gMessageSystem->addU8Fast(_PREHASH_Type, CHAT_TYPE_SHOUT); gMessageSystem->addS32("Channel", nChannel); gAgent.sendReliableMessage(); From 251b0fa5c07487d416400dfea72816d14fb6641a Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 1 Mar 2012 13:49:47 +0100 Subject: [PATCH 26/35] Memory consumption in statistics floater --- indra/newview/llfloaterstats.cpp | 6 +-- indra/newview/llviewerdisplay.cpp | 2 + indra/newview/llviewerstats.cpp | 12 ++++++ indra/newview/sgmemstat.cpp | 68 +++++++++++++++++++++++++++++-- indra/newview/sgmemstat.h | 2 + 5 files changed, 84 insertions(+), 6 deletions(-) diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index 84c637f2c..fa71cfb13 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -105,9 +105,9 @@ void LLFloaterStats::buildStats() stat_barp = stat_viewp->addStat("Allocated memory", &(LLViewerStats::getInstance()->mMallocStat), "DebugStatModeMalloc"); stat_barp->setUnitLabel(" MB"); stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = 4000.f; - stat_barp->mTickSpacing = 100.f; - stat_barp->mLabelSpacing = 200.f; + stat_barp->mMaxBar = 2048.f; + stat_barp->mTickSpacing = 128.f; + stat_barp->mLabelSpacing = 512.f; stat_barp->mPerSec = FALSE; stat_barp->mDisplayMean = FALSE; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 949235013..bf7d50e9f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -83,6 +83,7 @@ #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llpostprocess.h" +#include "sgmemstat.h" // [RLVa:KB] #include "rlvhandler.h" @@ -229,6 +230,7 @@ void display_stats() U32 memory = (U32)(gMemoryAllocated / (1024*1024)); llinfos << llformat("MEMORY: %d MB", memory) << llendl; llinfos << "THREADS: "<< LLThread::getCount() << llendl; + llinfos << "MALLOC: " << SGMemStat::getPrintableStat() <= mem_stats_freq) + { + LLViewerStats::getInstance()->mMallocStat.addValue(SGMemStat::getMalloc()/1024.f/1024.f); + mem_stats_timer.reset(); + } + } + + #if LL_LCD_COMPILE bool LCDenabled = gLcdScreen->Enabled(); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, LCDenabled); diff --git a/indra/newview/sgmemstat.cpp b/indra/newview/sgmemstat.cpp index 27f3cc7cb..0fbe006f6 100644 --- a/indra/newview/sgmemstat.cpp +++ b/indra/newview/sgmemstat.cpp @@ -18,14 +18,76 @@ #include "llviewerprecompiledheaders.h" #include "sgmemstat.h" +#if 0 bool SGMemStat::haveStat() { - return false; + return false; } F32 SGMemStat::getMalloc() { - return 0.f; + return 0.f; } U32 SGMemStat::getNumObjects() { - return 0; + return 0; } + +std::string SGMemStat::getPrintableStat() { + return std::string(); +} + +#else + +extern "C" { + typedef void (*MallocExtension_GetStats_t)(char* buffer, int buffer_length); + typedef int (*MallocExtension_GetNumericProperty_t)(const char* property, size_t* value); + //typedef int (*MallocExtension_SetNumericProperty_t)(const char* property, size_t value); +} + +static MallocExtension_GetNumericProperty_t MallocExtension_GetNumericProperty = 0; +static MallocExtension_GetStats_t MallocExtension_GetStats = 0; + +static void initialize() { + static bool initialized = false; + if (!initialized) { + apr_dso_handle_t* hprog;// = (apr_dso_handle_t*)dlopen(0,0); + LLAPRPool pool; + pool.create(); + apr_dso_load(&hprog, 0, pool()); + apr_dso_sym((apr_dso_handle_sym_t*)&MallocExtension_GetNumericProperty, + hprog, "MallocExtension_GetNumericProperty"); + apr_dso_sym((apr_dso_handle_sym_t*)&MallocExtension_GetStats, + hprog, "MallocExtension_GetStats"); + initialized = true; + } +} + +bool SGMemStat::haveStat() { + initialize(); + return MallocExtension_GetNumericProperty; +} + +F32 SGMemStat::getMalloc() { + if(MallocExtension_GetNumericProperty) { + size_t value; + MallocExtension_GetNumericProperty("generic.current_allocated_bytes", &value); + return value; + } + else return 0.0f; +} + +U32 SGMemStat::getNumObjects() { + return 0; +} + +std::string SGMemStat::getPrintableStat() { + initialize(); + if (MallocExtension_GetStats) { + char buffer[4096]; + buffer[4095] = 0; + MallocExtension_GetStats(buffer, 4095); + return std::string(buffer); + } + else return std::string(); +} + +#endif diff --git a/indra/newview/sgmemstat.h b/indra/newview/sgmemstat.h index 8a89e3b0d..1768f66ef 100644 --- a/indra/newview/sgmemstat.h +++ b/indra/newview/sgmemstat.h @@ -26,6 +26,8 @@ F32 getMalloc(); U32 getNumObjects(); +std::string getPrintableStat(); + } #endif From 5f7f7b7d61f428d4071a81c6cdf36f45a530804c Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Thu, 1 Mar 2012 23:38:48 +0100 Subject: [PATCH 27/35] Unsegfault memory tracker on Windows --- indra/newview/sgmemstat.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/indra/newview/sgmemstat.cpp b/indra/newview/sgmemstat.cpp index 0fbe006f6..d4e22a882 100644 --- a/indra/newview/sgmemstat.cpp +++ b/indra/newview/sgmemstat.cpp @@ -18,7 +18,7 @@ #include "llviewerprecompiledheaders.h" #include "sgmemstat.h" -#if 0 +#if (!LL_WINDOWS && !LL_LINUX) bool SGMemStat::haveStat() { return false; } @@ -49,10 +49,14 @@ static MallocExtension_GetStats_t MallocExtension_GetStats = 0; static void initialize() { static bool initialized = false; if (!initialized) { - apr_dso_handle_t* hprog;// = (apr_dso_handle_t*)dlopen(0,0); + apr_dso_handle_t* hprog = 0; LLAPRPool pool; pool.create(); +#if LL_WINDOWS + apr_dso_load(&hprog, "libtcmalloc_minimal.dll", pool()); +#else apr_dso_load(&hprog, 0, pool()); +#endif apr_dso_sym((apr_dso_handle_sym_t*)&MallocExtension_GetNumericProperty, hprog, "MallocExtension_GetNumericProperty"); apr_dso_sym((apr_dso_handle_sym_t*)&MallocExtension_GetStats, From 0a11f099187c694cff41d7be5278dd17d937b502 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Sun, 4 Mar 2012 09:39:28 +0100 Subject: [PATCH 28/35] Tiny fixies from Phoenix --- indra/newview/llfloateravatarlist.cpp | 2 +- indra/newview/llwlanimator.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 747a6a329..790ba6cec 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -704,7 +704,7 @@ void LLFloaterAvatarList::refreshAvatarList() LLVector3d delta = position - mypos; F32 distance = (F32)delta.magVec(); - if (position.mdV[VZ] == 0.0) + if (position.mdV[VZ] == 0.f || position.mdV[VZ] == 1020.f) { UnknownAltitude = true; distance = 9000.0; diff --git a/indra/newview/llwlanimator.cpp b/indra/newview/llwlanimator.cpp index e0aa84806..953898fe6 100644 --- a/indra/newview/llwlanimator.cpp +++ b/indra/newview/llwlanimator.cpp @@ -124,6 +124,7 @@ void LLWLAnimator::update(LLWLParamSet& curParams) // at the end of the interp cycle, force the end settings to get applied curParams.setAll(mInterpEndWL->getAll()); } + LLWaterParamManager::getInstance()->mCurParams.setAll(mInterpEndWater->getAll()); mIsInterpolating = false; mIsInterpolatingSky = false; return; From b67fa864ff8de572b6d24103218073edddbff487 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 5 Mar 2012 18:18:37 +0100 Subject: [PATCH 29/35] First shot at fixing font fallback --- indra/llrender/llfont.cpp | 2 + indra/llrender/llfontregistry.cpp | 9 +- indra/llwindow/llwindowsdl.cpp | 4 +- indra/newview/app_settings/settings.xml | 121 ------------------------ 4 files changed, 11 insertions(+), 125 deletions(-) diff --git a/indra/llrender/llfont.cpp b/indra/llrender/llfont.cpp index 69daf389c..fecdafe45 100644 --- a/indra/llrender/llfont.cpp +++ b/indra/llrender/llfont.cpp @@ -192,6 +192,8 @@ BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F FT_Done_Face(mFTFace); mFTFace = NULL; } + + llinfos << "Loading font file: " << filename << llendl; int error; diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 0e92afeb4..aaa5b421b 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -384,9 +384,13 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) // This may not be the best solution, but it at least prevents a crash. if (it != mFontMap.end() && it->second != NULL) { - llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; + if (it->second != NULL) { + llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; - return it->second; + return it->second; + } else { + llwarns << "Failed to find font" << llendl; + } //Haven't plugged free-type in yet. // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor /*LLFontGL *font = new LLFontGL; @@ -408,6 +412,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) file_names.insert(file_names.end(), match_default_desc->getFileNames().begin(), match_default_desc->getFileNames().end()); + llinfos << "Found matching fallback fonts: " << match_default_desc->getFileNames().size() << llendl; } // Add ultimate fallback list - generated dynamically on linux, diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index c363b8ae9..abaf4e826 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2564,7 +2564,7 @@ std::vector LLWindowSDL::getDynamicFallbackFontList() // Use libfontconfig to find us a nice ordered list of fallback fonts // specific to this system. std::string final_fallback("/usr/share/fonts/truetype/kochi/kochi-gothic.ttf"); - const int max_font_count_cutoff = 40; // fonts are expensive in the current system, don't enumerate an arbitrary number of them + const int max_font_count_cutoff = 100; // fonts are expensive in the current system, don't enumerate an arbitrary number of them // Our 'ideal' font properties which define the sorting results. // slant=0 means Roman, index=0 means the first face in a font file // (the one we actually use), weight=80 means medium weight, @@ -2654,7 +2654,7 @@ std::vector LLWindowSDL::getDynamicFallbackFontList() } llinfos << "Using " << rtns.size() << "/" << found_font_count << " system fonts." << llendl; - rtns.push_back(final_fallback); + //rtns.push_back(final_fallback); return rtns; } diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f9b809665..1d5539f10 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6654,72 +6654,6 @@ Value 0.5 - FontMonospace - - Comment - Name of monospace font that definitely exists (Truetype file name) - Persist - 0 - Type - String - Value - DejaVuSansMono.ttf - - FontSansSerif - - Comment - Name of primary sans-serif font that definitely exists (Truetype file name) - Persist - 0 - Type - String - Value - DroidSans.ttf - - FontSansSerifBundledFallback - - Comment - Name of secondary sans-serif font that definitely exists (Truetype file name) - Persist - 0 - Type - String - Value - DejaVuSansCondensed.ttf - - FontSansSerifBold - - Comment - Name of bold font (Truetype file name) - Persist - 0 - Type - String - Value - DroidSans-Bold.ttf - - FontSansSerifFallback - - Comment - Name of sans-serif font (Truetype file name) - Persist - 0 - Type - String - Value - - - FontSansSerifFallbackScale - - Comment - Scale of fallback font relative to huge font (fraction of huge font size) - Persist - 1 - Type - F32 - Value - 1.00 - FontScreenDPI Comment @@ -6731,61 +6665,6 @@ Value 96.0 - FontSizeHuge - - Comment - Size of huge font (points, or 1/72 of an inch) - Persist - 1 - Type - F32 - Value - 14.0 - - FontSizeLarge - - Comment - Size of large font (points, or 1/72 of an inch) - Persist - 1 - Type - F32 - Value - 11.0 - - FontSizeMedium - - Comment - Size of medium font (points, or 1/72 of an inch) - Persist - 1 - Type - F32 - Value - 9.5 - - FontSizeMonospace - - Comment - Size of monospaced font (points, or 1/72 of an inch) - Persist - 1 - Type - F32 - Value - 9.0 - - FontSizeSmall - - Comment - Size of small font (points, or 1/72 of an inch) - Persist - 1 - Type - F32 - Value - 8.5 - ForceNotecardDragCargoPermissive Comment From edd1b4d8e7204fc8bcdf9c2417b73abce627391a Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 5 Mar 2012 18:57:24 +0100 Subject: [PATCH 30/35] Avoid crashes in skins by using proper intended filenames --- indra/newview/skins/Pony-Aquablue/colors.xml | 206 +++++++++++++++++ .../skins/Pony-Aquablue/colors_base.xml | 209 ----------------- .../{colors_base.xml => colors.xml} | 0 .../dark/{colors_base.xml => colors.xml} | 0 .../darkgred/{colors_base.xml => colors.xml} | 0 .../{colors_base.xml => colors.xml} | 0 .../emerald/{colors_base.xml => colors.xml} | 0 indra/newview/skins/gemini/colors.xml | 207 +++++++++++++++++ indra/newview/skins/gemini/colors_base.xml | 210 ----------------- .../gred/{colors_base.xml => colors.xml} | 0 indra/newview/skins/kdarknv/colors_base.xml | 202 ----------------- indra/newview/skins/kliteat/colors_base.xml | 202 ----------------- indra/newview/skins/openlife/colors_base.xml | 190 ---------------- .../skins/openlife/textures/colors.xml | 178 --------------- .../skins/openlife/textures/colors_base.xml | 190 ---------------- .../pslgreen/{colors_base.xml => colors.xml} | 0 .../pslpurple/{colors_base.xml => colors.xml} | 0 .../ruby/{colors_base.xml => colors.xml} | 0 .../sapphire/{colors_base.xml => colors.xml} | 0 indra/newview/skins/silver/colors.xml | 209 +++++++++++++++++ indra/newview/skins/silver/colors_base.xml | 212 ------------------ indra/newview/skins/white_emerald/colors.xml | 204 +++++++++++++++++ .../skins/white_emerald/colors_base.xml | 207 ----------------- .../wisdom/{colors_base.xml => colors.xml} | 0 24 files changed, 826 insertions(+), 1800 deletions(-) delete mode 100644 indra/newview/skins/Pony-Aquablue/colors_base.xml rename indra/newview/skins/Pony-Purple/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/dark/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/darkgred/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/darkorange/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/emerald/{colors_base.xml => colors.xml} (100%) delete mode 100644 indra/newview/skins/gemini/colors_base.xml rename indra/newview/skins/gred/{colors_base.xml => colors.xml} (100%) delete mode 100644 indra/newview/skins/kdarknv/colors_base.xml delete mode 100644 indra/newview/skins/kliteat/colors_base.xml delete mode 100644 indra/newview/skins/openlife/colors_base.xml delete mode 100644 indra/newview/skins/openlife/textures/colors.xml delete mode 100644 indra/newview/skins/openlife/textures/colors_base.xml rename indra/newview/skins/pslgreen/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/pslpurple/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/ruby/{colors_base.xml => colors.xml} (100%) rename indra/newview/skins/sapphire/{colors_base.xml => colors.xml} (100%) delete mode 100644 indra/newview/skins/silver/colors_base.xml delete mode 100644 indra/newview/skins/white_emerald/colors_base.xml rename indra/newview/skins/wisdom/{colors_base.xml => colors.xml} (100%) diff --git a/indra/newview/skins/Pony-Aquablue/colors.xml b/indra/newview/skins/Pony-Aquablue/colors.xml index cf9466fad..b48208f68 100644 --- a/indra/newview/skins/Pony-Aquablue/colors.xml +++ b/indra/newview/skins/Pony-Aquablue/colors.xml @@ -1,3 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Pony-Aquablue/colors_base.xml b/indra/newview/skins/Pony-Aquablue/colors_base.xml deleted file mode 100644 index b48208f68..000000000 --- a/indra/newview/skins/Pony-Aquablue/colors_base.xml +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/Pony-Purple/colors_base.xml b/indra/newview/skins/Pony-Purple/colors.xml similarity index 100% rename from indra/newview/skins/Pony-Purple/colors_base.xml rename to indra/newview/skins/Pony-Purple/colors.xml diff --git a/indra/newview/skins/dark/colors_base.xml b/indra/newview/skins/dark/colors.xml similarity index 100% rename from indra/newview/skins/dark/colors_base.xml rename to indra/newview/skins/dark/colors.xml diff --git a/indra/newview/skins/darkgred/colors_base.xml b/indra/newview/skins/darkgred/colors.xml similarity index 100% rename from indra/newview/skins/darkgred/colors_base.xml rename to indra/newview/skins/darkgred/colors.xml diff --git a/indra/newview/skins/darkorange/colors_base.xml b/indra/newview/skins/darkorange/colors.xml similarity index 100% rename from indra/newview/skins/darkorange/colors_base.xml rename to indra/newview/skins/darkorange/colors.xml diff --git a/indra/newview/skins/emerald/colors_base.xml b/indra/newview/skins/emerald/colors.xml similarity index 100% rename from indra/newview/skins/emerald/colors_base.xml rename to indra/newview/skins/emerald/colors.xml diff --git a/indra/newview/skins/gemini/colors.xml b/indra/newview/skins/gemini/colors.xml index cf9466fad..4f5c5df9a 100644 --- a/indra/newview/skins/gemini/colors.xml +++ b/indra/newview/skins/gemini/colors.xml @@ -1,3 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/gemini/colors_base.xml b/indra/newview/skins/gemini/colors_base.xml deleted file mode 100644 index 4f5c5df9a..000000000 --- a/indra/newview/skins/gemini/colors_base.xml +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/gred/colors_base.xml b/indra/newview/skins/gred/colors.xml similarity index 100% rename from indra/newview/skins/gred/colors_base.xml rename to indra/newview/skins/gred/colors.xml diff --git a/indra/newview/skins/kdarknv/colors_base.xml b/indra/newview/skins/kdarknv/colors_base.xml deleted file mode 100644 index 477527766..000000000 --- a/indra/newview/skins/kdarknv/colors_base.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/kliteat/colors_base.xml b/indra/newview/skins/kliteat/colors_base.xml deleted file mode 100644 index 477527766..000000000 --- a/indra/newview/skins/kliteat/colors_base.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/openlife/colors_base.xml b/indra/newview/skins/openlife/colors_base.xml deleted file mode 100644 index 39f897639..000000000 --- a/indra/newview/skins/openlife/colors_base.xml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/openlife/textures/colors.xml b/indra/newview/skins/openlife/textures/colors.xml deleted file mode 100644 index c7575e9dd..000000000 --- a/indra/newview/skins/openlife/textures/colors.xml +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/indra/newview/skins/openlife/textures/colors_base.xml b/indra/newview/skins/openlife/textures/colors_base.xml deleted file mode 100644 index 39f897639..000000000 --- a/indra/newview/skins/openlife/textures/colors_base.xml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/pslgreen/colors_base.xml b/indra/newview/skins/pslgreen/colors.xml similarity index 100% rename from indra/newview/skins/pslgreen/colors_base.xml rename to indra/newview/skins/pslgreen/colors.xml diff --git a/indra/newview/skins/pslpurple/colors_base.xml b/indra/newview/skins/pslpurple/colors.xml similarity index 100% rename from indra/newview/skins/pslpurple/colors_base.xml rename to indra/newview/skins/pslpurple/colors.xml diff --git a/indra/newview/skins/ruby/colors_base.xml b/indra/newview/skins/ruby/colors.xml similarity index 100% rename from indra/newview/skins/ruby/colors_base.xml rename to indra/newview/skins/ruby/colors.xml diff --git a/indra/newview/skins/sapphire/colors_base.xml b/indra/newview/skins/sapphire/colors.xml similarity index 100% rename from indra/newview/skins/sapphire/colors_base.xml rename to indra/newview/skins/sapphire/colors.xml diff --git a/indra/newview/skins/silver/colors.xml b/indra/newview/skins/silver/colors.xml index cf9466fad..7ae59a490 100644 --- a/indra/newview/skins/silver/colors.xml +++ b/indra/newview/skins/silver/colors.xml @@ -1,3 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/silver/colors_base.xml b/indra/newview/skins/silver/colors_base.xml deleted file mode 100644 index 7ae59a490..000000000 --- a/indra/newview/skins/silver/colors_base.xml +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/white_emerald/colors.xml b/indra/newview/skins/white_emerald/colors.xml index cf9466fad..b637519e0 100644 --- a/indra/newview/skins/white_emerald/colors.xml +++ b/indra/newview/skins/white_emerald/colors.xml @@ -1,3 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/white_emerald/colors_base.xml b/indra/newview/skins/white_emerald/colors_base.xml deleted file mode 100644 index b637519e0..000000000 --- a/indra/newview/skins/white_emerald/colors_base.xml +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/wisdom/colors_base.xml b/indra/newview/skins/wisdom/colors.xml similarity index 100% rename from indra/newview/skins/wisdom/colors_base.xml rename to indra/newview/skins/wisdom/colors.xml From 5eb90ef9cdeaf9722d7830d3ee44a7e1359b2f48 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Mon, 5 Mar 2012 19:05:30 +0100 Subject: [PATCH 31/35] Preference button to clear settings --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llfloaterpreference.cpp | 13 +++- indra/newview/llfloaterpreference.h | 5 ++ indra/newview/llpanelgeneral.cpp | 44 ++++++++++++++ indra/newview/llpanelgeneral.h | 3 + .../skins/default/xui/en-us/notifications.xml | 59 +++++++++++++++++++ .../xui/en-us/panel_preferences_general.xml | 3 +- 7 files changed, 126 insertions(+), 3 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f9b809665..681ef347e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6402,7 +6402,7 @@ Type Boolean Value - 1 + 0 FlycamAbsolute diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 231d680a0..6e102d58c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -387,6 +387,7 @@ void LLPreferenceCore::refreshEnabledGraphics() LLFloaterPreference::LLFloaterPreference() { + mExitWithoutSaving = false; LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preferences.xml"); } @@ -532,7 +533,10 @@ void LLFloaterPreference::onBtnApply( void* userdata ) void LLFloaterPreference::onClose(bool app_quitting) { LLPanelLogin::setAlwaysRefresh(false); - cancel(); // will be a no-op if OK or apply was performed just prior. + if (!mExitWithoutSaving) + { + cancel(); // will be a no-op if OK or apply was performed just prior. + } LLFloater::onClose(app_quitting); } @@ -572,3 +576,10 @@ void LLFloaterPreference::switchTab(S32 i) { sInstance->mPreferenceCore->getTabContainer()->selectTab(i); } + +// static +void LLFloaterPreference::closeWithoutSaving() +{ + sInstance->mExitWithoutSaving = true; + sInstance->close(); +} diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index c849ac6ea..a662a08c7 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -124,6 +124,10 @@ public: static void switchTab(S32 i); + // *HACK: Close without doing anything. + // This is used by the "reset all settings" button. + static void closeWithoutSaving(); + protected: LLPreferenceCore *mPreferenceCore; @@ -133,6 +137,7 @@ protected: LLButton *mOKBtn; LLButton *mCancelBtn; LLButton *mApplyBtn; + bool mExitWithoutSaving; static void onClickAbout(void*); static void onBtnOK(void*); diff --git a/indra/newview/llpanelgeneral.cpp b/indra/newview/llpanelgeneral.cpp index a238d408d..fbd323a09 100644 --- a/indra/newview/llpanelgeneral.cpp +++ b/indra/newview/llpanelgeneral.cpp @@ -43,6 +43,7 @@ #include "llviewercontrol.h" #include "llagent.h" +#include "llfloaterpreference.h" #include "llviewerregion.h" #include "llavatarnamecache.h" #include "llvoavatar.h" @@ -109,6 +110,8 @@ BOOL LLPanelGeneral::postBuild() childSetVisible("maturity_desired_combobox", can_choose); childSetVisible("maturity_desired_textbox", !can_choose); + + childSetAction("clear_settings", &onClickClearSettings, this); return TRUE; } @@ -160,3 +163,44 @@ void LLPanelGeneral::cancel() { } +// static +void LLPanelGeneral::onClickClearSettings(void*) +{ + if(gAgent.getID().notNull()) { + LLNotifications::instance().add("ResetAllSettingsPrompt", LLSD(), LLSD(), &callbackResetAllSettings); + } + else + { + LLNotifications::instance().add("ResetSystemSettingsPrompt", LLSD(), LLSD(), &callbackResetAllSettings); + } +} + +// static +void LLPanelGeneral::callbackResetAllSettings(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if(option != 3) //At least some settings want to be removed + { + // We probably want to avoid altering this setting, so keep it across the reset. + std::string client_settings_file = gSavedSettings.getString("ClientSettingsFile"); + if(option != 2) + { + gSavedSettings.resetToDefaults(); + gSavedSettings.setString("ClientSettingsFile", client_settings_file); + gSavedSettings.saveToFile(client_settings_file, TRUE); + } + + // Wipe user-specific settings for good measure and consistency. + // Obviously, we can only do this if we're actually logged in. + if(gAgent.getID().notNull() && (option != 1)) + { + gSavedPerAccountSettings.resetToDefaults(); + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + } + LLNotifications::instance().add("ResetSettingsComplete"); + + // *HACK: Now close the floater without cancelling or applying. + // (the alternative route would be to add a method to every preference panel to handle this and update its UI) + LLFloaterPreference::closeWithoutSaving(); + } +} diff --git a/indra/newview/llpanelgeneral.h b/indra/newview/llpanelgeneral.h index 4afa5dd66..b60ce2289 100644 --- a/indra/newview/llpanelgeneral.h +++ b/indra/newview/llpanelgeneral.h @@ -46,6 +46,9 @@ public: void apply(); void cancel(); + + static void LLPanelGeneral::onClickClearSettings(void*); + static void callbackResetAllSettings(const LLSD& notification, const LLSD& response); }; #endif diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 86b27d335..39d1f73a1 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -7032,6 +7032,65 @@ Your shape, skin, hair or eyes might be defect. yestext="OK"/> + + Settings have been reset. You should relog to ensure this takes full effect. + + + + Resetting all settings may be helpful if you are experiencing problems; however, you will need to redo any changes you have made to the default configuration. + + Would you like to reset system settings? +
+