summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags1
-rwxr-xr-xautobuild.xml44
-rwxr-xr-xbuild.sh85
-rwxr-xr-xdoc/contributions.txt3
-rw-r--r--indra/cmake/BuildVersion.cmake12
-rw-r--r--indra/cmake/CMakeLists.txt2
-rw-r--r--indra/cmake/LLWindow.cmake2
-rw-r--r--indra/cmake/LibVLCPlugin.cmake27
-rw-r--r--indra/edit-me-to-trigger-new-build.txt1
-rw-r--r--indra/linux_crash_logger/linux_crash_logger.cpp2
-rw-r--r--indra/linux_crash_logger/llcrashloggerlinux.cpp2
-rw-r--r--indra/linux_crash_logger/llcrashloggerlinux.h2
-rw-r--r--indra/llcommon/CMakeLists.txt9
-rw-r--r--indra/llcommon/indra_constants.cpp4
-rw-r--r--indra/llcommon/indra_constants.h4
-rw-r--r--indra/llcommon/llapp.h8
-rw-r--r--indra/llcommon/llcoros.cpp29
-rw-r--r--indra/llcommon/lldependencies.cpp3
-rw-r--r--indra/llcommon/lldependencies.h6
-rw-r--r--indra/llcommon/llerror.h87
-rw-r--r--indra/llcommon/lleventcoro.cpp3
-rw-r--r--indra/llcommon/lleventcoro.h6
-rw-r--r--indra/llcommon/llevents.cpp15
-rw-r--r--indra/llcommon/llevents.h46
-rw-r--r--indra/llcommon/llexception.cpp55
-rw-r--r--indra/llcommon/llexception.h85
-rw-r--r--indra/llcommon/llfasttimer.h11
-rw-r--r--indra/llcommon/llleap.cpp5
-rw-r--r--indra/llcommon/llleap.h6
-rw-r--r--indra/llcommon/llmemory.h10
-rw-r--r--indra/llcommon/llprocess.cpp21
-rw-r--r--indra/llcommon/llprocess.h6
-rw-r--r--indra/llcommon/llstring.cpp27
-rw-r--r--indra/llcommon/llstring.h11
-rw-r--r--indra/llcommon/llthreadsafequeue.cpp13
-rw-r--r--indra/llcommon/llthreadsafequeue.h7
-rw-r--r--indra/llcommon/lluuid.cpp2
-rw-r--r--indra/llcommon/tests/llerror_test.cpp17
-rw-r--r--indra/llcommon/tests/llexception_test.cpp308
-rw-r--r--indra/llcommon/tests/wrapllerrs.h8
-rw-r--r--indra/llcrashlogger/llcrashlogger.h2
-rw-r--r--indra/llimage/llimage.cpp93
-rw-r--r--indra/llimage/llpngwrapper.cpp29
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp101
-rw-r--r--indra/llmessage/llassetstorage.h4
-rw-r--r--indra/llmessage/llavatarname.cpp23
-rw-r--r--indra/llmessage/llavatarname.h4
-rw-r--r--indra/llmessage/llavatarnamecache.cpp11
-rw-r--r--indra/llmessage/llcoproceduremanager.cpp14
-rw-r--r--indra/llmessage/llhttpnode.cpp12
-rw-r--r--indra/llmessage/tests/commtest.h8
-rw-r--r--indra/llmessage/tests/networkio.h5
-rw-r--r--indra/llprimitive/lldaeloader.cpp6
-rw-r--r--indra/llrender/llglslshader.cpp4
-rw-r--r--indra/llrender/llshadermgr.cpp2
-rw-r--r--indra/llui/llfloater.cpp36
-rw-r--r--indra/llui/llfloater.h4
-rw-r--r--indra/llui/llfolderview.cpp4
-rw-r--r--indra/llui/llfolderview.h3
-rw-r--r--indra/llui/llfolderviewitem.cpp5
-rw-r--r--indra/llui/lllineeditor.cpp7
-rw-r--r--indra/llui/lltextbase.cpp26
-rw-r--r--indra/llui/lltextbase.h3
-rw-r--r--indra/llui/lltextutil.cpp20
-rw-r--r--indra/llui/lltextutil.h6
-rw-r--r--indra/llui/llurlaction.cpp10
-rw-r--r--indra/llui/llurlaction.h1
-rw-r--r--indra/llui/llview.cpp7
-rw-r--r--indra/llwindow/llappdelegate-objc.h2
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h2
-rw-r--r--indra/mac_crash_logger/llcrashloggermac.cpp2
-rw-r--r--indra/mac_crash_logger/llcrashloggermac.h2
-rw-r--r--indra/mac_crash_logger/mac_crash_logger.cpp2
-rw-r--r--indra/media_plugins/CMakeLists.txt7
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp60
-rw-r--r--indra/media_plugins/libvlc/CMakeLists.txt86
-rw-r--r--indra/media_plugins/libvlc/media_plugin_libvlc.cpp618
-rwxr-xr-x[-rw-r--r--]indra/media_plugins/quicktime/CMakeLists.txt10
-rwxr-xr-x[-rw-r--r--]indra/media_plugins/quicktime/media_plugin_quicktime.cpp9
-rw-r--r--indra/newview/CMakeLists.txt9
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/commands.xml2
-rw-r--r--indra/newview/app_settings/settings.xml33
-rw-r--r--indra/newview/featuretable.txt2
-rw-r--r--indra/newview/featuretable_linux.txt2
-rw-r--r--indra/newview/featuretable_mac.txt2
-rw-r--r--indra/newview/installers/windows/installer_template.nsi11
-rw-r--r--indra/newview/installers/windows/lang_en-us.nsibin8510 -> 9096 bytes
-rw-r--r--indra/newview/llaccountingcostmanager.cpp10
-rw-r--r--indra/newview/llaisapi.cpp21
-rw-r--r--indra/newview/llappcorehttp.cpp7
-rw-r--r--indra/newview/llappdelegate-objc.mm24
-rw-r--r--indra/newview/llappearancemgr.cpp24
-rw-r--r--indra/newview/llappearancemgr.h4
-rw-r--r--indra/newview/llappviewer.cpp505
-rw-r--r--indra/newview/llappviewer.h3
-rw-r--r--indra/newview/llappviewerlinux.cpp6
-rw-r--r--indra/newview/llappviewermacosx.cpp9
-rw-r--r--indra/newview/llappviewerwin32.cpp52
-rw-r--r--indra/newview/llavataractions.cpp122
-rw-r--r--indra/newview/llavataractions.h5
-rw-r--r--indra/newview/llavatarlist.cpp17
-rw-r--r--indra/newview/llavatarlist.h4
-rw-r--r--indra/newview/llavatarlistitem.cpp22
-rw-r--r--indra/newview/llavatarlistitem.h4
-rw-r--r--indra/newview/llavatarrendernotifier.cpp6
-rw-r--r--indra/newview/llchathistory.cpp21
-rw-r--r--indra/newview/llcommandlineparser.cpp24
-rw-r--r--indra/newview/llcompilequeue.cpp939
-rw-r--r--indra/newview/llcompilequeue.h86
-rw-r--r--indra/newview/lldrawpoolterrain.cpp17
-rw-r--r--indra/newview/lleventpoll.cpp9
-rw-r--r--indra/newview/lleventpoll.h8
-rw-r--r--indra/newview/llfeaturemanager.cpp59
-rw-r--r--indra/newview/llfeaturemanager.h4
-rw-r--r--indra/newview/llfloatergesture.cpp3
-rw-r--r--indra/newview/llfloaterimnearbychathandler.cpp25
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp6
-rw-r--r--indra/newview/llfloaterimsessiontab.h2
-rw-r--r--indra/newview/llfloaternamedesc.cpp22
-rw-r--r--indra/newview/llfloaterregioninfo.cpp52
-rw-r--r--indra/newview/llfloaterregioninfo.h7
-rw-r--r--indra/newview/llfloatersnapshot.cpp14
-rw-r--r--indra/newview/llfloatersnapshot.h1
-rw-r--r--indra/newview/llfloaterwebcontent.cpp45
-rw-r--r--indra/newview/llfloaterwebcontent.h5
-rw-r--r--indra/newview/llfloaterworldmap.cpp4
-rw-r--r--indra/newview/llfloaterworldmap.h2
-rw-r--r--indra/newview/llinspectremoteobject.cpp2
-rw-r--r--indra/newview/llinventoryfunctions.cpp6
-rw-r--r--indra/newview/lllocationinputctrl.cpp25
-rw-r--r--indra/newview/lllocationinputctrl.h1
-rw-r--r--indra/newview/lllogchat.cpp3
-rw-r--r--indra/newview/llmeshrepository.cpp28
-rw-r--r--indra/newview/llmeshrepository.h1
-rw-r--r--indra/newview/llpanelmaininventory.cpp20
-rw-r--r--indra/newview/llpanelmaininventory.h1
-rw-r--r--indra/newview/llpanelpeople.cpp21
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp88
-rw-r--r--indra/newview/llpanelpeoplemenus.h2
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp46
-rw-r--r--indra/newview/llpanelprimmediacontrols.h8
-rw-r--r--indra/newview/llpanelprofile.cpp10
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp17
-rw-r--r--indra/newview/llpanelwearing.cpp2
-rw-r--r--indra/newview/llpresetsmanager.cpp57
-rw-r--r--indra/newview/llpresetsmanager.h2
-rw-r--r--indra/newview/llpreviewnotecard.cpp6
-rw-r--r--indra/newview/llpreviewtexture.cpp38
-rw-r--r--indra/newview/llsecapi.cpp13
-rw-r--r--indra/newview/llsecapi.h34
-rw-r--r--indra/newview/llsechandler_basic.cpp90
-rw-r--r--indra/newview/llstartup.cpp15
-rw-r--r--indra/newview/llsurfacepatch.cpp4
-rw-r--r--indra/newview/lltoast.cpp15
-rw-r--r--indra/newview/lltoast.h2
-rw-r--r--indra/newview/lltoastnotifypanel.cpp9
-rw-r--r--indra/newview/lltoastscriptquestion.cpp19
-rw-r--r--indra/newview/lltoastscriptquestion.h2
-rw-r--r--indra/newview/lltoolmgr.cpp9
-rw-r--r--indra/newview/lltoolmgr.h1
-rw-r--r--indra/newview/lltracker.cpp6
-rw-r--r--indra/newview/lltracker.h2
-rw-r--r--indra/newview/llviewerassetupload.cpp7
-rw-r--r--indra/newview/llviewermenu.cpp15
-rw-r--r--indra/newview/llviewerpartsource.cpp10
-rw-r--r--indra/newview/llviewerregion.cpp5
-rw-r--r--indra/newview/llviewertexture.cpp3
-rw-r--r--indra/newview/llviewertexturelist.cpp22
-rw-r--r--indra/newview/llvoavatar.cpp73
-rw-r--r--indra/newview/llvoicevivox.cpp2
-rw-r--r--indra/newview/llvovolume.cpp6
-rw-r--r--indra/newview/llweb.cpp4
-rw-r--r--indra/newview/llweb.h2
-rw-r--r--indra/newview/llworld.cpp8
-rw-r--r--indra/newview/skins/default/textures/icons/Video_URL_Off.pngbin0 -> 282 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_queue.xml8
-rw-r--r--indra/newview/skins/default/xui/en/floater_web_content.xml130
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml1
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml13
-rw-r--r--indra/newview/skins/default/xui/en/menu_object_icon.xml14
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_friends_view.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_objectim.xml7
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_tab.xml7
-rw-r--r--indra/newview/skins/default/xui/en/mime_types.xml56
-rw-r--r--indra/newview/skins/default/xui/en/mime_types_linux.xml30
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml54
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_login_first.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
-rwxr-xr-xindra/newview/viewer_manifest.py35
-rw-r--r--indra/test/llapp_tut.cpp2
-rw-r--r--indra/viewer_components/login/lllogin.cpp102
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.cpp16
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.cpp12
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp9
-rw-r--r--indra/viewer_components/updater/llupdaterservice.h5
-rw-r--r--indra/win_crash_logger/llcrashloggerwindows.cpp8
-rw-r--r--indra/win_crash_logger/llcrashloggerwindows.h2
-rw-r--r--indra/win_crash_logger/win_crash_logger.cpp2
206 files changed, 4327 insertions, 1538 deletions
diff --git a/.hgtags b/.hgtags
index 0d06bfe598..cee1281f2b 100755
--- a/.hgtags
+++ b/.hgtags
@@ -517,3 +517,4 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
0a5de9ec2cb868f367501024d8d6958c20869053 4.0.4-release
450de775fff66a011be1a001acd117cc623c445d 4.0.5-release
4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release
+33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
diff --git a/autobuild.xml b/autobuild.xml
index 072dfa678a..2d8bd22a1c 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1454,9 +1454,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>faa1e5b7cf70c143caabe190fa5588ce</string>
+ <string>fddd634dec5ec03924d62cc774f7f8ea</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/304432/arch/Linux/installer/llappearance_utility-0.0.1-linux-304432.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_viewer-llappearance-utility/rev/317266/arch/Linux/installer/llappearance_utility-0.0.1-linux-317266.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@@ -2135,6 +2135,46 @@
<key>version</key>
<string>0.8.0.1</string>
</map>
+ <key>vlc-bin</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string>
+ <key>license</key>
+ <string>GPL2</string>
+ <key>license_file</key>
+ <string>LICENSES/vlc.txt</string>
+ <key>name</key>
+ <string>vlc-bin</string>
+ <key>platforms</key>
+ <map>
+ <key>linux</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>2f410640df3f9812d1abff02a414cfa8</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>04cff37070a5f65f3652b4ddcec7183f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/317935/arch/CYGWIN/installer/vlc_bin-2.2.4.317935-windows-317935.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>2.2.4.317935</string>
+ </map>
<key>xmlrpc-epi</key>
<map>
<key>copyright</key>
diff --git a/build.sh b/build.sh
index 20d3a41f83..cd2a9ebf5e 100755
--- a/build.sh
+++ b/build.sh
@@ -16,12 +16,6 @@
# * The special style in which python is invoked is intentional to permit
# use of a native python install on windows - which requires paths in DOS form
-check_for()
-{
- if [ -e "$2" ]; then found_dict='FOUND'; else found_dict='MISSING'; fi
- echo "$1 ${found_dict} '$2' " 1>&2
-}
-
build_dir_Darwin()
{
echo build-darwin-i386
@@ -101,13 +95,14 @@ pre_build()
&& [ -r "$master_message_template_checkout/message_template.msg" ] \
&& template_verifier_master_url="-DTEMPLATE_VERIFIER_MASTER_URL=file://$master_message_template_checkout/message_template.msg"
- "$autobuild" configure -c $variant -- \
+ "$autobuild" configure --quiet -c $variant -- \
-DPACKAGE:BOOL=ON \
-DRELEASE_CRASH_REPORTING:BOOL=ON \
-DVIEWER_CHANNEL:STRING="\"$viewer_channel\"" \
-DGRID:STRING="\"$viewer_grid\"" \
-DLL_TESTS:BOOL="$run_tests" \
- -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url
+ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url \
+ || fatal "$variant configuration failed"
end_section "Configure $variant"
}
@@ -146,52 +141,46 @@ build()
local variant="$1"
if $build_viewer
then
- "$autobuild" build --no-configure -c $variant
- build_ok=$?
-
+ "$autobuild" build --no-configure -c $variant || fatal "failed building $variant"
+
# Run build extensions
- if [ $build_ok -eq 0 -a -d ${build_dir}/packages/build-extensions ]; then
- for extension in ${build_dir}/packages/build-extensions/*.sh; do
+ if [ $build_ok -eq 0 -a -d ${build_dir}/packages/build-extensions ]
+ then
+ for extension in ${build_dir}/packages/build-extensions/*.sh
+ do
begin_section "Extension $extension"
. $extension
end_section "Extension $extension"
- if [ $build_ok -ne 0 ]; then
- break
- fi
done
fi
# *TODO: Make this a build extension.
- package_llphysicsextensions_tpv
- tpvlib_build_ok=$?
- if [ $build_ok -eq 0 -a $tpvlib_build_ok -eq 0 ]
- then
+ package_llphysicsextensions_tpv || fatal "failed building llphysicsextensions packages"
+
+ echo true >"$build_dir"/build_ok
+ else
+ echo "Skipping build due to configuration build_viewer=${build_viewer}"
echo true >"$build_dir"/build_ok
- else
- echo false >"$build_dir"/build_ok
- fi
fi
}
-# Check to see if we were invoked from the wrapper, if not, re-exec ourselves from there
-if [ "x$arch" = x ]
+################################################################
+# Start of the actual script
+################################################################
+
+# Check to see if we were invoked from the master buildscripts wrapper, if not, fail
+if [ "x${BUILDSCRIPTS_SUPPORT_FUNCTIONS}" = x ]
then
- top=`hg root`
- if [ -x "$top/../buildscripts/hg/bin/build.sh" ]
- then
- exec "$top/../buildscripts/hg/bin/build.sh" "$top"
- else
- cat <<EOF
-This script, if called in a development environment, requires that the branch
-independent build script repository be checked out next to this repository.
-This repository is located at http://bitbucket.org/lindenlabinternal/sl-buildscripts
-EOF
+ echo "This script relies on being run by the master Linden Lab buildscripts" 1>&2
exit 1
- fi
fi
# Check to see if we're skipping the platform
-eval '$build_'"$arch" || pass
+if ! eval '$build_'"$arch"
+then
+ record_event "building on architecture $arch is disabled"
+ pass
+fi
# ensure AUTOBUILD is in native path form for child processes
AUTOBUILD="$(native_path "$AUTOBUILD")"
@@ -204,7 +193,7 @@ then
fi
# load autobuild provided shell functions and variables
-eval "$("$autobuild" source_environment)"
+eval "$("$autobuild" --quiet source_environment)"
# something about the additional_packages mechanism messes up buildscripts results.py on Linux
# since we don't care about those packages on Linux, just zero it out, yes - a HACK
@@ -235,14 +224,13 @@ do
begin_section "Initialize $variant Build Directory"
rm -rf "$build_dir"
- mkdir -p "$build_dir"
mkdir -p "$build_dir/tmp"
end_section "Initialize $variant Build Directory"
if pre_build "$variant" "$build_dir"
then
begin_section "Build $variant"
- build "$variant" "$build_dir" 2>&1 | tee -a "$build_log" | sed -n 's/^ *\(##teamcity.*\)/\1/p'
+ build "$variant" "$build_dir"
if `cat "$build_dir/build_ok"`
then
case "$variant" in
@@ -255,7 +243,7 @@ do
then
record_dependencies_graph # defined in buildscripts/hg/bin/build.sh
else
- record_event "TBD - no dependency graph for linux (probable python version dependency)" 1>&2
+ record_event "TBD - no dependency graph for linux (probable python version dependency)"
fi
end_section "Autobuild metadata"
else
@@ -306,11 +294,10 @@ then
dch --force-bad-version \
--distribution unstable \
--newversion "${VIEWER_VERSION}" \
- "Automated build #$build_id, repository $branch revision $revision." \
- >> "$build_log" 2>&1
+ "Automated build #$build_id, repository $branch revision $revision."
# build the debian package
- $pkg_default_debuild_command >>"$build_log" 2>&1 || record_failure "\"$pkg_default_debuild_command\" failed."
+ $pkg_default_debuild_command || record_failure "\"$pkg_default_debuild_command\" failed."
# Unmangle the changelog file
hg revert debian/changelog
@@ -359,10 +346,10 @@ then
end_section "Upload Debian Repository"
else
- echo debian build not enabled
+ record_event "debian build not enabled"
fi
else
- echo skipping debian build due to failed build.
+ record_event "skipping debian build due to failed build"
fi
fi
@@ -376,7 +363,7 @@ then
package=$(installer_$arch)
if [ x"$package" = x ] || test -d "$package"
then
- # Coverity doesn't package, so it's ok, anything else is fail
+ record_event "??? mystery event $package // $build_coverity"
succeeded=$build_coverity
else
# Upload base package.
@@ -428,12 +415,12 @@ then
fi
end_section Upload Installer
else
- echo skipping upload of installer
+ record_event "skipping upload of installer"
fi
else
- echo skipping upload of installer due to failed build.
+ record_event "skipping upload of installer due to failed build"
fi
# The branch independent build.sh script invoking this script will finish processing
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 9b31e5032a..8ed41ddc34 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -190,6 +190,9 @@ Ansariel Hiller
STORM-2094
MAINT-5756
MAINT-4677
+ MAINT-6432
+ STORM-2133
+ MAINT-6511
Aralara Rajal
Arare Chantilly
CHUIBUG-191
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index 195d6e705e..6ffa698a1c 100644
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -12,7 +12,7 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
if (DEFINED ENV{revision})
set(VIEWER_VERSION_REVISION $ENV{revision})
- message("Revision (from environment): ${VIEWER_VERSION_REVISION}")
+ message(STATUS "Revision (from environment): ${VIEWER_VERSION_REVISION}")
else (DEFINED ENV{revision})
find_program(MERCURIAL
@@ -33,23 +33,23 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
string(REGEX REPLACE "[^0-9a-f]" "" VIEWER_VERSION_REVISION ${VIEWER_VERSION_REVISION})
endif (NOT ${hg_id_result} EQUAL 0)
if ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
- message("Revision (from hg) ${VIEWER_VERSION_REVISION}")
+ message(STATUS "Revision (from hg) ${VIEWER_VERSION_REVISION}")
else ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
- message("Revision not set (repository not found?); using 0")
+ message(STATUS "Revision not set (repository not found?); using 0")
set(VIEWER_VERSION_REVISION 0 )
endif ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
else (MERCURIAL)
- message("Revision not set: mercurial not found; using 0")
+ message(STATUS "Revision not set: mercurial not found; using 0")
set(VIEWER_VERSION_REVISION 0)
endif (MERCURIAL)
endif (DEFINED ENV{revision})
- message("Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
+ message(STATUS "Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
else ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
message(SEND_ERROR "Cannot get viewer version from '${VIEWER_VERSION_BASE_FILE}'")
endif ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
if ("${VIEWER_VERSION_REVISION}" STREQUAL "")
- message("Ultimate fallback, revision was blank or not set: will use 0")
+ message(STATUS "Ultimate fallback, revision was blank or not set: will use 0")
set(VIEWER_VERSION_REVISION 0)
endif ("${VIEWER_VERSION_REVISION}" STREQUAL "")
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 6dc8e3dfbf..13a31cbce7 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -24,7 +24,6 @@ set(cmake_SOURCE_FILES
DirectX.cmake
DragDrop.cmake
EXPAT.cmake
-## ExamplePlugin.cmake
FindAPR.cmake
FindAutobuild.cmake
FindBerkeleyDB.cmake
@@ -100,6 +99,7 @@ set(cmake_SOURCE_FILES
Variables.cmake
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
+ LibVLCPlugin.cmake
XmlRpcEpi.cmake
ZLIB.cmake
)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index ba07a80f05..80af7ff2ab 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -18,7 +18,7 @@ else (USESYSTEMLIBS)
use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
- set (SDL_LIBRARY SDL directfb fusion direct)
+ set (SDL_LIBRARY SDL directfb fusion direct X11)
endif (LINUX)
endif (USESYSTEMLIBS)
diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake
new file mode 100644
index 0000000000..4472676fb4
--- /dev/null
+++ b/indra/cmake/LibVLCPlugin.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (USESYSTEMLIBS)
+ set(LIBVLCPLUGIN OFF CACHE BOOL
+ "LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
+else (USESYSTEMLIBS)
+ use_prebuilt_binary(vlc-bin)
+ set(LIBVLCPLUGIN ON CACHE BOOL
+ "LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
+ set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc)
+endif (USESYSTEMLIBS)
+
+if (WINDOWS)
+ set(VLC_PLUGIN_LIBRARIES
+ libvlc.lib
+ libvlccore.lib
+ )
+elseif (DARWIN)
+elseif (LINUX)
+ # Specify a full path to make sure we get a static link
+ set(VLC_PLUGIN_LIBRARIES
+ ${LIBS_PREBUILT_DIR}/lib/libvlc.a
+ ${LIBS_PREBUILT_DIR}/lib/libvlccore.a
+ )
+endif (WINDOWS)
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index 32aa08a2b7..9f9ca6c39c 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1,3 +1,4 @@
2014-02-25 10:34
+
diff --git a/indra/linux_crash_logger/linux_crash_logger.cpp b/indra/linux_crash_logger/linux_crash_logger.cpp
index 9d5ec33fed..63e5409876 100644
--- a/indra/linux_crash_logger/linux_crash_logger.cpp
+++ b/indra/linux_crash_logger/linux_crash_logger.cpp
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
return 1;
}
- app.mainLoop();
+ app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
return 0;
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp
index e2d2e7ff26..4092d43fc5 100644
--- a/indra/linux_crash_logger/llcrashloggerlinux.cpp
+++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp
@@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
{
}
-bool LLCrashLoggerLinux::mainLoop()
+bool LLCrashLoggerLinux::frame()
{
bool send_logs = true;
if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.h b/indra/linux_crash_logger/llcrashloggerlinux.h
index dae6c46651..789f6f03f5 100644
--- a/indra/linux_crash_logger/llcrashloggerlinux.h
+++ b/indra/linux_crash_logger/llcrashloggerlinux.h
@@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger
public:
LLCrashLoggerLinux(void);
~LLCrashLoggerLinux(void);
- virtual bool mainLoop();
+ virtual bool frame();
virtual void updateApplication(const std::string& = LLStringUtil::null);
virtual void gatherPlatformSpecificFiles();
virtual bool cleanup();
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 907dbab8f8..410a5819b3 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES
lleventfilter.cpp
llevents.cpp
lleventtimer.cpp
+ llexception.cpp
llfasttimer.cpp
llfile.cpp
llfindlocale.cpp
@@ -157,6 +158,7 @@ set(llcommon_HEADER_FILES
lleventfilter.h
llevents.h
lleventemitter.h
+ llexception.h
llfasttimer.h
llfile.h
llfindlocale.h
@@ -315,7 +317,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
- LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
@@ -328,6 +330,11 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
+## llexception_test.cpp isn't a regression test, and doesn't need to be run
+## every build. It's to help a developer make implementation choices about
+## throwing and catching exceptions.
+##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}")
+
# *TODO - reenable these once tcmalloc libs no longer break the build.
#ADD_BUILD_TEST(llallocator llcommon)
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index 60721977cd..7ea42a3fc0 100644
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -60,6 +60,10 @@ const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On d
const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
+const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER
+const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER
+const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER
+
const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 02f063f5e8..fda84aa5a8 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -197,6 +197,10 @@ LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
+LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD;
+LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD_2D;
+LL_COMMON_API extern const LLUUID IMG_TRANSPARENT;
+
LL_COMMON_API extern const LLUUID IMG_BLOOM1;
LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index d9933b3d36..ff9a92b45f 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -172,12 +172,12 @@ public:
virtual bool cleanup() = 0; // Override to do application cleanup
//
- // mainLoop()
+ // frame()
//
- // Runs the application main loop. It's assumed that when you exit
- // this method, the application is in one of the cleanup states, either QUITTING or ERROR
+ // Pass control to the application for a single frame. Returns 'done'
+ // flag: if frame() returns false, it expects to be called again.
//
- virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
+ virtual bool frame() = 0; // Override for application body logic
//
// Crash logging
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index d16bf0160b..8e516d8beb 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -38,6 +38,7 @@
#include "llevents.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
// do nothing, when we need nothing done
void LLCoros::no_cleanup(CoroData*) {}
@@ -131,9 +132,9 @@ bool LLCoros::cleanup(const LLSD&)
if ((previousCount < 5) || !(previousCount % 50))
{
if (previousCount < 5)
- LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
else
- LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
}
// The erase() call will invalidate its passed iterator value --
@@ -185,9 +186,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
if ((previousCount < 5) || !(previousCount % 50))
{
if (previousCount < 5)
- LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
else
- LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
}
@@ -223,7 +224,7 @@ std::string LLCoros::getName() const
void LLCoros::setStackSize(S32 stacksize)
{
- LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
mStackSize = stacksize;
}
@@ -235,7 +236,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
// capture the 'self' param in CoroData
data->mSelf = &self;
// run the code the caller actually wants in the coroutine
- callable();
+ try
+ {
+ callable();
+ }
+ catch (const LLContinueError&)
+ {
+ // Any uncaught exception derived from LLContinueError will be caught
+ // here and logged. This coroutine will terminate but the rest of the
+ // viewer will carry on.
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
+ catch (...)
+ {
+ // Any OTHER kind of uncaught exception will cause the viewer to
+ // crash, hopefully informatively.
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
// This cleanup isn't perfectly symmetrical with the way we initially set
// data->mPrev, but this is our last chance to reset mCurrentCoro.
sCurrentCoro.reset(data->mPrev);
diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp
index 0e72c175cb..0d5757effd 100644
--- a/indra/llcommon/lldependencies.cpp
+++ b/indra/llcommon/lldependencies.cpp
@@ -40,6 +40,7 @@
#include <boost/graph/topological_sort.hpp>
#include <boost/graph/exception.hpp>
// other Linden headers
+#include "llexception.h"
LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
{
@@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const
// Omit independent nodes: display only those that might contribute to
// the cycle.
describe(out, false);
- throw Cycle(out.str());
+ LLTHROW(Cycle(out.str()));
}
// A peculiarity of boost::topological_sort() is that it emits results in
// REVERSE topological order: to get the result you want, you must
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
index e0294e271b..125bd6a835 100644
--- a/indra/llcommon/lldependencies.h
+++ b/indra/llcommon/lldependencies.h
@@ -34,13 +34,13 @@
#include <vector>
#include <set>
#include <map>
-#include <stdexcept>
#include <iosfwd>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
+#include "llexception.h"
/*****************************************************************************
* Utilities
@@ -106,9 +106,9 @@ public:
/**
* Exception thrown by sort() if there's a cycle
*/
- struct Cycle: public std::runtime_error
+ struct Cycle: public LLException
{
- Cycle(const std::string& what): std::runtime_error(what) {}
+ Cycle(const std::string& what): LLException(what) {}
};
/**
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 3beef65723..7cbe4334b3 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -174,7 +174,8 @@ namespace LLError
// not really a level
// used to indicate that no messages should be logged
};
-
+ // If you change ELevel, please update llvlog() macro below.
+
/* Macro support
The classes CallSite and Log are used by the logging macros below.
They are not intended for general use.
@@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
/////////////////////////////////
// Error Logging Macros
-// See top of file for common usage.
+// See top of file for common usage.
/////////////////////////////////
-// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements
-// without braces:
-// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL
-
-#define lllog(level, once, ...) \
- do { \
- const char* tags[] = {"", ##__VA_ARGS__}; \
- ::size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \
- static LLError::CallSite _site( \
- level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
- if (LL_UNLIKELY(_site.shouldLog())) \
- { \
- std::ostringstream* _out = LLError::Log::out(); \
+// Instead of using LL_DEBUGS(), LL_INFOS() et al., it may be tempting to
+// directly code the lllog() macro so you can pass in the LLError::ELevel as a
+// variable. DON'T DO IT! The reason is that the first time control passes
+// through lllog(), it initializes a local static LLError::CallSite with that
+// *first* ELevel value. All subsequent visits will decide whether or not to
+// emit output based on the *first* ELevel value bound into that static
+// CallSite instance. Use LL_VLOGS() instead. lllog() assumes its ELevel
+// argument never varies.
+
+// this macro uses a one-shot do statement to avoid parsing errors when
+// writing control flow statements without braces:
+// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL;
+
+#define lllog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
+ lllog_test_()
+
+#define lllog_test_() \
+ if (LL_UNLIKELY(_site.shouldLog())) \
+ { \
+ std::ostringstream* _out = LLError::Log::out(); \
(*_out)
+#define lllog_site_args_(level, once, tags) \
+ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
+ __FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
+
//Use this construct if you need to do computation in the middle of a
//message:
//
@@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
+// Use this if you need to pass LLError::ELevel as a variable.
+#define LL_VLOGS(level, ...) llvlog(level, false, ##__VA_ARGS__)
+#define LL_VLOGS_ONCE(level, ...) llvlog(level, true, ##__VA_ARGS__)
+
+// The problem with using lllog() with a variable level is that the first time
+// through, it initializes a static CallSite instance with whatever level you
+// pass. That first level is bound into the CallSite; the level parameter is
+// never again examined. One approach to variable level would be to
+// dynamically construct a CallSite instance every call -- which could get
+// expensive, depending on context. So instead, initialize a static CallSite
+// for each level value we support, then dynamically select the CallSite
+// instance for the passed level value.
+// Compare implementation to lllog() above.
+#define llvlog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ /* Need a static CallSite instance per expected ELevel value. */ \
+ /* Since we intend to index this array with the ELevel, */ \
+ /* _sites[0] should be ELevel(0), and so on -- avoid using */ \
+ /* ELevel symbolic names when initializing -- except for */ \
+ /* the last entry, which handles anything beyond the end. */ \
+ /* (Commented ELevel value names are from 2016-09-01.) */ \
+ /* Passing an ELevel past the end of this array is itself */ \
+ /* a fatal error, so ensure the last is LEVEL_ERROR. */ \
+ static LLError::CallSite _sites[] = \
+ { \
+ /* LEVEL_DEBUG */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
+ /* LEVEL_INFO */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
+ /* LEVEL_WARN */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
+ /* LEVEL_ERROR */ \
+ LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
+ }; \
+ /* Clamp the passed 'level' to at most last entry */ \
+ std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
+ (LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
+ /* selected CallSite *must* be named _site for LL_ENDL */ \
+ LLError::CallSite& _site(_sites[which]); \
+ lllog_test_()
+
#endif // LL_LLERROR_H
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 2d5f964deb..56367b8f54 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -39,6 +39,7 @@
#include "llerror.h"
#include "llcoros.h"
#include "llmake.h"
+#include "llexception.h"
#include "lleventfilter.h"
@@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)
// returning it, deliver it via exception.
if (result.second)
{
- throw LLErrorEvent(desc, result.first);
+ LLTHROW(LLErrorEvent(desc, result.first));
}
// That way, our caller knows a simple return must be from the reply
// pump (pump 0).
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index 87926c692d..84827aab4a 100644
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -31,10 +31,10 @@
#include <boost/optional.hpp>
#include <string>
-#include <stdexcept>
#include <utility> // std::pair
#include "llevents.h"
#include "llerror.h"
+#include "llexception.h"
/**
* Like LLListenerOrPumpName, this is a class intended for parameter lists:
@@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc);
* because it's not an error in event processing: rather, this exception
* announces an event that bears error information (for some other API).
*/
-class LL_COMMON_API LLErrorEvent: public std::runtime_error
+class LL_COMMON_API LLErrorEvent: public LLException
{
public:
LLErrorEvent(const std::string& what, const LLSD& data):
- std::runtime_error(what),
+ LLException(what),
mData(data)
{}
virtual ~LLErrorEvent() throw() {}
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 645c29d770..19d700a3b0 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -57,6 +57,7 @@
#include "stringize.h"
#include "llerror.h"
#include "llsdutil.h"
+#include "llexception.h"
#if LL_MSVC
#pragma warning (disable : 4702)
#endif
@@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string
// Unless we're permitted to tweak it, that's Bad.
if (! tweak)
{
- throw LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'");
+ LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'"));
}
// The passed name isn't unique, but we're permitted to tweak it. Find the
// first decimal-integer suffix not already taken. The insert() attempt
@@ -326,8 +327,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// is only when the existing connection object is still connected.
if (found != mConnections.end() && found->second.connected())
{
- throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
- "' on " + typeid(*this).name() + " '" + getName() + "'");
+ LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name +
+ "' on " + typeid(*this).name() + " '" + getName() + "'"));
}
// Okay, name is unique, try to reconcile its dependencies. Specify a new
// "node" value that we never use for an mSignal placement; we'll fix it
@@ -353,8 +354,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// unsortable. If we leave the new node in mDeps, it will continue
// to screw up all future attempts to sort()! Pull it out.
mDeps.remove(name);
- throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
- " '" + getName() + "' would cause cycle: " + e.what());
+ LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() +
+ " '" + getName() + "' would cause cycle: " + e.what()));
}
// Walk the list to verify that we haven't changed the order.
float previous = 0.0, myprev = 0.0;
@@ -418,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// NOW remove the offending listener node.
mDeps.remove(name);
// Having constructed a description of the order change, inform caller.
- throw OrderChange(out.str());
+ LLTHROW(OrderChange(out.str()));
}
// This node becomes the previous one.
previous = dmi->second;
@@ -608,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
{
if (! mListener)
{
- throw Empty("attempting to call uninitialized");
+ LLTHROW(Empty("attempting to call uninitialized"));
}
return (*mListener)(event);
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index ba4fcd766e..1526128725 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -37,7 +37,6 @@
#include <set>
#include <vector>
#include <deque>
-#include <stdexcept>
#if LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
@@ -62,6 +61,7 @@
#include "llsingleton.h"
#include "lldependencies.h"
#include "llstl.h"
+#include "llexception.h"
/*==========================================================================*|
// override this to allow binding free functions with more parameters
@@ -95,12 +95,32 @@ struct LLStopWhenHandled
result_type operator()(InputIterator first, InputIterator last) const
{
for (InputIterator si = first; si != last; ++si)
- {
- if (*si)
- {
- return true;
- }
- }
+ {
+ try
+ {
+ if (*si)
+ {
+ return true;
+ }
+ }
+ catch (const LLContinueError&)
+ {
+ // We catch LLContinueError here because an LLContinueError-
+ // based exception means the viewer as a whole should carry on
+ // to the best of our ability. Therefore subsequent listeners
+ // on the same LLEventPump should still receive this event.
+
+ // The iterator passed to a boost::signals2 Combiner is very
+ // clever, but provides no contextual information. We would
+ // very much like to be able to log the name of the LLEventPump
+ // plus the name of this particular listener, but alas.
+ LOG_UNHANDLED_EXCEPTION("LLEventPump");
+ }
+ // We do NOT catch (...) here because we might as well let it
+ // propagate out to the generic handler. If we were able to log
+ // context information here, that would be great, but we can't, so
+ // there's no point.
+ }
return false;
}
};
@@ -188,10 +208,10 @@ public:
bool operator()(const LLSD& event) const;
/// exception if you try to call when empty
- struct Empty: public std::runtime_error
+ struct Empty: public LLException
{
Empty(const std::string& what):
- std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
+ LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {}
};
private:
@@ -371,10 +391,10 @@ public:
* you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
* variant.
*/
- struct DupPumpName: public std::runtime_error
+ struct DupPumpName: public LLException
{
DupPumpName(const std::string& what):
- std::runtime_error(std::string("DupPumpName: ") + what) {}
+ LLException(std::string("DupPumpName: ") + what) {}
};
/**
@@ -399,9 +419,9 @@ public:
/// group exceptions thrown by listen(). We use exceptions because these
/// particular errors are likely to be coding errors, found and fixed by
/// the developer even before preliminary checkin.
- struct ListenError: public std::runtime_error
+ struct ListenError: public LLException
{
- ListenError(const std::string& what): std::runtime_error(what) {}
+ ListenError(const std::string& what): LLException(what) {}
};
/**
* exception thrown by listen(). You are attempting to register a
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
new file mode 100644
index 0000000000..b32ec2c9c9
--- /dev/null
+++ b/indra/llcommon/llexception.cpp
@@ -0,0 +1,55 @@
+/**
+ * @file llexception.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-12
+ * @brief Implementation for llexception.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llexception.h"
+// STL headers
+// std headers
+#include <typeinfo>
+// external library headers
+#include <boost/exception/diagnostic_information.hpp>
+// other Linden headers
+#include "llerror.h"
+#include "llerrorcontrol.h"
+
+namespace {
+// used by crash_on_unhandled_exception_() and log_unhandled_exception_()
+void log_unhandled_exception_(LLError::ELevel level,
+ const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // log same message but allow caller-specified severity level
+ LL_VLOGS(level, "LLException") << LLError::abbreviateFile(file)
+ << "(" << line << "): Unhandled exception caught in " << pretty_function;
+ if (! context.empty())
+ {
+ LL_CONT << ": " << context;
+ }
+ LL_CONT << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL;
+}
+}
+
+void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // LL_ERRS() terminates and propagates message into crash dump.
+ log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context);
+}
+
+void log_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // Use LL_WARNS() because we seriously do not expect this to happen
+ // routinely, but we DO expect to return from this function.
+ log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function, context);
+}
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
new file mode 100644
index 0000000000..dfcb7c192f
--- /dev/null
+++ b/indra/llcommon/llexception.h
@@ -0,0 +1,85 @@
+/**
+ * @file llexception.h
+ * @author Nat Goodspeed
+ * @date 2016-06-29
+ * @brief Types needed for generic exception handling
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEXCEPTION_H)
+#define LL_LLEXCEPTION_H
+
+#include <stdexcept>
+#include <boost/exception/exception.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/current_function.hpp>
+
+// "Found someone who can comfort me
+// But there are always exceptions..."
+// - Empty Pages, Traffic, from John Barleycorn (1970)
+// https://www.youtube.com/watch?v=dRH0CGVK7ic
+
+/**
+ * LLException is intended as the common base class from which all
+ * viewer-specific exceptions are derived. Rationale for why it's derived from
+ * both std::exception and boost::exception is explained in
+ * tests/llexception_test.cpp.
+ *
+ * boost::current_exception_diagnostic_information() is quite wonderful: if
+ * all we need to do with an exception is log it, in most places we should
+ * catch (...) and log boost::current_exception_diagnostic_information().
+ * See CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() below.
+ *
+ * There may be circumstances in which it would be valuable to distinguish an
+ * exception explicitly thrown by viewer code from an exception thrown by
+ * (say) a third-party library. Catching (const LLException&) supports such
+ * usage. However, most of the value of this base class is in the
+ * diagnostic_information() available via Boost.Exception.
+ */
+struct LLException:
+ public std::runtime_error,
+ public boost::exception
+{
+ LLException(const std::string& what):
+ std::runtime_error(what)
+ {}
+};
+
+/**
+ * The point of LLContinueError is to distinguish exceptions that need not
+ * terminate the whole viewer session. In general, an uncaught exception will
+ * be logged and will crash the viewer. However, though an uncaught exception
+ * derived from LLContinueError will still be logged, the viewer will attempt
+ * to continue processing.
+ */
+struct LLContinueError: public LLException
+{
+ LLContinueError(const std::string& what):
+ LLException(what)
+ {}
+};
+
+/**
+ * Please use LLTHROW() to throw viewer exceptions whenever possible. This
+ * enriches the exception's diagnostic_information() with the source file,
+ * line and containing function of the LLTHROW() macro.
+ */
+// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in
+// LLTHROW() in case we ever want to revisit that implementation decision.
+#define LLTHROW(x) BOOST_THROW_EXCEPTION(x)
+
+/// Call this macro from a catch (...) clause
+#define CRASH_ON_UNHANDLED_EXCEPTION(CONTEXT) \
+ crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void crash_on_unhandled_exception_(const char*, int, const char*, const std::string&);
+
+/// Call this from a catch (const LLContinueError&) clause, or from a catch
+/// (...) clause in which you do NOT want the viewer to crash.
+#define LOG_UNHANDLED_EXCEPTION(CONTEXT) \
+ log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void log_unhandled_exception_(const char*, int, const char*, const std::string&);
+
+#endif /* ! defined(LL_LLEXCEPTION_H) */
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 2370253078..f56e5596f5 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -296,7 +296,16 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
{
#if LL_FAST_TIMER_ON
BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- if (!cur_timer_data) return;
+ if (!cur_timer_data)
+ {
+ // How likely is it that
+ // LLThreadLocalSingletonPointer<T>::getInstance() will return NULL?
+ // Even without researching, what we can say is that if we exit
+ // without setting mStartTime at all, gcc 4.7 produces (fatal)
+ // warnings about a possibly-uninitialized data member.
+ mStartTime = 0;
+ return;
+ }
TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
accumulator.mActiveCount++;
// keep current parent as long as it is active when we are
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 84d2a12f65..c87d2a3e58 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -33,6 +33,7 @@
#include "lltimer.h"
#include "lluuid.h"
#include "llleaplistener.h"
+#include "llexception.h"
#if LL_MSVC
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
@@ -69,7 +70,7 @@ public:
// Rule out empty vector
if (plugin.empty())
{
- throw Error("no plugin command");
+ LLTHROW(Error("no plugin command"));
}
// Don't leave desc empty either, but in this case, if we weren't
@@ -112,7 +113,7 @@ public:
// If that didn't work, no point in keeping this LLLeap object.
if (! mChild)
{
- throw Error(STRINGIZE("failed to run " << mDesc));
+ LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));
}
// Okay, launch apparently worked. Change our mDonePump listener.
diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h
index e33f25e530..8aac8a64c5 100644
--- a/indra/llcommon/llleap.h
+++ b/indra/llcommon/llleap.h
@@ -13,9 +13,9 @@
#define LL_LLLEAP_H
#include "llinstancetracker.h"
+#include "llexception.h"
#include <string>
#include <vector>
-#include <stdexcept>
/**
* LLSD Event API Plugin class. Because instances are managed by
@@ -67,9 +67,9 @@ public:
* string(s) passed to create() might come from an external source. This
* way the caller can catch LLLeap::Error and try to recover.
*/
- struct Error: public std::runtime_error
+ struct Error: public LLException
{
- Error(const std::string& what): std::runtime_error(what) {}
+ Error(const std::string& what): LLException(what) {}
};
virtual ~LLLeap();
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 0fb257aab1..575edddc43 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -110,11 +110,15 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
#else
+ char* aligned = NULL;
void* mem = malloc( size + (align - 1) + sizeof(void*) );
- char* aligned = ((char*)mem) + sizeof(void*);
- aligned += align - ((uintptr_t)aligned & (align - 1));
+ if (mem)
+ {
+ aligned = ((char*)mem) + sizeof(void*);
+ aligned += align - ((uintptr_t)aligned & (align - 1));
- ((void**)aligned)[-1] = mem;
+ ((void**)aligned)[-1] = mem;
+ }
return aligned;
#endif
}
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 44f56daf2d..8c321d06b9 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -34,6 +34,7 @@
#include "llapr.h"
#include "apr_signal.h"
#include "llevents.h"
+#include "llexception.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
@@ -472,9 +473,9 @@ private:
*****************************************************************************/
/// Need an exception to avoid constructing an invalid LLProcess object, but
/// internal use only
-struct LLProcessError: public std::runtime_error
+struct LLProcessError: public LLException
{
- LLProcessError(const std::string& msg): std::runtime_error(msg) {}
+ LLProcessError(const std::string& msg): LLException(msg) {}
};
LLProcessPtr LLProcess::create(const LLSDOrParams& params)
@@ -530,8 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
if (! params.validateBlock(true))
{
- throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
- << LLSDNotationStreamer(params)));
+ LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
+ << LLSDNotationStreamer(params))));
}
mPostend = params.postend;
@@ -596,10 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):
}
else
{
- throw LLProcessError(STRINGIZE("For " << params.executable()
- << ": unsupported FileParam for " << which
- << ": type='" << fparam.type()
- << "', name='" << fparam.name() << "'"));
+ LLTHROW(LLProcessError(STRINGIZE("For " << params.executable()
+ << ": unsupported FileParam for " << which
+ << ": type='" << fparam.type()
+ << "', name='" << fparam.name() << "'")));
}
}
// By default, pass APR_NO_PIPE for unspecified slots.
@@ -678,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
gAPRPoolp)))
{
- throw LLProcessError(STRINGIZE(params << " failed"));
+ LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
}
// arrange to call status_callback()
@@ -1063,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)
PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
if (! wp)
{
- throw NoPipe(error);
+ LLTHROW(NoPipe(error));
}
return *wp;
}
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 43ccadc412..bfac4567a5 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -30,13 +30,13 @@
#include "llinitparam.h"
#include "llsdparam.h"
#include "llwin32headerslean.h"
+#include "llexception.h"
#include "apr_thread_proc.h"
#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/optional.hpp>
#include <boost/noncopyable.hpp>
#include <iosfwd> // std::ostream
-#include <stdexcept>
#if LL_WINDOWS
#include "llwin32headerslean.h" // for HANDLE
@@ -479,9 +479,9 @@ public:
/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
/// create a pipe at the corresponding FILESLOT.
- struct NoPipe: public std::runtime_error
+ struct NoPipe: public LLException
{
- NoPipe(const std::string& what): std::runtime_error(what) {}
+ NoPipe(const std::string& what): LLException(what) {}
};
/**
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index f3b8999883..c45db3b185 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -576,6 +576,33 @@ std::string utf8str_truncate(const std::string& utf8str, const S32 max_len)
}
}
+std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len)
+{
+ if (0 == symbol_len)
+ {
+ return std::string();
+ }
+ if ((S32)utf8str.length() <= symbol_len)
+ {
+ return utf8str;
+ }
+ else
+ {
+ int len = 0, byteIndex = 0;
+ const char* aStr = utf8str.c_str();
+ size_t origSize = utf8str.size();
+
+ for (byteIndex = 0; len < symbol_len && byteIndex < origSize; byteIndex++)
+ {
+ if ((aStr[byteIndex] & 0xc0) != 0x80)
+ {
+ len += 1;
+ }
+ }
+ return utf8str.substr(0, byteIndex);
+ }
+}
+
std::string utf8str_substChar(
const std::string& utf8str,
const llwchar target_char,
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 393f6d7a8c..a40db0f8cc 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -564,6 +564,17 @@ LL_COMMON_API S32 utf8str_compare_insensitive(
const std::string& rhs);
/**
+* @brief Properly truncate a utf8 string to a maximum character count.
+*
+* If symbol_len is longer than the string passed in, the return
+* value == utf8str.
+* @param utf8str A valid utf8 string to truncate.
+* @param symbol_len The maximum number of symbols in the return value.
+* @return Returns a valid utf8 string with symbol count <= max_len.
+*/
+LL_COMMON_API std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len);
+
+/**
* @brief Replace all occurences of target_char with replace_char
*
* @param utf8str A utf8 string to process.
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
index 185f0d63fb..491f920c0f 100644
--- a/indra/llcommon/llthreadsafequeue.cpp
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -27,6 +27,7 @@
#include <apr_pools.h>
#include <apr_queue.h>
#include "llthreadsafequeue.h"
+#include "llexception.h"
@@ -41,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
{
if(mOwnsPool) {
apr_status_t status = apr_pool_create(&mPool, 0);
- if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool");
+ if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));
} else {
; // No op.
}
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
- if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue");
+ if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
}
@@ -68,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)
apr_status_t status = apr_queue_push(mQueue, element);
if(status == APR_EINTR) {
- throw LLThreadSafeQueueInterrupt();
+ LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
- throw LLThreadSafeQueueError("push failed");
+ LLTHROW(LLThreadSafeQueueError("push failed"));
} else {
; // Success.
}
@@ -88,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)
apr_status_t status = apr_queue_pop(mQueue, &element);
if(status == APR_EINTR) {
- throw LLThreadSafeQueueInterrupt();
+ LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
- throw LLThreadSafeQueueError("pop failed");
+ LLTHROW(LLThreadSafeQueueError("pop failed"));
} else {
return element;
}
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 58cac38769..45289ef0b4 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -27,9 +27,8 @@
#ifndef LL_LLTHREADSAFEQUEUE_H
#define LL_LLTHREADSAFEQUEUE_H
-
+#include "llexception.h"
#include <string>
-#include <stdexcept>
struct apr_pool_t; // From apr_pools.h
@@ -40,11 +39,11 @@ class LLThreadSafeQueueImplementation; // See below.
// A general queue exception.
//
class LL_COMMON_API LLThreadSafeQueueError:
-public std::runtime_error
+ public LLException
{
public:
LLThreadSafeQueueError(std::string const & message):
- std::runtime_error(message)
+ LLException(message)
{
; // No op.
}
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index e3671047b4..d4af2c6b01 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data )
unsigned int ret = 0;
for( int ix = 0; ix < 5; ++ix ) {
char * s = strchr( encodeTable, fiveChars[ ix ] );
-if( s == 0 ) throw bad_input_data();
+if( s == 0 ) LLTHROW(bad_input_data());
ret = ret * 85 + (s-encodeTable);
}
return ret;
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index f51279e817..8bace8ac41 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -237,8 +237,21 @@ namespace tut
void ErrorTestObject::test<4>()
// file abbreviation
{
- std::string thisFile = __FILE__;
- std::string abbreviateFile = LLError::abbreviateFile(thisFile);
+ std::string prev, abbreviateFile = __FILE__;
+ do
+ {
+ prev = abbreviateFile;
+ abbreviateFile = LLError::abbreviateFile(abbreviateFile);
+ // __FILE__ is assumed to end with
+ // indra/llcommon/tests/llerror_test.cpp. This test used to call
+ // abbreviateFile() exactly once, then check below whether it
+ // still contained the string 'indra'. That fails if the FIRST
+ // part of the pathname also contains indra! Certain developer
+ // machine images put local directory trees under
+ // /ngi-persist/indra, which is where we observe the problem. So
+ // now, keep calling abbreviateFile() until it returns its
+ // argument unchanged, THEN check.
+ } while (abbreviateFile != prev);
ensure_ends_with("file name abbreviation",
abbreviateFile,
diff --git a/indra/llcommon/tests/llexception_test.cpp b/indra/llcommon/tests/llexception_test.cpp
new file mode 100644
index 0000000000..6bee1943c2
--- /dev/null
+++ b/indra/llcommon/tests/llexception_test.cpp
@@ -0,0 +1,308 @@
+/**
+ * @file llexception_test.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-12
+ * @brief Tests for throwing exceptions.
+ *
+ * This isn't a regression test: it doesn't need to be run every build, which
+ * is why the corresponding line in llcommon/CMakeLists.txt is commented out.
+ * Rather it's a head-to-head test of what kind of exception information we
+ * can collect from various combinations of exception base classes, type of
+ * throw verb and sequences of catch clauses.
+ *
+ * This "test" makes no ensure() calls: its output goes to stdout for human
+ * examination.
+ *
+ * As of 2016-08-12 with Boost 1.57, we come to the following conclusions.
+ * These should probably be re-examined from time to time as we update Boost.
+ *
+ * - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than
+ * plain throw. The macro annotates the exception object with the filename,
+ * line number and function name from which the exception was thrown.
+ *
+ * - That being the case, deriving only from boost::exception isn't an option.
+ * Every exception object passed to BOOST_THROW_EXCEPTION() must be derived
+ * directly or indirectly from std::exception. The only question is whether
+ * to also derive from boost::exception. We decided to derive LLException
+ * from both, as it makes message output slightly cleaner, but this is a
+ * trivial reason: if a strong reason emerges to prefer single inheritance,
+ * dropping the boost::exception base class shouldn't be a problem.
+ *
+ * - (As you will have guessed, ridiculous things like a char* or int or a
+ * class derived from neither boost::exception nor std::exception can only
+ * be caught by that specific type or (...), and
+ * boost::current_exception_diagnostic_information() simply throws up its
+ * hands and confesses utter ignorance. Stay away from such nonsense.)
+ *
+ * - But if you derive from std::exception, to nat's surprise,
+ * boost::current_exception_diagnostic_information() gives as much
+ * information about exceptions in a catch (...) clause as you can get from
+ * a specific catch (const std::exception&) clause, notably the concrete
+ * exception class and the what() string. So instead of a sequence like
+ *
+ * try { ... }
+ * catch (const boost::exception& e) { ... boost-flavored logging ... }
+ * catch (const std::exception& e) { ... std::exception logging ... }
+ * catch (...) { ... generic logging ... }
+ *
+ * we should be able to get away with only a catch (...) clause that logs
+ * boost::current_exception_diagnostic_information().
+ *
+ * - Going further: boost::current_exception_diagnostic_information() provides
+ * just as much information even within a std::set_terminate() handler. So
+ * it might not even be strictly necessary to include a catch (...) clause
+ * since the viewer does use std::set_terminate().
+ *
+ * - (We might consider adding a catch (int) clause because Kakadu internally
+ * throws ints, and who knows if one of those might leak out. If it does,
+ * boost::current_exception_diagnostic_information() can do nothing with it.
+ * A catch (int) clause could at least log the value and rethrow.)
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llexception.h"
+// STL headers
+// std headers
+#include <typeinfo>
+// external library headers
+#include <boost/throw_exception.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+// helper for display output
+// usage: std::cout << center(some string value, fill char, width) << std::endl;
+// (assumes it's the only thing on that particular line)
+struct center
+{
+ center(const std::string& label, char fill, std::size_t width):
+ mLabel(label),
+ mFill(fill),
+ mWidth(width)
+ {}
+
+ // Use friend declaration not because we need to grant access, but because
+ // it lets us declare a free operator like a member function.
+ friend std::ostream& operator<<(std::ostream& out, const center& ctr)
+ {
+ std::size_t padded = ctr.mLabel.length() + 2;
+ std::size_t left = (ctr.mWidth - padded) / 2;
+ std::size_t right = ctr.mWidth - left - padded;
+ return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' '
+ << std::string(right, ctr.mFill);
+ }
+
+ std::string mLabel;
+ char mFill;
+ std::size_t mWidth;
+};
+
+/*****************************************************************************
+* Four kinds of exceptions: derived from boost::exception, from
+* std::exception, from both, from neither
+*****************************************************************************/
+// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION()
+// (which we want) -- we reach a failure topped by this comment:
+// //All boost exceptions are required to derive from std::exception,
+// //to ensure compatibility with BOOST_NO_EXCEPTIONS.
+struct FromBoost: public boost::exception
+{
+ FromBoost(const std::string& what): mWhat(what) {}
+ ~FromBoost() throw() {}
+ std::string what() const { return mWhat; }
+ std::string mWhat;
+};
+
+struct FromStd: public std::runtime_error
+{
+ FromStd(const std::string& what): std::runtime_error(what) {}
+};
+
+struct FromBoth: public boost::exception, public std::runtime_error
+{
+ FromBoth(const std::string& what): std::runtime_error(what) {}
+};
+
+// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION().
+struct FromNeither
+{
+ FromNeither(const std::string& what): mWhat(what) {}
+ std::string what() const { return mWhat; }
+ std::string mWhat;
+};
+
+/*****************************************************************************
+* Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION()
+*****************************************************************************/
+template <typename EXC>
+void plain_throw(const std::string& what)
+{
+ throw EXC(what);
+}
+
+template <typename EXC>
+void boost_throw(const std::string& what)
+{
+ BOOST_THROW_EXCEPTION(EXC(what));
+}
+
+// Okay, for completeness, functions that throw non-class values. We wouldn't
+// even deign to consider these if we hadn't found examples in our own source
+// code! (Note that Kakadu's internal exception support is still based on
+// throwing ints.)
+void throw_char_ptr(const std::string& what)
+{
+ throw what.c_str(); // umm...
+}
+
+void throw_int(const std::string& what)
+{
+ throw int(what.length());
+}
+
+/*****************************************************************************
+* Three sequences of catch clauses:
+* boost::exception then ...,
+* std::exception then ...,
+* or just ...
+*****************************************************************************/
+void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (const boost::exception& e)
+ {
+ std::cout << "catch (const boost::exception& e)" << std::endl;
+ std::cout << "e is " << typeid(e).name() << std::endl;
+ std::cout << "boost::diagnostic_information(e):\n'"
+ << boost::diagnostic_information(e) << "'" << std::endl;
+ // no way to report e.what()
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "catch (const std::exception& e)" << std::endl;
+ std::cout << "e is " << typeid(e).name() << std::endl;
+ std::cout << "boost::diagnostic_information(e):\n'"
+ << boost::diagnostic_information(e) << "'" << std::endl;
+ std::cout << "e.what: '"
+ << e.what() << "'" << std::endl;
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+/*****************************************************************************
+* Try a particular kind of throw against each of three catch sequences
+*****************************************************************************/
+void catch_several(void (*thrower)(const std::string&), const std::string& what)
+{
+ std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl;
+ catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")");
+
+ std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl;
+ catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")");
+
+ std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl;
+ catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")");
+}
+
+/*****************************************************************************
+* For a particular kind of exception, try both kinds of throw against all
+* three catch sequences
+*****************************************************************************/
+template <typename EXC>
+void catch_both_several(const std::string& what)
+{
+ std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl;
+ catch_several(plain_throw<EXC>, "plain_throw<" + what + ">");
+
+ std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl;
+ catch_several(boost_throw<EXC>, "boost_throw<" + what + ">");
+}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llexception_data
+ {
+ };
+ typedef test_group<llexception_data> llexception_group;
+ typedef llexception_group::object object;
+ llexception_group llexceptiongrp("llexception");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("throwing exceptions");
+
+ // For each kind of exception, try both kinds of throw against all
+ // three catch sequences
+ std::size_t margin = 72;
+ std::cout << center("FromStd", '=', margin) << std::endl;
+ catch_both_several<FromStd>("FromStd");
+
+ std::cout << center("FromBoth", '=', margin) << std::endl;
+ catch_both_several<FromBoth>("FromBoth");
+
+ std::cout << center("FromBoost", '=', margin) << std::endl;
+ // can't throw with BOOST_THROW_EXCEPTION(), just use catch_several()
+ catch_several(plain_throw<FromBoost>, "plain_throw<FromBoost>");
+
+ std::cout << center("FromNeither", '=', margin) << std::endl;
+ // can't throw this with BOOST_THROW_EXCEPTION() either
+ catch_several(plain_throw<FromNeither>, "plain_throw<FromNeither>");
+
+ std::cout << center("const char*", '=', margin) << std::endl;
+ // We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft
+ // as a const char* or an int, so don't bother with
+ // catch_both_several() -- just catch_several().
+ catch_several(throw_char_ptr, "throw_char_ptr");
+
+ std::cout << center("int", '=', margin) << std::endl;
+ catch_several(throw_int, "throw_int");
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 785197ba11..9a4bbbd630 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -35,13 +35,13 @@
#include <tut/tut.hpp>
#include "llerrorcontrol.h"
+#include "llexception.h"
#include "stringize.h"
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <list>
#include <string>
-#include <stdexcept>
// statically reference the function in test.cpp... it's short, we could
// replicate, but better to reuse
@@ -67,9 +67,9 @@ struct WrapLLErrs
LLError::restoreSettings(mPriorErrorSettings);
}
- struct FatalException: public std::runtime_error
+ struct FatalException: public LLException
{
- FatalException(const std::string& what): std::runtime_error(what) {}
+ FatalException(const std::string& what): LLException(what) {}
};
void operator()(const std::string& message)
@@ -78,7 +78,7 @@ struct WrapLLErrs
error = message;
// Also throw an appropriate exception since calling code is likely to
// assume that control won't continue beyond LL_ERRS.
- throw FatalException(message);
+ LLTHROW(FatalException(message));
}
std::string error;
diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h
index 8b4afae24a..56e26c23ba 100644
--- a/indra/llcrashlogger/llcrashlogger.h
+++ b/indra/llcrashlogger/llcrashlogger.h
@@ -57,7 +57,7 @@ public:
LLSD constructPostData();
virtual void updateApplication(const std::string& message = LLStringUtil::null);
virtual bool init();
- virtual bool mainLoop() = 0;
+ virtual bool frame() = 0;
virtual bool cleanup() = 0;
void commonCleanup();
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 91fa8c6ad1..f331c533fd 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1401,7 +1401,12 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
{
- llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
+ S32 components = getComponents();
+ if (! ((1 == components) || (3 == components) || (4 == components) ))
+ {
+ LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
+ return false;
+ }
S32 old_width = getWidth();
S32 old_height = getHeight();
@@ -1415,67 +1420,53 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
if (scale_image_data)
{
- /*
- S32 temp_data_size = old_width * new_height * getComponents();
- llassert_always(temp_data_size > 0);
- std::vector<U8> temp_buffer(temp_data_size);
-
- // Vertical
- for( S32 col = 0; col < old_width; col++ )
- {
- copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width );
- }
-
- deleteData();
+ S32 new_data_size = new_width * new_height * components;
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
+ if (new_data_size > 0)
+ {
+ U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
+ if(NULL == new_data)
+ {
+ return false;
+ }
- // Horizontal
- for( S32 row = 0; row < new_height; row++ )
- {
- copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
- }
- */
-
- S32 new_data_size = new_width * new_height * getComponents();
- llassert_always(new_data_size > 0);
-
- U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
- if(NULL == new_data)
- {
- return false;
+ bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components);
+ setDataAndSize(new_data, new_width, new_height, components);
}
-
- bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents());
- setDataAndSize(new_data, new_width, new_height, getComponents());
}
else
{
// copy out existing image data
- S32 temp_data_size = old_width * old_height * getComponents();
+ S32 temp_data_size = old_width * old_height * components;
std::vector<U8> temp_buffer(temp_data_size);
memcpy(&temp_buffer[0], getData(), temp_data_size);
// allocate new image data, will delete old data
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
-
- for( S32 row = 0; row < new_height; row++ )
- {
- if (row < old_height)
- {
- memcpy(new_buffer + (new_width * row * getComponents()), &temp_buffer[0] + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width));
- if (old_width < new_width)
- {
- // pad out rest of row with black
- memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
- }
- }
- else
- {
- // pad remaining rows with black
- memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
- }
- }
+ U8* new_buffer = allocateDataSize(new_width, new_height, components);
+
+ if (!new_buffer)
+ {
+ LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL;
+ return false;
+ }
+
+ for( S32 row = 0; row < new_height; row++ )
+ {
+ if (row < old_height)
+ {
+ memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width));
+ if (old_width < new_width)
+ {
+ // pad out rest of row with black
+ memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width));
+ }
+ }
+ else
+ {
+ // pad remaining rows with black
+ memset(new_buffer + (new_width * row * components), 0, new_width * components);
+ }
+ }
}
return true ;
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index aad139f570..da289ea889 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -31,6 +31,16 @@
#include "llimage.h"
#include "llpngwrapper.h"
+#include "llexception.h"
+
+namespace {
+// Failure to load an image shouldn't crash the whole viewer.
+struct PngError: public LLContinueError
+{
+ PngError(png_const_charp msg): LLContinueError(msg) {}
+};
+} // anonymous namespace
+
// ---------------------------------------------------------------------------
// LLPngWrapper
// ---------------------------------------------------------------------------
@@ -75,11 +85,10 @@ BOOL LLPngWrapper::isValidPng(U8* src)
}
// Called by the libpng library when a fatal encoding or decoding error
-// occurs. We simply throw the error message and let our try/catch
-// block clean up.
+// occurs. We throw PngError and let our try/catch block clean up.
void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)
{
- throw msg;
+ LLTHROW(PngError(msg));
}
// Called by the libpng library when reading (decoding) the PNG file. We
@@ -129,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
this, &errorHandler, NULL);
if (mReadPngPtr == NULL)
{
- throw "Problem creating png read structure";
+ LLTHROW(PngError("Problem creating png read structure"));
}
// Allocate/initialize the memory for image information.
@@ -187,9 +196,9 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
mFinalSize = dataPtr.mOffset;
}
- catch (png_const_charp msg)
+ catch (const PngError& msg)
{
- mErrorMessage = msg;
+ mErrorMessage = msg.what();
releaseResources();
return (FALSE);
}
@@ -288,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
if (mColorType == -1)
{
- throw "Unsupported image: unexpected number of channels";
+ LLTHROW(PngError("Unsupported image: unexpected number of channels"));
}
mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, &errorHandler, NULL);
if (!mWritePngPtr)
{
- throw "Problem creating png write structure";
+ LLTHROW(PngError("Problem creating png write structure"));
}
mWriteInfoPtr = png_create_info_struct(mWritePngPtr);
@@ -339,9 +348,9 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
png_write_end(mWritePngPtr, mWriteInfoPtr);
mFinalSize = dataPtr.mOffset;
}
- catch (png_const_charp msg)
+ catch (const PngError& msg)
{
- mErrorMessage = msg;
+ mErrorMessage = msg.what();
releaseResources();
return (FALSE);
}
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 025c77b85e..0ed6ffefa9 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -1,4 +1,4 @@
- /**
+/**
* @file llimagej2ckdu.cpp
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
*
@@ -35,16 +35,51 @@
#include "kdu_block_coding.h"
-#include <stdexcept>
-#include <iostream>
+#include "llexception.h"
+#include <boost/exception/diagnostic_information.hpp>
+#include <sstream>
+#include <iomanip>
namespace {
-// exception used to keep KDU from terminating entire program -- see comments
-// in LLKDUMessageError::flush()
-struct KDUError: public std::runtime_error
+// Failure to load an image shouldn't crash the whole viewer.
+struct KDUError: public LLContinueError
{
- KDUError(const std::string& msg): std::runtime_error(msg) {}
+ KDUError(const std::string& msg): LLContinueError(msg) {}
};
+
+// KDU defines int error codes as hex values, so we should log them in hex
+// so we can grep KDU headers for the hex. However those hex values
+// generally "happen" to encode big-endian multibyte character sequences,
+// e.g. KDU_ERROR_EXCEPTION is 0x6b647545: 'kduE'
+// But beware because KDU_NULL_EXCEPTION is simply 0 -- which doesn't
+// preclude somebody from throwing it.
+std::string report_kdu_exception(kdu_exception mb)
+{
+ std::ostringstream out;
+ // always report mb in hex
+ out << "kdu_exception " << std::hex << mb;
+
+ // Also display as many chars as are encoded in the kdu_exception
+ // value. Make a char array; reserve 1 extra byte for nul terminator.
+ char bytes[sizeof(kdu_exception) + 1];
+ // Back up through 'bytes'
+ char *bptr = bytes + sizeof(bytes);
+ *(--bptr) = '\0';
+ while (mb)
+ {
+ // store low-order byte of mb in next-left char
+ *(--bptr) = char(mb & 0xFF);
+ // then shift mb right by one byte
+ mb >>= 8;
+ }
+ // did that produce any characters?
+ if (*bptr)
+ {
+ out << " (" << bptr << ')';
+ }
+
+ return out.str();
+}
} // anonymous namespace
// stream kdu_dims to std::ostream
@@ -195,7 +230,7 @@ struct LLKDUMessageError : public LLKDUMessage
// shutdown will NOT engage the behavior described above.
if (end_of_message)
{
- throw KDUError("LLKDUMessageError::flush()");
+ LLTHROW(KDUError("LLKDUMessageError::flush()"));
}
}
};
@@ -439,9 +474,19 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch (...)
{
- base.setLastError("Unknown J2C error");
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -537,9 +582,21 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
cleanupCodeStream();
return true; // done
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ base.decodeFailed();
+ cleanupCodeStream();
+ return true; // done
+ }
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
base.decodeFailed();
cleanupCodeStream();
return true; // done
@@ -728,9 +785,19 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch( ... )
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -752,9 +819,19 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
base.setLastError(msg.what());
return false;
}
+ catch (kdu_exception kdu_value)
+ {
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
+ return false;
+ }
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
}
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 4be677a4b0..0f23754096 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -181,6 +181,10 @@ protected:
// Map of known bad assets
typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
+// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
+// future project would be to convert these to C++ callables (std::function<>) so that
+// we can use bind and remove the userData parameter.
+//
typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
diff --git a/indra/llmessage/llavatarname.cpp b/indra/llmessage/llavatarname.cpp
index d12f157910..d2115ee499 100644
--- a/indra/llmessage/llavatarname.cpp
+++ b/indra/llmessage/llavatarname.cpp
@@ -166,7 +166,7 @@ void LLAvatarName::setExpires(F64 expires)
mExpires = LLFrameTimer::getTotalSeconds() + expires;
}
-std::string LLAvatarName::getCompleteName() const
+std::string LLAvatarName::getCompleteName(bool use_parentheses) const
{
std::string name;
if (sUseDisplayNames)
@@ -182,7 +182,14 @@ std::string LLAvatarName::getCompleteName() const
name = mDisplayName;
if(sUseUsernames)
{
- name += " (" + mUsername + ")";
+ if(use_parentheses)
+ {
+ name += " (" + mUsername + ")";
+ }
+ else
+ {
+ name += " [ " + mUsername + " ]";
+ }
}
}
}
@@ -220,7 +227,7 @@ std::string LLAvatarName::getDisplayName() const
}
}
-std::string LLAvatarName::getUserName() const
+std::string LLAvatarName::getUserName(bool lowercase) const
{
std::string name;
if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
@@ -238,7 +245,15 @@ std::string LLAvatarName::getUserName() const
}
else
{
- name = mLegacyFirstName + " " + mLegacyLastName;
+ if(lowercase)
+ {
+ name = mLegacyFirstName + "." + mLegacyLastName;
+ LLStringUtil::toLower(name);
+ }
+ else
+ {
+ name = mLegacyFirstName + " " + mLegacyLastName;
+ }
}
return name;
}
diff --git a/indra/llmessage/llavatarname.h b/indra/llmessage/llavatarname.h
index 1cb3ae421f..192f43f07c 100644
--- a/indra/llmessage/llavatarname.h
+++ b/indra/llmessage/llavatarname.h
@@ -65,7 +65,7 @@ public:
// For normal names, returns "James Linden (james.linden)"
// When display names are disabled returns just "James Linden"
- std::string getCompleteName() const;
+ std::string getCompleteName(bool use_parentheses = true) const;
// Returns "James Linden" or "bobsmith123 Resident" for backwards
// compatibility with systems like voice and muting
@@ -80,7 +80,7 @@ public:
// Returns "James Linden" or "bobsmith123 Resident"
// Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
// Also used for backwards compatibility with systems like voice and muting
- std::string getUserName() const;
+ std::string getUserName(bool lowercase = false) const;
// Returns "james.linden" or the legacy name for very old names
std::string getAccountName() const { return mUsername; }
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 1ca5f58ae2..004db546b7 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -43,6 +43,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include "llexception.h"
+#include "stringize.h"
#include <map>
#include <set>
@@ -231,13 +233,12 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
}
- catch (std::exception e)
- {
- LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << url << "', " << agentIds.size()
+ << " Agent Ids)"));
+ throw;
}
}
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index d4c0788b7d..74cdff2b00 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -27,6 +27,8 @@
#include "linden_common.h"
#include "llcoproceduremanager.h"
+#include "llexception.h"
+#include "stringize.h"
#include <boost/assign.hpp>
//=========================================================================
@@ -388,14 +390,14 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap
{
coproc->mProc(httpAdapter, coproc->mId);
}
- catch (std::exception &e)
- {
- LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() <<
- " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("Coprocedure('" << coproc->mName
+ << "', id=" << coproc->mId.asString()
+ << ") in pool '" << mPoolName << "'"));
+ // must NOT omit this or we deplete the pool
+ mActiveCoprocs.erase(itActive);
+ throw;
}
LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL;
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index f235965879..04b34a296c 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -31,6 +31,7 @@
#include "llstl.h"
#include "llhttpconstants.h"
+#include "llexception.h"
const std::string CONTEXT_HEADERS("headers");
const std::string CONTEXT_PATH("path");
@@ -92,27 +93,28 @@ LLHTTPNode::~LLHTTPNode()
namespace {
- class NotImplemented
+ struct NotImplemented: public LLException
{
+ NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}
};
}
// virtual
LLSD LLHTTPNode::simpleGet() const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePut(const LLSD& input) const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePost(const LLSD& input) const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
@@ -172,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
// virtual
LLSD LLHTTPNode::simpleDel(const LLSD&) const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
// virtual
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h
index 0d149b5258..7c8f27bbd2 100644
--- a/indra/llmessage/tests/commtest.h
+++ b/indra/llmessage/tests/commtest.h
@@ -33,15 +33,15 @@
#include "llevents.h"
#include "llsd.h"
#include "llhost.h"
+#include "llexception.h"
#include "stringize.h"
#include <map>
#include <string>
-#include <stdexcept>
#include <boost/lexical_cast.hpp>
-struct CommtestError: public std::runtime_error
+struct CommtestError: public LLException
{
- CommtestError(const std::string& what): std::runtime_error(what) {}
+ CommtestError(const std::string& what): LLException(what) {}
};
static bool query_verbose()
@@ -68,7 +68,7 @@ static int query_port(const std::string& var)
const char* cport = getenv(var.c_str());
if (! cport)
{
- throw CommtestError(STRINGIZE("missing environment variable" << var));
+ LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var)));
}
// This will throw, too, if the value of PORT isn't numeric.
int port(boost::lexical_cast<int>(cport));
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 2aff90ca1e..5eb739393f 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -34,6 +34,7 @@
#include "llares.h"
#include "llpumpio.h"
#include "llhttpclient.h"
+#include "llexception.h"
/*****************************************************************************
* NetworkIO
@@ -51,7 +52,7 @@ public:
ll_init_apr();
if (! gAPRPoolp)
{
- throw std::runtime_error("Can't initialize APR");
+ LLTHROW(LLException("Can't initialize APR"));
}
// Create IO Pump to use for HTTP Requests.
@@ -59,7 +60,7 @@ public:
LLHTTPClient::setPump(*mServicePump);
if (ll_init_ares() == NULL || !gAres->isInitialized())
{
- throw std::runtime_error("Can't start DNS resolver");
+ LLTHROW(LLException("Can't start DNS resolver"));
}
// You can interrupt pump() without waiting the full timeout duration
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 720986a411..00bde8dbc3 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2235,7 +2235,11 @@ std::string LLDAELoader::getElementLabel(daeElement *element)
// retrieve index to distinguish items inside same parent
size_t ind = 0;
parent->getChildren().find(element, ind);
- index_string = "_" + boost::lexical_cast<std::string>(ind);
+
+ if (ind > 0)
+ {
+ index_string = "_" + boost::lexical_cast<std::string>(ind);
+ }
// if parent has a name or ID, use it
std::string name = parent->getAttribute("name");
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index b30bc1aed6..58c1186a3e 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -349,8 +349,8 @@ void LLGLSLShader::unloadInternal()
for (GLsizei i = 0; i < count; i++)
{
glDetachObjectARB(mProgramObject, obj[i]);
- glDeleteObjectARB(obj[i]);
- }
+ glDeleteObjectARB(obj[i]);
+ }
glDeleteObjectARB(mProgramObject);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index b297223c2e..55f0791174 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -520,7 +520,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
if (!filename.empty())
{
LL_CONT << "From " << filename << ":\n";
- }
+ }
LL_CONT << log << LL_ENDL;
}
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 14f75a2352..1f9869fadc 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1326,7 +1326,7 @@ void LLFloater::setMinimized(BOOL minimize)
}
mMinimized = FALSE;
-
+ setFrontmost();
// Reshape *after* setting mMinimized
reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE );
}
@@ -1575,6 +1575,7 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
if(offerClickToButton(x, y, mask, BUTTON_TEAR_OFF)) return TRUE;
if(offerClickToButton(x, y, mask, BUTTON_DOCK)) return TRUE;
+ setFrontmost(TRUE, FALSE);
// Otherwise pass to drag handle for movement
return mDragHandle->handleMouseDown(x, y, mask);
}
@@ -1649,7 +1650,7 @@ void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
}
}
-void LLFloater::setFrontmost(BOOL take_focus)
+void LLFloater::setFrontmost(BOOL take_focus, BOOL restore)
{
LLMultiFloater* hostp = getHost();
if (hostp)
@@ -1665,7 +1666,7 @@ void LLFloater::setFrontmost(BOOL take_focus)
LLFloaterView * parent = dynamic_cast<LLFloaterView*>( getParent() );
if (parent)
{
- parent->bringToFront(this, take_focus);
+ parent->bringToFront(this, take_focus, restore);
}
// Make sure to set the appropriate transparency type (STORM-732).
@@ -2262,7 +2263,7 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
LLView* viewp = *child_it;
- LLFloater* floaterp = (LLFloater*)viewp;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
if (floaterp->isDependent())
{
// dependents are moved with their "dependee"
@@ -2319,8 +2320,11 @@ void LLFloaterView::restoreAll()
// make sure all subwindows aren't minimized
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
- LLFloater* floaterp = (LLFloater*)*child_it;
- floaterp->setMinimized(FALSE);
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
+ if (floaterp)
+ {
+ floaterp->setMinimized(FALSE);
+ }
}
// *FIX: make sure dependents are restored
@@ -2394,7 +2398,7 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
}
-void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
+void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore)
{
if (!child)
return;
@@ -2478,7 +2482,12 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
{
sendChildToFront(child);
}
- child->setMinimized(FALSE);
+
+ if(restore)
+ {
+ child->setMinimized(FALSE);
+ }
+
if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
{
child->setFocus(TRUE);
@@ -2591,7 +2600,7 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
++child_it) //loop floaters
{
// Examine minimized children.
- LLFloater* floater = (LLFloater*)((LLView*)*child_it);
+ LLFloater* floater = dynamic_cast<LLFloater*>(*child_it);
if(floater->isMinimized())
{
LLRect r = floater->getRect();
@@ -2644,7 +2653,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
continue;
}
- LLFloater* floaterp = (LLFloater*)viewp;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
// Attempt to close floater. This will cause the "do you want to save"
// dialogs to appear.
@@ -2710,8 +2719,7 @@ BOOL LLFloaterView::allChildrenClosed()
// by setting themselves invisible)
for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it)
{
- LLView* viewp = *it;
- LLFloater* floaterp = (LLFloater*)viewp;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*it);
if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable())
{
@@ -2947,7 +2955,7 @@ void LLFloaterView::syncFloaterTabOrder()
// otherwise, make sure the focused floater is in the front of the child list
for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
{
- LLFloater* floaterp = (LLFloater*)*child_it;
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
if (gFocusMgr.childHasKeyboardFocus(floaterp))
{
bringToFront(floaterp, FALSE);
@@ -2969,7 +2977,7 @@ LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const
if (parentp == this)
{
- return (LLFloater*)viewp;
+ return dynamic_cast<LLFloater*>(viewp);
}
return NULL;
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index ef7c6180d2..165f67499b 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -310,7 +310,7 @@ public:
/*virtual*/ void setVisible(BOOL visible); // do not override
/*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override
- void setFrontmost(BOOL take_focus = TRUE);
+ void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
// Defaults to false.
@@ -547,7 +547,7 @@ public:
void setCycleMode(BOOL mode) { mFocusCycleMode = mode; }
BOOL getCycleMode() const { return mFocusCycleMode; }
- void bringToFront( LLFloater* child, BOOL give_focus = TRUE );
+ void bringToFront( LLFloater* child, BOOL give_focus = TRUE, BOOL restore = TRUE );
void highlightFocusedFloater();
void unhighlightFocusedFloater();
void focusFrontFloater();
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 3282c5f726..8166ef6a07 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -1629,9 +1629,9 @@ void LLFolderView::update()
if (mNeedsAutoSelect)
{
LL_RECORD_BLOCK_TIME(FTM_AUTO_SELECT);
- // select new item only if a filtered item not currently selected
+ // select new item only if a filtered item not currently selected and there was a selection
LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
- if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible()))
+ if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible())
{
// these are named variables to get around gcc not binding non-const references to rvalues
// and functor application is inherently non-const to allow for stateful functors
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 114dd7bd2f..b5deefd653 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -242,6 +242,8 @@ public:
bool useLabelSuffix() { return mUseLabelSuffix; }
virtual void updateMenu();
+ void finishRenamingItem( void );
+
// Note: We may eventually have to move that method up the hierarchy to LLFolderViewItem.
LLHandle<LLFolderView> getHandle() const { return getDerivedHandle<LLFolderView>(); }
@@ -255,7 +257,6 @@ protected:
void commitRename( const LLSD& data );
void onRenamerLost();
- void finishRenamingItem( void );
void closeRenamer( void );
bool selectFirstItem();
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 3def0386e1..5eb5ca4f82 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -972,6 +972,11 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
mIndentation = (getParentFolder())
? getParentFolder()->getIndentation() + mLocalIndentation
: 0;
+
+ if(isOpen() && folder->isOpen())
+ {
+ requestArrange();
+ }
}
static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange");
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index a08cf91a69..492c9315d1 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -400,12 +400,7 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
if (mMaxLengthChars)
{
- LLWString truncated_wstring = utf8str_to_wstring(truncated_utf8);
- if (truncated_wstring.size() > (U32)mMaxLengthChars)
- {
- truncated_wstring = truncated_wstring.substr(0, mMaxLengthChars);
- }
- mText.assign(wstring_to_utf8str(truncated_wstring));
+ mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars));
}
if (all_selected)
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 616c42895c..c7d7535f87 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -177,6 +177,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
: LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
mURLClickSignal(NULL),
mIsFriendSignal(NULL),
+ mIsObjectBlockedSignal(NULL),
mMaxTextByteLength( p.max_text_length ),
mFont(p.font),
mFontShadow(p.font_shadow),
@@ -268,6 +269,8 @@ LLTextBase::~LLTextBase()
{
mSegments.clear();
delete mURLClickSignal;
+ delete mIsFriendSignal;
+ delete mIsObjectBlockedSignal;
}
void LLTextBase::initFromParams(const LLTextBase::Params& p)
@@ -1942,6 +1945,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url, true));
registrar.add("Url.Block", boost::bind(&LLUrlAction::blockObject, url));
+ registrar.add("Url.Unblock", boost::bind(&LLUrlAction::unblockObject, url));
registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
@@ -1968,6 +1972,19 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
removeFriendButton->setEnabled(isFriend);
}
}
+
+ if (mIsObjectBlockedSignal)
+ {
+ bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url));
+ LLView* blockButton = mPopupMenu->getChild<LLView>("block_object");
+ LLView* unblockButton = mPopupMenu->getChild<LLView>("unblock_object");
+
+ if (blockButton && unblockButton)
+ {
+ blockButton->setVisible(!is_blocked);
+ unblockButton->setVisible(is_blocked);
+ }
+ }
if (mPopupMenu)
{
@@ -3022,6 +3039,15 @@ boost::signals2::connection LLTextBase::setIsFriendCallback(const is_friend_sign
return mIsFriendSignal->connect(cb);
}
+boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb)
+{
+ if (!mIsObjectBlockedSignal)
+ {
+ mIsObjectBlockedSignal = new is_blocked_signal_t();
+ }
+ return mIsObjectBlockedSignal->connect(cb);
+}
+
//
// LLTextSegment
//
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index c6ce5efcb8..85641fd899 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -270,6 +270,7 @@ public:
friend class LLUICtrlFactory;
typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t;
+ typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t;
struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>
{
@@ -456,6 +457,7 @@ public:
virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb);
boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
+ boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
void setWordWrap(bool wrap);
LLScrollContainer* getScrollContainer() const { return mScroller; }
@@ -685,6 +687,7 @@ protected:
// Used to check if user with given ID is avatar's friend
is_friend_signal_t* mIsFriendSignal;
+ is_blocked_signal_t* mIsObjectBlockedSignal;
LLUIString mLabel; // text label that is visible when no user text provided
};
diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp
index fff04b34f2..f6b2ee1dc0 100644
--- a/indra/llui/lltextutil.cpp
+++ b/indra/llui/lltextutil.cpp
@@ -56,6 +56,26 @@ void LLTextUtil::textboxSetHighlightedVal(LLTextBox *txtbox, const LLStyle::Para
txtbox->appendText(text.substr(hl_begin + hl_len), false, normal_style);
}
+void LLTextUtil::textboxSetGreyedVal(LLTextBox *txtbox, const LLStyle::Params& normal_style, const std::string& text, const std::string& greyed)
+{
+ static LLUIColor sGreyedTextColor = LLUIColorTable::instance().getColor("Gray", LLColor4::grey);
+
+ size_t greyed_begin = 0, greyed_len = greyed.size();
+
+ if (greyed_len == 0 || (greyed_begin = text.find(greyed)) == std::string::npos)
+ {
+ txtbox->setText(text, normal_style);
+ return;
+ }
+
+ LLStyle::Params greyed_style = normal_style;
+ greyed_style.color = sGreyedTextColor;
+ txtbox->setText(LLStringUtil::null); // clear text
+ txtbox->appendText(text.substr(0, greyed_begin), false, normal_style);
+ txtbox->appendText(text.substr(greyed_begin, greyed_len), false, greyed_style);
+ txtbox->appendText(text.substr(greyed_begin + greyed_len), false, normal_style);
+}
+
const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str)
{
static const std::string PHONE_SEPARATOR = LLUI::sSettingGroups["config"]->getString("AvalinePhoneSeparator");
diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h
index 1be81ffd62..a9c143e445 100644
--- a/indra/llui/lltextutil.h
+++ b/indra/llui/lltextutil.h
@@ -52,6 +52,12 @@ namespace LLTextUtil
const std::string& text,
const std::string& hl);
+ void textboxSetGreyedVal(
+ LLTextBox *txtbox,
+ const LLStyle::Params& normal_style,
+ const std::string& text,
+ const std::string& greyed);
+
/**
* Formats passed phone number to be more human readable.
*
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index 56977c597b..84ea770a8d 100644
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -231,3 +231,13 @@ void LLUrlAction::blockObject(std::string url)
executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + LLURI::escape(object_name));
}
}
+
+void LLUrlAction::unblockObject(std::string url)
+{
+ std::string object_id = getObjectId(url);
+ std::string object_name = getObjectName(url);
+ if (LLUUID::validate(object_id))
+ {
+ executeSLURL("secondlife:///app/agent/" + object_id + "/unblock/" + object_name);
+ }
+}
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index 5497e28bb4..2d2a8dfef1 100644
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -83,6 +83,7 @@ public:
static void addFriend(std::string url);
static void removeFriend(std::string url);
static void blockObject(std::string url);
+ static void unblockObject(std::string url);
/// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 8f7cac1f61..fd7406b653 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -588,6 +588,11 @@ void LLView::onVisibilityChange ( BOOL new_visibility )
BOOL log_visibility_change = LLViewerEventRecorder::instance().getLoggingStatus();
BOOST_FOREACH(LLView* viewp, mChildList)
{
+ if (!viewp)
+ {
+ continue;
+ }
+
// only views that are themselves visible will have their overall visibility affected by their ancestors
old_visibility=viewp->getVisible();
@@ -807,7 +812,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
{
if (!getVisible())
- return false;
+ return NULL;
BOOST_FOREACH(LLView* viewp, mChildList)
{
diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h
index faa5d3abb7..6daf1ac55b 100644
--- a/indra/llwindow/llappdelegate-objc.h
+++ b/indra/llwindow/llappdelegate-objc.h
@@ -41,7 +41,7 @@
@property (retain) NSString *currentInputLanguage;
-- (void) mainLoop;
+- (void) oneFrame;
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
- (void) languageUpdated;
- (bool) romanScript;
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index c22f3382fb..b06cd2c184 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -69,7 +69,7 @@ typedef const NativeKeyEventData * NSKeyEventRef;
// These are defined in llappviewermacosx.cpp.
bool initViewer();
void handleQuit();
-bool runMainLoop();
+bool pumpMainLoop();
void initMainLoop();
void cleanupViewer();
void handleUrl(const char* url);
diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp
index 3149fad6e8..ec3616e26a 100644
--- a/indra/mac_crash_logger/llcrashloggermac.cpp
+++ b/indra/mac_crash_logger/llcrashloggermac.cpp
@@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()
{
}
-bool LLCrashLoggerMac::mainLoop()
+bool LLCrashLoggerMac::frame()
{
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
diff --git a/indra/mac_crash_logger/llcrashloggermac.h b/indra/mac_crash_logger/llcrashloggermac.h
index 6d8f63ecac..05ef8c9f53 100644
--- a/indra/mac_crash_logger/llcrashloggermac.h
+++ b/indra/mac_crash_logger/llcrashloggermac.h
@@ -37,7 +37,7 @@ public:
LLCrashLoggerMac(void);
~LLCrashLoggerMac(void);
virtual bool init();
- virtual bool mainLoop();
+ virtual bool frame();
virtual bool cleanup();
virtual void gatherPlatformSpecificFiles();
};
diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp
index 95d4e65207..54e41a1954 100644
--- a/indra/mac_crash_logger/mac_crash_logger.cpp
+++ b/indra/mac_crash_logger/mac_crash_logger.cpp
@@ -49,7 +49,7 @@ int main(int argc, char **argv)
{
// return NSApplicationMain(argc, (const char **)argv);
}
- app.mainLoop();
+ app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index 24eb3947b4..9055e0111a 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -4,15 +4,18 @@ add_subdirectory(base)
if (LINUX)
add_subdirectory(gstreamer010)
+ add_subdirectory(libvlc)
endif (LINUX)
-if (WINDOWS OR DARWIN)
+if (DARWIN)
add_subdirectory(quicktime)
add_subdirectory(cef)
-endif (WINDOWS OR DARWIN)
+endif (DARWIN)
if (WINDOWS)
+ add_subdirectory(cef)
add_subdirectory(winmmshim)
+ add_subdirectory(libvlc)
endif (WINDOWS)
### add_subdirectory(example)
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index 8d9d1dd975..28a8a5886a 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -100,6 +100,12 @@ private:
LLCEFLib* mLLCEFLib;
VolumeCatcher mVolumeCatcher;
+
+ U8 *mPopupBuffer;
+ U32 mPopupW;
+ U32 mPopupH;
+ U32 mPopupX;
+ U32 mPopupY;
};
////////////////////////////////////////////////////////////////////////////////
@@ -127,12 +133,19 @@ MediaPluginBase(host_send_func, host_user_data)
mCookiePath = "";
mPickedFile = "";
mLLCEFLib = new LLCEFLib();
+
+ mPopupBuffer = NULL;
+ mPopupW = 0;
+ mPopupH = 0;
+ mPopupX = 0;
+ mPopupY = 0;
}
////////////////////////////////////////////////////////////////////////////////
//
MediaPluginCEF::~MediaPluginCEF()
{
+ delete[] mPopupBuffer;
}
////////////////////////////////////////////////////////////////////////////////
@@ -155,20 +168,28 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg)
//
void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup)
{
- if (mPixels && pixels)
+ if( is_popup )
+ {
+ delete mPopupBuffer;
+ mPopupBuffer = NULL;
+ mPopupH = 0;
+ mPopupW = 0;
+ mPopupX = 0;
+ mPopupY = 0;
+ }
+
+ if( mPixels && pixels )
{
if (is_popup)
{
- for (int line = 0; line < height; ++line)
+ if( width > 0 && height> 0 )
{
- int inverted_y = mHeight - y - height;
- int src = line * width * mDepth;
- int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth;
-
- if (dst + width * mDepth < mWidth * mHeight * mDepth)
- {
- memcpy(mPixels + dst, pixels + src, width * mDepth);
- }
+ mPopupBuffer = new U8[ width * height * mDepth ];
+ memcpy( mPopupBuffer, pixels, width * height * mDepth );
+ mPopupH = height;
+ mPopupW = width;
+ mPopupX = x;
+ mPopupY = mHeight - y - height;
}
}
else
@@ -177,6 +198,23 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y,
{
memcpy(mPixels, pixels, mWidth * mHeight * mDepth);
}
+ if( mPopupBuffer && mPopupH && mPopupW )
+ {
+ U32 bufferSize = mWidth * mHeight * mDepth;
+ U32 popupStride = mPopupW * mDepth;
+ U32 bufferStride = mWidth * mDepth;
+ int dstY = mPopupY;
+
+ int src = 0;
+ int dst = dstY * mWidth * mDepth + mPopupX * mDepth;
+
+ for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line )
+ {
+ memcpy( mPixels + dst, mPopupBuffer + src, popupStride );
+ src += popupStride;
+ dst += bufferStride;
+ }
+ }
}
setDirty(0, 0, mWidth, mHeight);
@@ -559,6 +597,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
S32 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
+ y = mHeight - y;
+
// only even send left mouse button events to LLCEFLib
// (partially prompted by crash in OS X CEF when sending right button events)
// we catch the right click in viewer and display our own context menu anyway
diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt
new file mode 100644
index 0000000000..535d29125b
--- /dev/null
+++ b/indra/media_plugins/libvlc/CMakeLists.txt
@@ -0,0 +1,86 @@
+# -*- cmake -*-
+
+project(media_plugin_libvlc)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(OpenGL)
+
+include(LibVLCPlugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ ${VLC_INCLUDE_DIR}
+)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ )
+
+
+### media_plugin_libvlc
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+set(media_plugin_libvlc_SOURCE_FILES
+ media_plugin_libvlc.cpp
+ )
+
+add_library(media_plugin_libvlc
+ SHARED
+ ${media_plugin_libvlc_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_libvlc
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${VLC_PLUGIN_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_libvlc
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ media_plugin_libvlc
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT"
+ )
+endif (WINDOWS)
+
+if (DARWIN)
+ # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+ set_target_properties(
+ media_plugin_libvlc
+ PROPERTIES
+ PREFIX ""
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path"
+ LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+ )
+
+endif (DARWIN)
diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
new file mode 100644
index 0000000000..0bd323eb58
--- /dev/null
+++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
@@ -0,0 +1,618 @@
+/**
+* @file media_plugin_libvlc.cpp
+* @brief LibVLC plugin for LLMedia API plugin system
+*
+* @cond
+* $LicenseInfo:firstyear=2008&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+* @endcond
+*/
+
+#include "linden_common.h"
+
+#include "llgl.h"
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#include "vlc/vlc.h"
+#include "vlc/libvlc_version.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginLibVLC :
+ public MediaPluginBase
+{
+public:
+ MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginLibVLC();
+
+ /*virtual*/ void receiveMessage(const char* message_string);
+
+private:
+ bool init();
+
+ void initVLC();
+ void playMedia();
+ void resetVLC();
+ void setVolume(const F64 volume);
+ void updateTitle(const char* title);
+
+ static void* lock(void* data, void** p_pixels);
+ static void unlock(void* data, void* id, void* const* raw_pixels);
+ static void display(void* data, void* id);
+
+ /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */;
+
+ static void eventCallbacks(const libvlc_event_t* event, void* ptr);
+
+ libvlc_instance_t* mLibVLC;
+ libvlc_media_t* mLibVLCMedia;
+ libvlc_media_player_t* mLibVLCMediaPlayer;
+
+ struct mLibVLCContext
+ {
+ unsigned char* texture_pixels;
+ libvlc_media_player_t* mp;
+ MediaPluginLibVLC* parent;
+ };
+ struct mLibVLCContext mLibVLCCallbackContext;
+
+ std::string mURL;
+ F64 mCurVolume;
+
+ bool mIsLooping;
+
+ float mCurTime;
+ float mDuration;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
+MediaPluginBase(host_send_func, host_user_data)
+{
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mDepth = 4;
+ mPixels = 0;
+
+ mLibVLC = 0;
+ mLibVLCMedia = 0;
+ mLibVLCMediaPlayer = 0;
+
+ mCurVolume = 0.0;
+
+ mIsLooping = false;
+
+ mCurTime = 0.0;
+ mDuration = 0.0;
+
+ mURL = std::string();
+
+ setStatus(STATUS_NONE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginLibVLC::~MediaPluginLibVLC()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+void* MediaPluginLibVLC::lock(void* data, void** p_pixels)
+{
+ struct mLibVLCContext* context = (mLibVLCContext*)data;
+
+ *p_pixels = context->texture_pixels;
+
+ return NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels)
+{
+ // nothing to do here for the moment
+ // we *could* modify pixels here to, for example, Y flip, but this is done with
+ // a VLC video filter transform.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::display(void* data, void* id)
+{
+ struct mLibVLCContext* context = (mLibVLCContext*)data;
+
+ context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::initVLC()
+{
+ char const* vlc_argv[] =
+ {
+ "--no-xlib",
+ "--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client
+ };
+
+ int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
+ mLibVLC = libvlc_new(vlc_argc, vlc_argv);
+
+ if (!mLibVLC)
+ {
+ // for the moment, if this fails, the plugin will fail and
+ // the media sub-system will tell the viewer something went wrong.
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::resetVLC()
+{
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+ libvlc_release(mLibVLC);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// *virtual*
+void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
+
+ message.setValueS32("left", left);
+ message.setValueS32("top", top);
+ message.setValueS32("right", right);
+ message.setValueS32("bottom", bottom);
+
+ message.setValueReal("current_time", mCurTime);
+ message.setValueReal("duration", mDuration);
+ message.setValueReal("current_rate", 1.0f);
+
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
+{
+ MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr;
+ if (parent == 0)
+ {
+ return;
+ }
+
+ switch (event->type)
+ {
+ case libvlc_MediaPlayerOpening:
+ parent->setStatus(STATUS_LOADING);
+ break;
+
+ case libvlc_MediaPlayerPlaying:
+ parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f;
+ parent->setStatus(STATUS_PLAYING);
+ break;
+
+ case libvlc_MediaPlayerPaused:
+ parent->setStatus(STATUS_PAUSED);
+ break;
+
+ case libvlc_MediaPlayerStopped:
+ parent->setStatus(STATUS_DONE);
+ break;
+
+ case libvlc_MediaPlayerEndReached:
+ parent->setStatus(STATUS_DONE);
+ break;
+
+ case libvlc_MediaPlayerEncounteredError:
+ parent->setStatus(STATUS_ERROR);
+ break;
+
+ case libvlc_MediaPlayerTimeChanged:
+ parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f;
+ break;
+
+ case libvlc_MediaPlayerPositionChanged:
+ break;
+
+ case libvlc_MediaPlayerLengthChanged:
+ parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f;
+ break;
+
+ case libvlc_MediaPlayerTitleChanged:
+ {
+ char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title);
+ if (title)
+ {
+ parent->updateTitle(title);
+ }
+ }
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::playMedia()
+{
+ if (mURL.length() == 0)
+ {
+ return;
+ }
+
+ if (mLibVLCMediaPlayer)
+ {
+ // stop listening to events while we reset things
+ libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
+ if (em)
+ {
+ libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL);
+ };
+
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+
+ mLibVLCMediaPlayer = 0;
+ }
+
+ if (mLibVLCMedia)
+ {
+ libvlc_media_release(mLibVLCMedia);
+
+ mLibVLCMedia = 0;
+ }
+
+ mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
+ if (!mLibVLCMedia)
+ {
+ mLibVLCMediaPlayer = 0;
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia);
+ if (!mLibVLCMediaPlayer)
+ {
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ // listen to events
+ libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
+ if (em)
+ {
+ libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
+ }
+
+ mLibVLCCallbackContext.parent = this;
+ mLibVLCCallbackContext.texture_pixels = mPixels;
+ mLibVLCCallbackContext.mp = mLibVLCMediaPlayer;
+
+ // Send a "navigate begin" event.
+ // This is really a browser message but the QuickTime plugin did it and
+ // the media system relies on this message to update internal state so we must send it too
+ // Note: see "navigate_complete" message below too
+ // https://jira.secondlife.com/browse/MAINT-6528
+ LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ message_begin.setValue("uri", mURL);
+ message_begin.setValueBoolean("history_back_available", false);
+ message_begin.setValueBoolean("history_forward_available", false);
+ sendMessage(message_begin);
+
+ // volume level gets set before VLC is initialized (thanks media system) so we have to record
+ // it in mCurVolume and set it again here so that volume levels are correctly initialized
+ setVolume(mCurVolume);
+
+ setStatus(STATUS_LOADED);
+
+ libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
+ libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
+
+ // note this relies on the "set_loop" message arriving before the "start" (play) one
+ // but that appears to always be the case
+ if (mIsLooping)
+ {
+ libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1");
+ }
+
+ libvlc_media_player_play(mLibVLCMediaPlayer);
+
+ // send a "location_changed" message - this informs the media system
+ // that a new URL is the 'current' one and is used extensively.
+ // Again, this is really a browser message but we will use it here.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
+ message.setValue("uri", mURL);
+ sendMessage(message);
+
+ // Send a "navigate complete" event.
+ // This is really a browser message but the QuickTime plugin did it and
+ // the media system relies on this message to update internal state so we must send it too
+ // Note: see "navigate_begin" message above too
+ // https://jira.secondlife.com/browse/MAINT-6528
+ LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ message_complete.setValue("uri", mURL);
+ message_complete.setValueS32("result_code", 200);
+ message_complete.setValue("result_string", "OK");
+ sendMessage(message_complete);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::updateTitle(const char* title)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", title);
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::setVolume(const F64 volume)
+{
+ mCurVolume = volume;
+
+ if (mLibVLCMediaPlayer)
+ {
+ int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, (int)(volume * 100));
+ if (result != 0)
+ {
+ // volume wasn't set but not much to be done here
+ }
+ }
+ else
+ {
+ // volume change was requested but VLC wasn't ready.
+ // that's okay thought because we saved the value in mCurVolume and
+ // the next volume change after the VLC system is initilzied will set it
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::receiveMessage(const char* message_string)
+{
+ LLPluginMessage message_in;
+
+ if (message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if (message_name == "init")
+ {
+ initVLC();
+
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::ostringstream s;
+ s << "LibVLC plugin ";
+ s << LIBVLC_VERSION_MAJOR;
+ s << ".";
+ s << LIBVLC_VERSION_MINOR;
+ s << ".";
+ s << LIBVLC_VERSION_REVISION;
+
+ message.setValue("plugin_version", s.str());
+ sendMessage(message);
+ }
+ else if (message_name == "idle")
+ {
+ }
+ else if (message_name == "cleanup")
+ {
+ resetVLC();
+ }
+ else if (message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+ }
+ else if (message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if (iter != mSharedSegments.end())
+ {
+ if (mPixels == iter->second.mAddress)
+ {
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+ mLibVLCMediaPlayer = 0;
+
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+ //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if (message_name == "init")
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGB);
+ message.setValueU32("format", GL_BGRA_EXT);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else if (message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ if (!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if (iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ playMedia();
+ };
+ };
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+ }
+ else if (message_name == "load_uri")
+ {
+ mURL = message_in.getValue("uri");
+ playMedia();
+ }
+ }
+ else
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if (message_name == "stop")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "start")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_play(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "pause")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_pause(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "seek")
+ {
+ if (mDuration > 0)
+ {
+ F64 normalized_offset = message_in.getValueReal("time") / mDuration;
+ libvlc_media_player_set_position(mLibVLCMediaPlayer, normalized_offset);
+ }
+ }
+ else if (message_name == "set_loop")
+ {
+ mIsLooping = true;
+ }
+ else if (message_name == "set_volume")
+ {
+ // volume comes in 0 -> 1.0
+ F64 volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginLibVLC::init()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", "LibVLC Plugin");
+ sendMessage(message);
+
+ return true;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func,
+ void* host_user_data,
+ LLPluginInstance::sendMessageFunction *plugin_send_func,
+ void **plugin_user_data)
+{
+ MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
index c5615145be..58391007ff 100644..100755
--- a/indra/media_plugins/quicktime/CMakeLists.txt
+++ b/indra/media_plugins/quicktime/CMakeLists.txt
@@ -14,7 +14,6 @@ include(PluginAPI)
include(MediaPluginBase)
include(OpenGL)
include(QuickTimePlugin)
-include(Boost)
include_directories(
${LLPLUGIN_INCLUDE_DIRS}
@@ -54,12 +53,17 @@ target_link_libraries(media_plugin_quicktime
${PLUGIN_API_WINDOWS_LIBRARIES}
)
+add_dependencies(media_plugin_quicktime
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
if (WINDOWS)
set_target_properties(
media_plugin_quicktime
PROPERTIES
- LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
- LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD"
+ LINK_FLAGS "/MANIFEST:NO"
)
endif (WINDOWS)
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index 7ef5a0fe44..893fb738ce 100644..100755
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -837,9 +837,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
else if(message_name == "cleanup")
{
// TODO: clean up here
- LLPluginMessage message("base", "goodbye");
- sendMessage(message);
- }
+ }
else if(message_name == "shm_added")
{
SharedSegmentInfo info;
@@ -921,7 +919,10 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
#endif
message.setValueS32("depth", mDepth);
message.setValueU32("internalformat", GL_RGB);
- message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
+
+ // note this apparently only has an effect when media is opened in 2D browser.
+ // see https://jira.secondlife.com/browse/BUG-18252 - media flipped in 2D so flipping it back.
+ message.setValueBoolean("coords_opengl", false); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
message.setValueBoolean("allow_downsample", true);
sendMessage(message);
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8d863631cf..b505bd3316 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1315,13 +1315,10 @@ set(viewer_HEADER_FILES
source_group("CMake Rules" FILES ViewerInstall.cmake)
+#summary.json creation moved to viewer_manifest.py MAINT-6413
# the viewer_version.txt file created here is for passing to viewer_manifest and autobuild
-# the summary.json file is created for the benefit of the TeamCity builds, where
-# it is used to provide descriptive information to the build results page
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt"
"${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\n")
-file(WRITE "${CMAKE_BINARY_DIR}/summary.json"
- "{\"Type\":\"viewer\",\"Version\":\"${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\"}\n")
set_source_files_properties(
llversioninfo.cpp tests/llversioninfo_test.cpp
@@ -1753,6 +1750,7 @@ if (WINDOWS)
SLPlugin
media_plugin_quicktime
media_plugin_cef
+ media_plugin_libvlc
winmm_shim
windows-crash-logger
)
@@ -1968,6 +1966,7 @@ if (LINUX)
linux-crash-logger
SLPlugin
media_plugin_gstreamer010
+ media_plugin_libvlc
llcommon
)
@@ -2075,7 +2074,7 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger)
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
if (ENABLE_SIGNING)
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 43beb4001b..627a3f43a6 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-4.0.7
+4.1.1
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 2cd6638042..a0d3dc0f99 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -37,7 +37,7 @@
tooltip_ref="Command_Build_Tooltip"
execute_function="Build.Toggle"
execute_parameters="build"
- is_enabled_function="Build.Enabled"
+ is_enabled_function="Build.EnabledOrActive"
is_enabled_parameters="build"
is_running_function="Floater.IsOpen"
is_running_parameters="build"
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a8d42be2a1..6ccf89eabe 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3701,6 +3701,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>QueueInventoryFetchTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Max time llcompilequeue will wait for inventory fetch to complete (in seconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>300.0</real>
+ </map>
<key>FindLandArea</key>
<map>
<key>Comment</key>
@@ -11065,6 +11076,28 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>FriendsListHideUsernames</key>
+ <map>
+ <key>Comment</key>
+ <string>Show both Display name and Username in Friend list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>NearbyListHideUsernames</key>
+ <map>
+ <key>Comment</key>
+ <string>Show both Display name and Username in Nearby list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>NearbyListShowMap</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index be8ea2bab9..e99b94f150 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -32,7 +32,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
-RenderAvatarMaxComplexity 1 80000
+RenderAvatarMaxComplexity 1 350000
RenderAvatarVP 1 1
RenderAutoMuteSurfaceAreaLimit 1 1000.0
RenderCubeMap 1 1
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index ca6c00951d..801a622e93 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -32,7 +32,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
-RenderAvatarMaxComplexity 1 80000
+RenderAvatarMaxComplexity 1 350000
RenderAvatarVP 1 1
RenderAutoMuteSurfaceAreaLimit 1 1000.0
RenderCubeMap 1 1
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index ea69b088f9..1f891ee4d7 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -32,7 +32,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
-RenderAvatarMaxComplexity 1 80000
+RenderAvatarMaxComplexity 1 350000
RenderAvatarVP 1 1
RenderAutoMuteSurfaceAreaLimit 1 1000.0
RenderCubeMap 1 1
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index b8677fd9e4..89317f2793 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -648,6 +648,7 @@ Function un.ProgramFiles
%%DELETE_FILES%%
# Optional/obsolete files. Delete won't fail if they don't exist.
+Delete "$INSTDIR\autorun.bat"
Delete "$INSTDIR\dronesettings.ini"
Delete "$INSTDIR\message_template.msg"
Delete "$INSTDIR\newview.pdb"
@@ -679,6 +680,16 @@ FOLDERFOUND:
NOFOLDER:
+MessageBox MB_YESNO $(DeleteRegistryKeysMB) IDYES DeleteKeys IDNO NoDelete
+
+DeleteKeys:
+ DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Classes\x-grid-location-info"
+ DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Classes\secondlife"
+ DeleteRegKey HKEY_CLASSES_ROOT "x-grid-location-info"
+ DeleteRegKey HKEY_CLASSES_ROOT "secondlife"
+
+NoDelete:
+
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi
index 343c312ddc..aa403a961c 100644
--- a/indra/newview/installers/windows/lang_en-us.nsi
+++ b/indra/newview/installers/windows/lang_en-us.nsi
Binary files differ
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index 92a5413adb..1dddf52961 100644
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -31,6 +31,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include "llexception.h"
+#include "stringize.h"
#include <algorithm>
#include <iterator>
@@ -154,13 +156,11 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
} while (false);
}
- catch (std::exception e)
- {
- LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << url << "')"));
+ throw;
}
mPendingObjectQuota.clear();
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 3e3d5c7456..648212177b 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -838,11 +838,11 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
void AISUpdate::doUpdate()
{
- // Do version/descendent accounting.
+ // Do version/descendant accounting.
for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
catit != mCatDescendentDeltas.end(); ++catit)
{
- LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL;
+ LL_DEBUGS("Inventory") << "descendant accounting for " << catit->first << LL_ENDL;
const LLUUID cat_id(catit->first);
// Don't account for update if we just created this category.
@@ -859,13 +859,13 @@ void AISUpdate::doUpdate()
continue;
}
- // If we have a known descendent count, set that now.
+ // If we have a known descendant count, set that now.
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (cat)
{
S32 descendent_delta = catit->second;
S32 old_count = cat->getDescendentCount();
- LL_DEBUGS("Inventory") << "Updating descendent count for "
+ LL_DEBUGS("Inventory") << "Updating descendant count for "
<< cat->getName() << " " << cat_id
<< " with delta " << descendent_delta << " from "
<< old_count << " to " << (old_count+descendent_delta) << LL_ENDL;
@@ -896,7 +896,7 @@ void AISUpdate::doUpdate()
LLUUID category_id(update_it->first);
LLPointer<LLViewerInventoryCategory> new_category = update_it->second;
// Since this is a copy of the category *before* the accounting update, above,
- // we need to transfer back the updated version/descendent count.
+ // we need to transfer back the updated version/descendant count.
LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID());
if (!curr_cat)
{
@@ -961,7 +961,16 @@ void AISUpdate::doUpdate()
{
LL_WARNS() << "Possible version mismatch for category " << cat->getName()
<< ", viewer version " << cat->getVersion()
- << " server version " << version << LL_ENDL;
+ << " AIS version " << version << " !!!Adjusting local version!!!" << LL_ENDL;
+
+ // the AIS version should be considered the true version. Adjust
+ // our local category model to reflect this version number. Otherwise
+ // it becomes possible to get stuck with the viewer being out of
+ // sync with the inventory system. Under normal circumstances
+ // inventory COF is maintained on the viewer through calls to
+ // LLInventoryModel::accountForUpdate when a changing operation
+ // is performed. This occasionally gets out of sync however.
+ cat->setVersion(version);
}
}
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index 49291ea564..c1f898284a 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -30,6 +30,8 @@
#include "llappviewer.h"
#include "llviewercontrol.h"
+#include "llexception.h"
+#include "stringize.h"
#include <openssl/x509_vfy.h>
#include <openssl/ssl.h>
@@ -534,7 +536,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
// somewhat clumsy, as we may run into errors that do not map directly to curl
// error codes. Should be refactored with login refactoring, perhaps.
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
- result.setMessage(cert_exception.getMessage());
+ result.setMessage(cert_exception.what());
LLPointer<LLCertificate> cert = cert_exception.getCert();
cert->ref(); // adding an extra ref here
result.setErrorData(cert.get());
@@ -544,13 +546,14 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
catch (LLCertException &cert_exception)
{
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
- result.setMessage(cert_exception.getMessage());
+ result.setMessage(cert_exception.what());
LLPointer<LLCertificate> cert = cert_exception.getCert();
cert->ref(); // adding an extra ref here
result.setErrorData(cert.get());
}
catch (...)
{
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("('" << url << "')"));
// any other odd error, we just handle as a connect error.
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);
}
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 549df80fa1..be8877328d 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -48,16 +48,19 @@
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
frameTimer = nil;
-
+
[self languageUpdated];
-
+
if (initViewer())
{
- frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
+ // Set up recurring calls to oneFrame (repeating timer with timeout 0)
+ // until applicationShouldTerminate.
+ frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self
+ selector:@selector(oneFrame) userInfo:nil repeats:YES];
} else {
handleQuit();
}
-
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];
// [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
@@ -96,22 +99,29 @@
- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender
{
- if (!runMainLoop())
+ // run one frame to assess state
+ if (!pumpMainLoop())
{
+ // pumpMainLoop() returns true when done, false if it wants to be
+ // called again. Since it returned false, do not yet cancel
+ // frameTimer.
handleQuit();
return NSTerminateCancel;
} else {
+ // pumpMainLoop() returned true: it's done. Okay, done with frameTimer.
[frameTimer release];
cleanupViewer();
return NSTerminateNow;
}
}
-- (void) mainLoop
+- (void) oneFrame
{
- bool appExiting = runMainLoop();
+ bool appExiting = pumpMainLoop();
if (appExiting)
{
+ // Once pumpMainLoop() reports that we're done, cancel frameTimer:
+ // stop the repetitive calls.
[frameTimer release];
[[NSApplication sharedApplication] terminate:self];
}
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index cc676550ab..a1d9786321 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -60,6 +60,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
+#include "llavatarpropertiesprocessor.h"
+
#if LL_MSVC
// disable boost::lexical_cast warning
#pragma warning (disable:4702)
@@ -3359,15 +3361,9 @@ void LLAppearanceMgr::requestServerAppearanceUpdate()
{
if (!mOutstandingAppearanceBakeRequest)
{
-#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE
mRerequestAppearanceBake = false;
LLCoprocedureManager::CoProcedure_t proc = boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this, _1);
LLCoprocedureManager::instance().enqueueCoprocedure("AIS", "LLAppearanceMgr::serverAppearanceUpdateCoro", proc);
-#else
- LLCoros::instance().launch("serverAppearanceUpdateCoro",
- boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this));
-
-#endif
}
else
{
@@ -3375,17 +3371,8 @@ void LLAppearanceMgr::requestServerAppearanceUpdate()
}
}
-#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE
void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter)
-#else
-void LLAppearanceMgr::serverAppearanceUpdateCoro()
-#endif
{
-#ifndef APPEARANCEBAKE_AS_IN_AIS_QUEUE
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(
- new LLCoreHttpUtil::HttpCoroutineAdapter("serverAppearanceUpdateCoro", LLCore::HttpRequest::DEFAULT_POLICY_ID));
-#endif
-
mRerequestAppearanceBake = false;
if (!gAgent.getRegion())
{
@@ -3493,10 +3480,15 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro()
// on multiple machines.
if (result.has("expected"))
{
-
S32 expectedCofVersion = result["expected"].asInteger();
LL_WARNS("Avatar") << "Server expected " << expectedCofVersion << " as COF version" << LL_ENDL;
+ // Force an update texture request for ourself. The message will return
+ // through the UDP and be handled in LLVOAvatar::processAvatarAppearance
+ // this should ensure that we receive a new canonical COF from the sim
+ // host. Hopefully it will return before the timeout.
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(gAgent.getID());
+
bRetry = true;
// Wait for a 1/2 second before trying again. Just to keep from asking too quickly.
if (++retryCount > BAKE_RETRY_MAX_COUNT)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index bf181cb4ad..7069da7352 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -228,11 +228,7 @@ public:
private:
-#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE
void serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter);
-#else
- void serverAppearanceUpdateCoro();
-#endif
static void debugAppearanceUpdateCOF(const LLSD& content);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b6d02ea2f8..3023944f6e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -122,9 +122,13 @@
#include "llleap.h"
#include "stringize.h"
#include "llcoros.h"
+#include "llexception.h"
#if !LL_LINUX
#include "cef/llceflib.h"
-#endif
+#if LL_WINDOWS
+#include "vlc/libvlc_version.h"
+#endif // LL_WINDOWS
+#endif // LL_LINUX
// Third party library includes
#include <boost/bind.hpp>
@@ -231,7 +235,6 @@
#include "llcoproceduremanager.h"
#include "llviewereventrecorder.h"
-
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
// this app, or another 'component' of the viewer. App globals should be
@@ -769,9 +772,6 @@ bool LLAppViewer::init()
//
// Start of the application
//
-#ifdef LL_DARWIN
- mMainLoopInitialized = false;
-#endif
// initialize LLWearableType translation bridge.
// Memory will be cleaned up in ::cleanupClass()
@@ -925,7 +925,7 @@ bool LLAppViewer::init()
// Provide the text fields with callbacks for opening Urls
LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
- LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
+ LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false));
LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
@@ -1220,6 +1220,23 @@ bool LLAppViewer::init()
boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),
boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS));
+ /*----------------------------------------------------------------------*/
+ // nat 2016-06-29 moved the following here from the former mainLoop().
+ mMainloopTimeout = new LLWatchdogTimeout();
+
+ // Create IO Pump to use for HTTP Requests.
+ gServicePump = new LLPumpIO(gAPRPoolp);
+
+ // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
+
+ LLVoiceChannel::initClass();
+ LLVoiceClient::getInstance()->init(gServicePump);
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
+
+ joystick = LLViewerJoystick::getInstance();
+ joystick->setNeedsReset(true);
+ /*----------------------------------------------------------------------*/
+
return true;
}
@@ -1294,299 +1311,265 @@ static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");
// externally visible timers
LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
-bool LLAppViewer::mainLoop()
+bool LLAppViewer::frame()
{
-#ifdef LL_DARWIN
- if (!mMainLoopInitialized)
-#endif
- {
- LL_INFOS() << "Entering main_loop" << LL_ENDL;
- mMainloopTimeout = new LLWatchdogTimeout();
-
- //-------------------------------------------
- // Run main loop until time to quit
- //-------------------------------------------
-
- // Create IO Pump to use for HTTP Requests.
- gServicePump = new LLPumpIO(gAPRPoolp);
-
- // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
-
- LLVoiceChannel::initClass();
- LLVoiceClient::getInstance()->init(gServicePump);
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
-
- joystick = LLViewerJoystick::getInstance();
- joystick->setNeedsReset(true);
-
-#ifdef LL_DARWIN
- // Ensure that this section of code never gets called again on OS X.
- mMainLoopInitialized = true;
-#endif
- }
- // As we do not (yet) send data on the mainloop LLEventPump that varies
- // with each frame, no need to instantiate a new LLSD event object each
- // time. Obviously, if that changes, just instantiate the LLSD at the
- // point of posting.
-
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
-
- LLSD newFrame;
-
+ LLSD newFrame;
+
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
-
+
//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
//LLPrivateMemoryPoolTester::destroy() ;
- // Handle messages
-#ifdef LL_DARWIN
- if (!LLApp::isExiting())
-#else
- while (!LLApp::isExiting())
-#endif
+ LL_RECORD_BLOCK_TIME(FTM_FRAME);
+ LLTrace::BlockTimer::processTimes();
+ LLTrace::get_frame_recording().nextPeriod();
+ LLTrace::BlockTimer::logStats();
+
+ LLTrace::get_thread_recorder()->pullFromChildren();
+
+ //clear call stack records
+ LL_CLEAR_CALLSTACKS();
+
+ //check memory availability information
+ checkMemory() ;
+
+ try
{
- LL_RECORD_BLOCK_TIME(FTM_FRAME);
- LLTrace::BlockTimer::processTimes();
- LLTrace::get_frame_recording().nextPeriod();
- LLTrace::BlockTimer::logStats();
+ pingMainloopTimeout("Main:MiscNativeWindowEvents");
- LLTrace::get_thread_recorder()->pullFromChildren();
+ if (gViewerWindow)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+ gViewerWindow->getWindow()->processMiscNativeEvents();
+ }
+
+ pingMainloopTimeout("Main:GatherInput");
+
+ if (gViewerWindow)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+ if (!restoreErrorTrap())
+ {
+ LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
+ }
- //clear call stack records
- LL_CLEAR_CALLSTACKS();
+ gViewerWindow->getWindow()->gatherInput();
+ }
- //check memory availability information
- checkMemory() ;
+#if 1 && !LL_RELEASE_FOR_DOWNLOAD
+ // once per second debug info
+ if (debugTime.getElapsedTimeF32() > 1.f)
+ {
+ debugTime.reset();
+ }
- try
+#endif
+ //memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
{
- pingMainloopTimeout("Main:MiscNativeWindowEvents");
+ mem_leak_instance->idle() ;
+ }
+
+ // canonical per-frame event
+ mainloop.post(newFrame);
- if (gViewerWindow)
+ if (!LLApp::isExiting())
+ {
+ pingMainloopTimeout("Main:JoystickKeyboard");
+
+ // Scan keyboard for movement keys. Command keys and typing
+ // are handled by windows callbacks. Don't do this until we're
+ // done initializing. JC
+ if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
+ && gViewerWindow->getActive()
+ && !gViewerWindow->getWindow()->getMinimized()
+ && LLStartUp::getStartupState() == STATE_STARTED
+ && (gHeadlessClient || !gViewerWindow->getShowProgress())
+ && !gFocusMgr.focusLocked())
{
- LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
- gViewerWindow->getWindow()->processMiscNativeEvents();
+ joystick->scanJoystick();
+ gKeyboard->scanKeyboard();
}
-
- pingMainloopTimeout("Main:GatherInput");
-
- if (gViewerWindow)
+
+ // Update state based on messages, user input, object idle.
{
- LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
- if (!restoreErrorTrap())
- {
- LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
- }
+ pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
+
+ LL_RECORD_BLOCK_TIME(FTM_IDLE);
+ idle();
- gViewerWindow->getWindow()->gatherInput();
+ resumeMainloopTimeout();
}
-#if 1 && !LL_RELEASE_FOR_DOWNLOAD
- // once per second debug info
- if (debugTime.getElapsedTimeF32() > 1.f)
+ if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
- debugTime.reset();
+ pauseMainloopTimeout();
+ saveFinalSnapshot();
+ disconnectViewer();
+ resumeMainloopTimeout();
}
-
-#endif
- //memory leaking simulation
- LLFloaterMemLeak* mem_leak_instance =
- LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if(mem_leak_instance)
- {
- mem_leak_instance->idle() ;
- }
-
- // canonical per-frame event
- mainloop.post(newFrame);
- if (!LLApp::isExiting())
+ // Render scene.
+ // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
+ if (!LLApp::isExiting() && !gHeadlessClient)
{
- pingMainloopTimeout("Main:JoystickKeyboard");
-
- // Scan keyboard for movement keys. Command keys and typing
- // are handled by windows callbacks. Don't do this until we're
- // done initializing. JC
- if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
- && gViewerWindow->getActive()
- && !gViewerWindow->getWindow()->getMinimized()
- && LLStartUp::getStartupState() == STATE_STARTED
- && (gHeadlessClient || !gViewerWindow->getShowProgress())
- && !gFocusMgr.focusLocked())
- {
- joystick->scanJoystick();
- gKeyboard->scanKeyboard();
- }
+ pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
+ display();
+ pingMainloopTimeout("Main:Snapshot");
+ LLFloaterSnapshot::update(); // take snapshots
+ gGLActive = FALSE;
+ }
+ }
- // Update state based on messages, user input, object idle.
- {
- pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
-
- LL_RECORD_BLOCK_TIME(FTM_IDLE);
- idle();
+ pingMainloopTimeout("Main:Sleep");
- resumeMainloopTimeout();
- }
-
- if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
- {
- pauseMainloopTimeout();
- saveFinalSnapshot();
- disconnectViewer();
- resumeMainloopTimeout();
- }
+ pauseMainloopTimeout();
+
+ // Sleep and run background threads
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SLEEP);
+
+ // yield some time to the os based on command line option
+ if(mYieldTime >= 0)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_YIELD);
+ ms_sleep(mYieldTime);
+ }
- // Render scene.
- // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
- if (!LLApp::isExiting() && !gHeadlessClient)
+ // yield cooperatively when not running as foreground window
+ if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
+ || !gFocusMgr.getAppHasFocus())
+ {
+ // Sleep if we're not rendering, or the window is minimized.
+ S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
+ // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
+ // of equal priority on Windows
+ if (milliseconds_to_sleep > 0)
{
- pingMainloopTimeout("Main:Display");
- gGLActive = TRUE;
- display();
- pingMainloopTimeout("Main:Snapshot");
- LLFloaterSnapshot::update(); // take snapshots
- gGLActive = FALSE;
+ ms_sleep(milliseconds_to_sleep);
+ // also pause worker threads during this wait period
+ LLAppViewer::getTextureCache()->pause();
+ LLAppViewer::getImageDecodeThread()->pause();
}
}
-
- pingMainloopTimeout("Main:Sleep");
- pauseMainloopTimeout();
+ if (mRandomizeFramerate)
+ {
+ ms_sleep(rand() % 200);
+ }
- // Sleep and run background threads
+ if (mPeriodicSlowFrame
+ && (gFrameCount % 10 == 0))
{
- LL_RECORD_BLOCK_TIME(FTM_SLEEP);
-
- // yield some time to the os based on command line option
- if(mYieldTime >= 0)
- {
- LL_RECORD_BLOCK_TIME(FTM_YIELD);
- ms_sleep(mYieldTime);
- }
+ LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
+ ms_sleep(500);
+ }
+
+ const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second
+ idleTimer.reset();
+ S32 total_work_pending = 0;
+ S32 total_io_pending = 0;
+ while(1)
+ {
+ S32 work_pending = 0;
+ S32 io_pending = 0;
+ F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
+
+ work_pending += updateTextureThreads(max_time);
- // yield cooperatively when not running as foreground window
- if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
- || !gFocusMgr.getAppHasFocus())
{
- // Sleep if we're not rendering, or the window is minimized.
- S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
- // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
- // of equal priority on Windows
- if (milliseconds_to_sleep > 0)
- {
- ms_sleep(milliseconds_to_sleep);
- // also pause worker threads during this wait period
- LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
- }
+ LL_RECORD_BLOCK_TIME(FTM_VFS);
+ io_pending += LLVFSThread::updateClass(1);
}
-
- if (mRandomizeFramerate)
{
- ms_sleep(rand() % 200);
+ LL_RECORD_BLOCK_TIME(FTM_LFS);
+ io_pending += LLLFSThread::updateClass(1);
}
- if (mPeriodicSlowFrame
- && (gFrameCount % 10 == 0))
+ if (io_pending > 1000)
{
- LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
- ms_sleep(500);
+ ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
}
- const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second
- idleTimer.reset();
- S32 total_work_pending = 0;
- S32 total_io_pending = 0;
- while(1)
- {
- S32 work_pending = 0;
- S32 io_pending = 0;
- F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
-
- work_pending += updateTextureThreads(max_time);
-
- {
- LL_RECORD_BLOCK_TIME(FTM_VFS);
- io_pending += LLVFSThread::updateClass(1);
- }
- {
- LL_RECORD_BLOCK_TIME(FTM_LFS);
- io_pending += LLLFSThread::updateClass(1);
- }
-
- if (io_pending > 1000)
- {
- ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
- }
-
- total_work_pending += work_pending ;
- total_io_pending += io_pending ;
-
- if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
- {
- break;
- }
- }
- gMeshRepo.update() ;
+ total_work_pending += work_pending ;
+ total_io_pending += io_pending ;
- if(!total_work_pending) //pause texture fetching threads if nothing to process.
+ if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
{
- LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
- LLAppViewer::getTextureFetch()->pause();
+ break;
}
- if(!total_io_pending) //pause file threads if nothing to process.
- {
- LLVFSThread::sLocal->pause();
- LLLFSThread::sLocal->pause();
- }
+ }
+ gMeshRepo.update() ;
+
+ if(!total_work_pending) //pause texture fetching threads if nothing to process.
+ {
+ LLAppViewer::getTextureCache()->pause();
+ LLAppViewer::getImageDecodeThread()->pause();
+ LLAppViewer::getTextureFetch()->pause();
+ }
+ if(!total_io_pending) //pause file threads if nothing to process.
+ {
+ LLVFSThread::sLocal->pause();
+ LLLFSThread::sLocal->pause();
+ }
- //texture fetching debugger
- if(LLTextureFetchDebugger::isEnabled())
+ //texture fetching debugger
+ if(LLTextureFetchDebugger::isEnabled())
+ {
+ LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
+ if(tex_fetch_debugger_instance)
{
- LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
- LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
- if(tex_fetch_debugger_instance)
- {
- tex_fetch_debugger_instance->idle() ;
- }
+ tex_fetch_debugger_instance->idle() ;
}
+ }
- if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
- (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
- {
- gFrameStalls++;
- }
- frameTimer.reset();
+ if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
+ (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
+ {
+ gFrameStalls++;
+ }
+ frameTimer.reset();
- resumeMainloopTimeout();
-
- pingMainloopTimeout("Main:End");
- }
+ resumeMainloopTimeout();
+
+ pingMainloopTimeout("Main:End");
}
- catch(std::bad_alloc)
- {
- LLMemory::logMemoryInfo(TRUE) ;
+ }
+ catch (const LLContinueError&)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
+ }
+ catch(std::bad_alloc)
+ {
+ LLMemory::logMemoryInfo(TRUE) ;
- //stop memory leaking simulation
- LLFloaterMemLeak* mem_leak_instance =
- LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if(mem_leak_instance)
- {
- mem_leak_instance->stop() ;
- LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
- }
- else
- {
- //output possible call stacks to log file.
- LLError::LLCallStacks::print() ;
+ //stop memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
+ {
+ mem_leak_instance->stop() ;
+ LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
+ }
+ else
+ {
+ //output possible call stacks to log file.
+ LLError::LLCallStacks::print() ;
- LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
- }
+ LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION("");
+ }
if (LLApp::isExiting())
{
@@ -1600,7 +1583,7 @@ bool LLAppViewer::mainLoop()
catch(std::bad_alloc)
{
LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ;
-
+
//stop memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
@@ -1609,16 +1592,20 @@ bool LLAppViewer::mainLoop()
mem_leak_instance->stop() ;
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()");
+ }
}
-
+
delete gServicePump;
-
+
destroyMainloopTimeout();
-
+
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
- return LLApp::isExiting();
+ return ! LLApp::isRunning();
}
S32 LLAppViewer::updateTextureThreads(F32 max_time)
@@ -3342,6 +3329,19 @@ LLSD LLAppViewer::getViewerInfo() const
info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION;
#else
info["LLCEFLIB_VERSION"] = "Undefined";
+
+#endif
+
+#if LL_WINDOWS
+ std::ostringstream ver_codec;
+ ver_codec << LIBVLC_VERSION_MAJOR;
+ ver_codec << ".";
+ ver_codec << LIBVLC_VERSION_MINOR;
+ ver_codec << ".";
+ ver_codec << LIBVLC_VERSION_REVISION;
+ info["LIBVLC_VERSION"] = ver_codec.str();
+#else
+ info["LIBVLC_VERSION"] = "Undefined";
#endif
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
@@ -3438,6 +3438,12 @@ std::string LLAppViewer::getViewerInfoString() const
{
support << '\n' << LLTrans::getString("AboutTraffic", args);
}
+
+ // SLT timestamp
+ LLSD substitution;
+ substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected();
+ support << "\n" << LLTrans::getString("AboutTime", substitution);
+
return support.str();
}
@@ -5540,8 +5546,7 @@ void LLAppViewer::forceErrorInfiniteLoop()
void LLAppViewer::forceErrorSoftwareException()
{
LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL;
- // *FIX: Any way to insure it won't be handled?
- throw;
+ LLTHROW(LLException("User selected Force Software Exception"));
}
void LLAppViewer::forceErrorDriverCrash()
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index b5e674bd7b..f7c1bb58b4 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -79,7 +79,7 @@ public:
//
virtual bool init(); // Override to do application initialization
virtual bool cleanup(); // Override to do application cleanup
- virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
+ virtual bool frame(); // Override for application body logic
// Application control
void flushVFSIO(); // waits for vfs transfers to complete
@@ -283,7 +283,6 @@ private:
std::string mSerialNumber;
bool mPurgeCache;
bool mPurgeOnExit;
- bool mMainLoopInitialized;
LLViewerJoystick* joystick;
bool mSavedFinalSnapshot;
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index f5742b29cf..6f32aab851 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -95,10 +95,8 @@ int main( int argc, char **argv )
}
// Run the application main loop
- if(!LLApp::isQuitting())
- {
- viewer_app_ptr->mainLoop();
- }
+ while (! viewer_app_ptr->frame())
+ {}
if (!LLApp::isError())
{
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index ca219fda59..4fe1e31668 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -117,12 +117,17 @@ void handleQuit()
LLAppViewer::instance()->userQuit();
}
-bool runMainLoop()
+// This function is called pumpMainLoop() rather than runMainLoop() because
+// it passes control to the viewer's main-loop logic for a single frame. Like
+// LLAppViewer::frame(), it returns 'true' when it's done. Until then, it
+// expects to be called again by the timer in LLAppDelegate
+// (llappdelegate-objc.mm).
+bool pumpMainLoop()
{
bool ret = LLApp::isQuitting();
if (!ret && gViewerAppPtr != NULL)
{
- ret = gViewerAppPtr->mainLoop();
+ ret = gViewerAppPtr->frame();
} else {
ret = true;
}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 4786f83bfd..af0cd27fd5 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -317,10 +317,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
}
// Run the application main loop
- if(!LLApp::isQuitting())
- {
- viewer_app_ptr->mainLoop();
- }
+ while (! viewer_app_ptr->frame())
+ {}
if (!LLApp::isError())
{
@@ -330,33 +328,33 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
// app cleanup if there was a problem.
//
#if WINDOWS_CRT_MEM_CHECKS
- LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
- if (!_CrtCheckMemory())
- {
- LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " No corruption detected." << LL_ENDL;
- }
+ LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
+ if (!_CrtCheckMemory())
+ {
+ LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " No corruption detected." << LL_ENDL;
+ }
#endif
-
- gGLActive = TRUE;
- viewer_app_ptr->cleanup();
-
+ gGLActive = TRUE;
+
+ viewer_app_ptr->cleanup();
+
#if WINDOWS_CRT_MEM_CHECKS
- LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
- if (!_CrtCheckMemory())
- {
- LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " No corruption detected." << LL_ENDL;
- }
+ LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
+ if (!_CrtCheckMemory())
+ {
+ LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " No corruption detected." << LL_ENDL;
+ }
#endif
-
+
}
delete viewer_app_ptr;
viewer_app_ptr = NULL;
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 00bc8ebe87..a6e745448a 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -476,13 +476,63 @@ void LLAvatarActions::kick(const LLUUID& id)
}
// static
+void LLAvatarActions::freezeAvatar(const LLUUID& id)
+{
+ std::string fullname;
+ gCacheName->getFullName(id, fullname);
+ LLSD payload;
+ payload["avatar_id"] = id;
+
+ if (!fullname.empty())
+ {
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotificationsUtil::add("FreezeAvatarFullname", args, payload, handleFreezeAvatar);
+ }
+ else
+ {
+ LLNotificationsUtil::add("FreezeAvatar", LLSD(), payload, handleFreezeAvatar);
+ }
+}
+
+// static
+void LLAvatarActions::ejectAvatar(const LLUUID& id, bool ban_enabled)
+{
+ std::string fullname;
+ gCacheName->getFullName(id, fullname);
+ LLSD payload;
+ payload["avatar_id"] = id;
+ payload["ban_enabled"] = ban_enabled;
+ LLSD args;
+ if (!fullname.empty())
+ {
+ args["AVATAR_NAME"] = fullname;
+ }
+
+ if (ban_enabled)
+ {
+ LLNotificationsUtil::add("EjectAvatarFullname", args, payload, handleEjectAvatar);
+ }
+ else
+ {
+ if (!fullname.empty())
+ {
+ LLNotificationsUtil::add("EjectAvatarFullnameNoBan", args, payload, handleEjectAvatar);
+ }
+ else
+ {
+ LLNotificationsUtil::add("EjectAvatarNoBan", LLSD(), payload, handleEjectAvatar);
+ }
+ }
+}
+
+// static
void LLAvatarActions::freeze(const LLUUID& id)
{
LLSD payload;
payload["avatar_id"] = id;
LLNotifications::instance().add("FreezeUser", LLSD(), payload, handleFreeze);
}
-
// static
void LLAvatarActions::unfreeze(const LLUUID& id)
{
@@ -1133,10 +1183,77 @@ bool LLAvatarActions::handleKick(const LLSD& notification, const LLSD& response)
}
return false;
}
-bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response)
+
+bool LLAvatarActions::handleFreezeAvatar(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
+ if (0 == option || 1 == option)
+ {
+ U32 flags = 0x0;
+ if (1 == option)
+ {
+ // unfreeze
+ flags |= 0x1;
+ }
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage("FreezeUser");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("Data");
+ msg->addUUID("TargetID", avatar_id );
+ msg->addU32("Flags", flags );
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+
+bool LLAvatarActions::handleEjectAvatar(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (2 == option)
+ {
+ return false;
+ }
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean();
+
+ if (0 == option)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ U32 flags = 0x0;
+ msg->newMessage("EjectUser");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID() );
+ msg->addUUID("SessionID", gAgent.getSessionID() );
+ msg->nextBlock("Data");
+ msg->addUUID("TargetID", avatar_id );
+ msg->addU32("Flags", flags );
+ gAgent.sendReliableMessage();
+ }
+ else if (ban_enabled)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+
+ U32 flags = 0x1;
+ msg->newMessage("EjectUser");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID() );
+ msg->addUUID("SessionID", gAgent.getSessionID() );
+ msg->nextBlock("Data");
+ msg->addUUID("TargetID", avatar_id );
+ msg->addU32("Flags", flags );
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+
+bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
@@ -1153,6 +1270,7 @@ bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& respons
}
return false;
}
+
bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotification::getSelectedOption(notification, response);
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index bd0ac24e93..256d44d820 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -173,6 +173,9 @@ public:
*/
static void inviteToGroup(const LLUUID& id);
+ static void freezeAvatar(const LLUUID& id);
+
+ static void ejectAvatar(const LLUUID& id, bool ban_enabled = false);
/**
* Kick avatar off grid
*/
@@ -242,6 +245,8 @@ private:
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static bool handleRemove(const LLSD& notification, const LLSD& response);
static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);
+ static bool handleFreezeAvatar(const LLSD& notification, const LLSD& response);
+ static bool handleEjectAvatar(const LLSD& notification, const LLSD& response);
static bool handleKick(const LLSD& notification, const LLSD& response);
static bool handleFreeze(const LLSD& notification, const LLSD& response);
static bool handleUnfreeze(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 8846d1317d..513f25e301 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -140,6 +140,7 @@ LLAvatarList::LLAvatarList(const Params& p)
, mShowProfileBtn(p.show_profile_btn)
, mShowSpeakingIndicator(p.show_speaking_indicator)
, mShowPermissions(p.show_permissions_granted)
+, mShowCompleteName(false)
{
setCommitOnSelectionChange(true);
@@ -174,6 +175,11 @@ void LLAvatarList::setShowIcons(std::string param_name)
mShowIcons = gSavedSettings.getBOOL(mIconParamName);
}
+std::string LLAvatarList::getAvatarName(LLAvatarName av_name)
+{
+ return mShowCompleteName? av_name.getCompleteName(false) : av_name.getDisplayName();
+}
+
// virtual
void LLAvatarList::draw()
{
@@ -279,7 +285,7 @@ void LLAvatarList::refresh()
LLAvatarName av_name;
have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
- if (!have_filter || findInsensitive(av_name.getDisplayName(), mNameFilter))
+ if (!have_filter || findInsensitive(getAvatarName(av_name), mNameFilter))
{
if (nadded >= ADD_LIMIT)
{
@@ -297,7 +303,7 @@ void LLAvatarList::refresh()
}
else
{
- std::string display_name = av_name.getDisplayName();
+ std::string display_name = getAvatarName(av_name);
addNewItem(buddy_id,
display_name.empty() ? waiting_str : display_name,
LLAvatarTracker::instance().isBuddyOnline(buddy_id));
@@ -327,7 +333,7 @@ void LLAvatarList::refresh()
const LLUUID& buddy_id = it->asUUID();
LLAvatarName av_name;
have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
- if (!findInsensitive(av_name.getDisplayName(), mNameFilter))
+ if (!findInsensitive(getAvatarName(av_name), mNameFilter))
{
removeItemByUUID(buddy_id);
modified = true;
@@ -381,6 +387,7 @@ void LLAvatarList::updateAvatarNames()
for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
{
LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
+ item->setShowCompleteName(mShowCompleteName);
item->updateAvatarName();
}
mNeedUpdateNames = false;
@@ -400,7 +407,7 @@ bool LLAvatarList::filterHasMatches()
// If name has not been loaded yet we consider it as a match.
// When the name will be loaded the filter will be applied again(in refresh()).
- if (have_name && !findInsensitive(av_name.getDisplayName(), mNameFilter))
+ if (have_name && !findInsensitive(getAvatarName(av_name), mNameFilter))
{
continue;
}
@@ -434,6 +441,7 @@ S32 LLAvatarList::notifyParent(const LLSD& info)
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
+ item->setShowCompleteName(mShowCompleteName);
// This sets the name as a side effect
item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus);
item->setOnline(mIgnoreOnlineStatus ? true : is_online);
@@ -445,6 +453,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is
item->showSpeakingIndicator(mShowSpeakingIndicator);
item->setShowPermissions(mShowPermissions);
+
item->setDoubleClickCallback(boost::bind(&LLAvatarList::onItemDoubleClicked, this, _1, _2, _3, _4));
addItem(item, id, pos);
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index 3542577ae3..1a672c279b 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -83,6 +83,7 @@ public:
void setShowIcons(std::string param_name);
bool getIconsVisible() const { return mShowIcons; }
const std::string getIconParamName() const{return mIconParamName;}
+ std::string getAvatarName(LLAvatarName av_name);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -100,6 +101,8 @@ public:
void addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name);
void handleDisplayNamesOptionChanged();
+ void setShowCompleteName(bool show) { mShowCompleteName = show;};
+
protected:
void refresh();
@@ -126,6 +129,7 @@ private:
bool mShowProfileBtn;
bool mShowSpeakingIndicator;
bool mShowPermissions;
+ bool mShowCompleteName;
LLTimer* mLITUpdateTimer; // last interaction time update timer
std::string mIconParamName;
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 3e6c817dd6..af3fac91bc 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -77,8 +77,10 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)
mShowInfoBtn(true),
mShowProfileBtn(true),
mShowPermissions(false),
+ mShowCompleteName(false),
mHovered(false),
- mAvatarNameCacheConnection()
+ mAvatarNameCacheConnection(),
+ mGreyOutUsername("")
{
if (not_from_ui_factory)
{
@@ -399,14 +401,28 @@ void LLAvatarListItem::updateAvatarName()
void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight)
{
- LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight);
+ if(mShowCompleteName && highlight.empty())
+ {
+ LLTextUtil::textboxSetGreyedVal(mAvatarName, mAvatarNameStyle, name, mGreyOutUsername);
+ }
+ else
+ {
+ LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight);
+ }
}
void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name)
{
mAvatarNameCacheConnection.disconnect();
- setAvatarName(av_name.getDisplayName());
+ mGreyOutUsername = "";
+ std::string name_string = mShowCompleteName? av_name.getCompleteName(false) : av_name.getDisplayName();
+ if(av_name.getCompleteName() != av_name.getUserName())
+ {
+ mGreyOutUsername = "[ " + av_name.getUserName(true) + " ]";
+ LLStringUtil::toLower(mGreyOutUsername);
+ }
+ setAvatarName(name_string);
setAvatarToolTip(av_name.getUserName());
//requesting the list to resort
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index 7ef35a746e..36d18114aa 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -106,6 +106,7 @@ public:
void setShowPermissions(bool show) { mShowPermissions = show; };
void showLastInteractionTime(bool show);
void setAvatarIconVisible(bool visible);
+ void setShowCompleteName(bool show) { mShowCompleteName = show;};
const LLUUID& getAvatarId() const;
std::string getAvatarName() const;
@@ -218,6 +219,9 @@ private:
/// true when the mouse pointer is hovering over this item
bool mHovered;
+ bool mShowCompleteName;
+ std::string mGreyOutUsername;
+
void fetchAvatarName();
boost::signals2::connection mAvatarNameCacheConnection;
diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp
index a13e142e16..24934fdb73 100644
--- a/indra/newview/llavatarrendernotifier.cpp
+++ b/indra/newview/llavatarrendernotifier.cpp
@@ -63,7 +63,7 @@ mLatestAgentComplexity(0),
mLatestOverLimitPct(0.0f),
mShowOverLimitAgents(false),
mNotifyOutfitLoading(false),
-mLastCofVersion(-1),
+mLastCofVersion(LLViewerInventoryCategory::VERSION_UNKNOWN),
mLastOutfitRezStatus(-1),
mLastSkeletonSerialNum(-1)
{
@@ -207,8 +207,8 @@ void LLAvatarRenderNotifier::updateNotificationState()
mLastSkeletonSerialNum = gAgentAvatarp->mLastSkeletonSerialNum;
}
else if (mLastCofVersion >= 0
- && (mLastCofVersion != gAgentAvatarp->mLastUpdateRequestCOFVersion
- || mLastSkeletonSerialNum != gAgentAvatarp->mLastSkeletonSerialNum))
+ && (mLastCofVersion != LLAppearanceMgr::instance().getCOFVersion()
+ || mLastSkeletonSerialNum != gAgentAvatarp->mLastSkeletonSerialNum))
{
// version mismatch in comparison to previous outfit - outfit changed
mNotifyOutfitLoading = true;
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 4b426081d0..5d2997688f 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -156,6 +156,10 @@ public:
LLFloaterSidePanelContainer::showPanel("people", "panel_people",
LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));
}
+ else if (level == "unblock")
+ {
+ LLMuteList::getInstance()->remove(LLMute(getAvatarId(), mFrom, LLMute::OBJECT));
+ }
else if (level == "map")
{
std::string url = "secondlife://" + mObjectData["slurl"].asString();
@@ -169,6 +173,20 @@ public:
}
+ bool onObjectIconContextMenuItemVisible(const LLSD& userdata)
+ {
+ std::string level = userdata.asString();
+ if (level == "is_blocked")
+ {
+ return LLMuteList::getInstance()->isMuted(getAvatarId(), mFrom, LLMute::flagTextChat);
+ }
+ else if (level == "not_blocked")
+ {
+ return !LLMuteList::getInstance()->isMuted(getAvatarId(), mFrom, LLMute::flagTextChat);
+ }
+ return false;
+ }
+
void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
{
std::string level = userdata.asString();
@@ -275,6 +293,7 @@ public:
registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
+ registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));
LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mPopupMenuHandleAvatar = menu->getHandle();
@@ -719,6 +738,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
editor_params.trusted_content = false;
mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);
mEditor->setIsFriendCallback(LLAvatarActions::isFriend);
+ mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
+
}
LLSD LLChatHistory::getValue() const
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index 1819fc74ee..90a5483dc9 100644
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -26,6 +26,7 @@
#include "llviewerprecompiledheaders.h"
#include "llcommandlineparser.h"
+#include "llexception.h"
// *NOTE: The boost::lexical_cast generates
// the warning C4701(local used with out assignment) in VC7.1.
@@ -50,6 +51,7 @@
#include "llsdserialize.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
#include <string>
#include <set>
#include <iostream>
@@ -98,14 +100,14 @@ namespace
bool gPastLastOption = false;
}
-class LLCLPError : public std::logic_error {
+class LLCLPError : public LLException {
public:
- LLCLPError(const std::string& what) : std::logic_error(what) {}
+ LLCLPError(const std::string& what) : LLException(what) {}
};
-class LLCLPLastOption : public std::logic_error {
+class LLCLPLastOption : public LLException {
public:
- LLCLPLastOption(const std::string& what) : std::logic_error(what) {}
+ LLCLPLastOption(const std::string& what) : LLException(what) {}
};
class LLCLPValue : public po::value_semantic_codecvt_helper<char>
@@ -202,17 +204,17 @@ protected:
{
if(gPastLastOption)
{
- throw(LLCLPLastOption("Don't parse no more!"));
+ LLTHROW(LLCLPLastOption("Don't parse no more!"));
}
// Error checks. Needed?
if (!value_store.empty() && !is_composing())
{
- throw(LLCLPError("Non composing value with multiple occurences."));
+ LLTHROW(LLCLPError("Non composing value with multiple occurences."));
}
if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens())
{
- throw(LLCLPError("Illegal number of tokens specified."));
+ LLTHROW(LLCLPError("Illegal number of tokens specified."));
}
if(value_store.empty())
@@ -466,7 +468,7 @@ onevalue(const std::string& option,
{
// What does it mean when the user specifies a command-line switch
// that requires a value, but omits the value? Complain.
- throw LLCLPError(STRINGIZE("No value specified for --" << option << "!"));
+ LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));
}
else if (value.size() > 1)
{
@@ -484,9 +486,9 @@ void badvalue(const std::string& option,
// If the user passes an unusable value for a command-line switch, it
// seems like a really bad idea to just ignore it, even with a log
// warning.
- throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
- << "' for variable '" << varname << "' of type " << type
- << ": '" << value << "'"));
+ LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
+ << "' for variable '" << varname << "' of type " << type
+ << ": '" << value << "'")));
}
template <typename T>
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 219bcf0eb0..7721e67290 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -62,6 +62,57 @@
#include "llviewerassetupload.h"
#include "llcorehttputil.h"
+namespace
+{
+
+ const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue");
+
+
+ class ObjectInventoryFetcher: public LLVOInventoryListener
+ {
+ public:
+ typedef boost::shared_ptr<ObjectInventoryFetcher> ptr_t;
+
+ ObjectInventoryFetcher(LLEventPump &pump, LLViewerObject* object, void* user_data) :
+ mPump(pump),
+ LLVOInventoryListener()
+ {
+ registerVOInventoryListener(object, this);
+ }
+
+ virtual void inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void* user_data);
+
+ void fetchInventory()
+ {
+ requestVOInventory();
+ }
+
+ const LLInventoryObject::object_list_t & getInventoryList() const { return mInventoryList; }
+
+ private:
+ LLInventoryObject::object_list_t mInventoryList;
+ LLEventPump & mPump;
+ };
+
+ class HandleScriptUserData
+ {
+ public:
+ HandleScriptUserData(const std::string &pumpname) :
+ mPumpname(pumpname)
+ { }
+
+ const std::string &getPumpName() const { return mPumpname; }
+
+ private:
+ std::string mPumpname;
+ };
+
+
+}
+
// *NOTE$: A minor specialization of LLScriptAssetUpload, it does not require a buffer
// (and does not save a buffer to the vFS) and it finds the compile queue window and
// displays a compiling message.
@@ -149,47 +200,6 @@ BOOL LLFloaterScriptQueue::postBuild()
return TRUE;
}
-// This is the callback method for the viewer object currently being
-// worked on.
-// NOT static, virtual!
-void LLFloaterScriptQueue::inventoryChanged(LLViewerObject* viewer_object,
- LLInventoryObject::object_list_t* inv,
- S32,
- void* q_id)
-{
- LL_INFOS() << "LLFloaterScriptQueue::inventoryChanged() for object "
- << viewer_object->getID() << LL_ENDL;
-
- //Remove this listener from the object since its
- //listener callback is now being executed.
-
- //We remove the listener here because the function
- //removeVOInventoryListener removes the listener from a ViewerObject
- //which it internally stores.
-
- //If we call this further down in the function, calls to handleInventory
- //and nextObject may update the internally stored viewer object causing
- //the removal of the incorrect listener from an incorrect object.
-
- //Fixes SL-6119:Recompile scripts fails to complete
- removeVOInventoryListener();
-
- if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) )
- {
- handleInventory(viewer_object, inv);
- }
- else
- {
- // something went wrong...
- // note that we're not working on this one, and move onto the
- // next object in the list.
- LL_WARNS() << "No inventory for " << mCurrentObjectID
- << LL_ENDL;
- nextObject();
- }
-}
-
-
// static
void LLFloaterScriptQueue::onCloseBtn(void* user_data)
{
@@ -197,9 +207,10 @@ void LLFloaterScriptQueue::onCloseBtn(void* user_data)
self->closeFloater();
}
-void LLFloaterScriptQueue::addObject(const LLUUID& id)
+void LLFloaterScriptQueue::addObject(const LLUUID& id, std::string name)
{
- mObjectIDs.push_back(id);
+ ObjectData obj = { id, name };
+ mObjectList.push_back(obj);
}
BOOL LLFloaterScriptQueue::start()
@@ -208,7 +219,7 @@ BOOL LLFloaterScriptQueue::start()
LLStringUtil::format_map_t args;
args["[START]"] = mStartString;
- args["[COUNT]"] = llformat ("%d", mObjectIDs.size());
+ args["[COUNT]"] = llformat ("%d", mObjectList.size());
buffer = getString ("Starting", args);
getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
@@ -216,74 +227,24 @@ BOOL LLFloaterScriptQueue::start()
return startQueue();
}
-BOOL LLFloaterScriptQueue::isDone() const
+void LLFloaterScriptQueue::addProcessingMessage(const std::string &message, const LLSD &args)
{
- return (mCurrentObjectID.isNull() && (mObjectIDs.size() == 0));
-}
+ std::string buffer(LLTrans::getString(message, args));
-// go to the next object. If no objects left, it falls out silently
-// and waits to be killed by the window being closed.
-BOOL LLFloaterScriptQueue::nextObject()
-{
- U32 count;
- BOOL successful_start = FALSE;
- do
- {
- count = mObjectIDs.size();
- LL_INFOS() << "LLFloaterScriptQueue::nextObject() - " << count
- << " objects left to process." << LL_ENDL;
- mCurrentObjectID.setNull();
- if(count > 0)
- {
- successful_start = popNext();
- }
- LL_INFOS() << "LLFloaterScriptQueue::nextObject() "
- << (successful_start ? "successful" : "unsuccessful")
- << LL_ENDL;
- } while((mObjectIDs.size() > 0) && !successful_start);
- if(isDone() && !mDone)
- {
- mDone = true;
- getChild<LLScrollListCtrl>("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM);
- getChildView("close")->setEnabled(TRUE);
- }
- return successful_start;
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
}
-// returns true if the queue has started, otherwise false. This
-// method pops the top object off of the queue.
-BOOL LLFloaterScriptQueue::popNext()
+void LLFloaterScriptQueue::addStringMessage(const std::string &message)
{
- // get the first element off of the container, and attempt to get
- // the inventory.
- BOOL rv = FALSE;
- S32 count = mObjectIDs.size();
- if(mCurrentObjectID.isNull() && (count > 0))
- {
- mCurrentObjectID = mObjectIDs.at(0);
- LL_INFOS() << "LLFloaterScriptQueue::popNext() - mCurrentID: "
- << mCurrentObjectID << LL_ENDL;
- mObjectIDs.erase(mObjectIDs.begin());
- LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
- if(obj)
- {
- LL_INFOS() << "LLFloaterScriptQueue::popNext() requesting inv for "
- << mCurrentObjectID << LL_ENDL;
- LLUUID* id = new LLUUID(getKey().asUUID());
- registerVOInventoryListener(obj,id);
- requestVOInventory();
- rv = TRUE;
- }
- }
- return rv;
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
}
-BOOL LLFloaterScriptQueue::startQueue()
+
+BOOL LLFloaterScriptQueue::isDone() const
{
- return nextObject();
+ return (mCurrentObjectID.isNull() && (mObjectList.size() == 0));
}
-
///----------------------------------------------------------------------------
/// Class LLFloaterCompileQueue
///----------------------------------------------------------------------------
@@ -306,7 +267,7 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content )
{
mExperienceIds.insert(it->asUUID());
}
- nextObject();
+// nextObject();
}
BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
@@ -314,188 +275,289 @@ BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
return mExperienceIds.find(id) != mExperienceIds.end();
}
+// //Attempt to record this asset ID. If it can not be inserted into the set
+// //then it has already been processed so return false.
+// bool LLFloaterCompileQueue::checkAssetId(const LLUUID &assetId)
+// {
+// std::pair<uuid_list_t::iterator, bool> result = mAssetIds.insert(assetId);
+// return result.second;
+// }
-void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
- LLInventoryObject::object_list_t* inv)
+void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult)
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
+ LLEventPumps::instance().post(pumpName, expresult);
+}
- typedef std::multimap<LLUUID, LLPointer<LLInventoryItem> > uuid_item_map;
- uuid_item_map asset_item_map;
+// *TODO: handleSCriptRetrieval is passed into the VFS via a legacy C function pointer
+// future project would be to convert these to C++ callables (std::function<>) so that
+// we can use bind and remove the userData parameter.
+//
+void LLFloaterCompileQueue::handleScriptRetrieval(LLVFS *vfs, const LLUUID& assetId,
+ LLAssetType::EType type, void* userData, S32 status, LLExtStat extStatus)
+{
+ LLSD result(LLSD::emptyMap());
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- // Check permissions before allowing the user to retrieve data.
- if (item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) &&
- item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()) )
- {
- LLPointer<LLViewerInventoryItem> script = new LLViewerInventoryItem(item);
- mCurrentScripts.push_back(script);
- asset_item_map.insert(std::make_pair(item->getAssetUUID(), item));
- }
- }
- }
+ result["asset_id"] = assetId;
+ if (status)
+ {
+ result["error"] = status;
+
+ if (status == LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE)
+ {
+ result["message"] = LLTrans::getString("CompileQueueProblemDownloading") + (":");
+ result["alert"] = LLTrans::getString("CompileQueueScriptNotFound");
+ }
+ else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
+ {
+ result["message"] = LLTrans::getString("CompileQueueInsufficientPermFor") + (":");
+ result["alert"] = LLTrans::getString("CompileQueueInsufficientPermDownload");
+ }
+ else
+ {
+ result["message"] = LLTrans::getString("CompileQueueUnknownFailure");
+ }
+ }
- if (asset_item_map.empty())
- {
- // There are no scripts in this object. move on.
- nextObject();
- }
- else
- {
- // request all of the assets.
- uuid_item_map::iterator iter;
- for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++)
- {
- LLInventoryItem *itemp = iter->second;
- LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(),
- viewer_object->getID(), itemp);
-
- LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
- boost::bind(&LLFloaterCompileQueue::requestAsset, datap, _1));
- }
- }
-}
+ LLEventPumps::instance().post(((HandleScriptUserData *)userData)->getPumpName(), result);
+}
-void LLFloaterCompileQueue::requestAsset( LLScriptQueueData* datap, const LLSD& experience )
+/*static*/
+void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent)
{
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", datap->mQueueID);
- if(!queue)
- {
- delete datap;
- return;
- }
- if(experience.has(LLExperienceCache::EXPERIENCE_ID))
- {
- datap->mExperienceId=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
- if(!queue->hasExperience(datap->mExperienceId))
- {
- std::string buffer = LLTrans::getString("CompileNoExperiencePerm", LLSD::emptyMap()
- .with("SCRIPT", datap->mItem->getName())
- .with("EXPERIENCE", experience[LLExperienceCache::NAME].asString()));
-
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
- queue->removeItemByItemID(datap->mItem->getUUID());
- delete datap;
- return;
- }
- }
- //LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL;
- gAssetStorage->getInvItemAsset(datap->mHost,
- gAgent.getID(),
- gAgent.getSessionID(),
- datap->mItem->getPermissions().getOwner(),
- datap->mTaskId,
- datap->mItem->getUUID(),
- datap->mItem->getAssetUUID(),
- datap->mItem->getType(),
- LLFloaterCompileQueue::scriptArrived,
- (void*)datap);
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", parent);
+ if (!queue)
+ return;
+
+ queue->experienceIdsReceived(result["experience_ids"]);
+
+ LLHandle<LLFloaterScriptQueue> hFloater(queue->getDerivedHandle<LLFloaterScriptQueue>());
+
+ fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript,
+ queue->getDerivedHandle<LLFloaterCompileQueue>(), _1, _2, _3);
+
+
+ LLCoros::instance().launch("ScriptQueueCompile", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ queue->mStartString,
+ hFloater,
+ queue->mObjectList,
+ fn));
+
}
-/*static*/
-void LLFloaterCompileQueue::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId)
+bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
+ LLSD result;
+ LLFloaterCompileQueue *that = hfloater.get();
+ bool monocompile = that->mMono;
+ F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
+
+ if (!that)
+ return false;
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(queueId));
- if (queue)
+ // Initial test to see if we can (or should) attempt to compile the script.
+ LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory);
{
- // Bytecode save completed
- if (response["compiled"])
+
+ if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) ||
+ !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
{
- std::string message = std::string("Compilation of \"") + scriptName + std::string("\" succeeded");
+ std::string buffer = "Skipping: " + item->getName() + "(Permissions)";
+ that->addStringMessage(buffer);
+ return true;
+ }
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
- LL_INFOS() << message << LL_ENDL;
+// if (!that->checkAssetId(item->getAssetUUID()))
+// {
+// std::string buffer = "Skipping: " + item->getName() + "(Repeat)";
+// that->addStringMessage(buffer);
+// return true;
+// }
+ }
+ that = NULL;
+
+ // Attempt to retrieve the experience
+ LLUUID experienceId;
+ {
+ LLExperienceCache::instance().fetchAssociatedExperience(inventory->getParentUUID(), inventory->getUUID(),
+ boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1));
+
+ result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
+ LLSD().with("timeout", LLSD::Boolean(true)));
+
+ that = hfloater.get();
+ if (!that)
+ {
+ return false;
}
- else
+
+ if (result.has("timeout") && result["timeout"].asBoolean())
{
- LLSD compile_errors = response["errors"];
- for (LLSD::array_const_iterator line = compile_errors.beginArray();
- line < compile_errors.endArray(); line++)
- {
- std::string str = line->asString();
- str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = that->getString("Timeout", args);
+ that->addStringMessage(buffer);
+ return true;
+ }
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(str, ADD_BOTTOM);
+ if (result.has(LLExperienceCache::EXPERIENCE_ID))
+ {
+ experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID();
+ if (!that->hasExperience(experienceId))
+ {
+ that->addProcessingMessage("CompileNoExperiencePerm", LLSD()
+ .with("SCRIPT", inventory->getName())
+ .with("EXPERIENCE", result[LLExperienceCache::NAME].asString()));
+ return true;
}
- LL_INFOS() << response["errors"] << LL_ENDL;
}
}
+ that = NULL;
+
+ {
+ HandleScriptUserData userData(pump.getName());
+
+
+ // request the asset
+ gAssetStorage->getInvItemAsset(LLHost(),
+ gAgent.getID(),
+ gAgent.getSessionID(),
+ item->getPermissions().getOwner(),
+ object->getID(),
+ item->getUUID(),
+ item->getAssetUUID(),
+ item->getType(),
+ &LLFloaterCompileQueue::handleScriptRetrieval,
+ &userData);
+
+ result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
+ LLSD().with("timeout", LLSD::Boolean(true)));
+ }
+
+ that = hfloater.get();
+ if (!that)
+ {
+ return false;
+ }
+
+ if (result.has("timeout"))
+ {
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = that->getString("Timeout", args);
+ that->addStringMessage(buffer);
+ return true;
+ }
+ }
+
+ if (result.has("error"))
+ {
+ LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL;
+ std::string buffer = result["message"].asString() + " " + inventory->getName();
+ that->addStringMessage(buffer);
+
+ if (result.has("alert"))
+ {
+ LLSD args;
+ args["MESSAGE"] = result["alert"].asString();
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
+ return true;
+ }
+
+ LLUUID assetId = result["asset_id"];
+ that = NULL;
+
+
+ std::string url = object->getRegion()->getCapability("UpdateScriptTask");
+
+
+ {
+ LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(),
+ inventory->getUUID(),
+ assetId,
+ monocompile ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2,
+ true,
+ inventory->getName(),
+ LLUUID(),
+ experienceId,
+ boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _4)));
+
+ LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+ }
+
+ result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSD().with("timeout", LLSD::Boolean(true)));
+
+ that = hfloater.get();
+ if (!that)
+ {
+ return false;
+ }
+
+ if (result.has("timeout"))
+ {
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = that->getString("Timeout", args);
+ that->addStringMessage(buffer);
+ return true;
+ }
+ }
+
+ // Bytecode save completed
+ if (result["compiled"])
+ {
+ std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded");
+
+ that->addStringMessage(buffer);
+ LL_INFOS() << buffer << LL_ENDL;
+ }
+ else
+ {
+ LLSD compile_errors = result["errors"];
+ std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:");
+ that->addStringMessage(buffer);
+ for (LLSD::array_const_iterator line = compile_errors.beginArray();
+ line < compile_errors.endArray(); line++)
+ {
+ std::string str = line->asString();
+ str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
+
+ that->addStringMessage(str);
+ }
+ LL_INFOS() << result["errors"] << LL_ENDL;
+ }
+
+ return true;
}
-// This is the callback for when each script arrives
-// static
-void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
- LLAssetType::EType type,
- void* user_data, S32 status, LLExtStat ext_status)
+bool LLFloaterCompileQueue::startQueue()
{
- LL_INFOS() << "LLFloaterCompileQueue::scriptArrived()" << LL_ENDL;
- LLScriptQueueData* data = (LLScriptQueueData*)user_data;
- if(!data)
- {
- return;
- }
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", data->mQueueID);
-
- std::string buffer;
- if(queue && (0 == status))
- {
- LLViewerObject* object = gObjectList.findObject(data->mTaskId);
- if (object)
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string lookup_url = region->getCapability("GetCreatorExperiences");
+ if (!lookup_url.empty())
{
- std::string url = object->getRegion()->getCapability("UpdateScriptTask");
- std::string scriptName = data->mItem->getName();
-
- LLBufferedAssetUploadInfo::taskUploadFinish_f proc = boost::bind(&LLFloaterCompileQueue::finishLSLUpload, _1, _2, _3, _4,
- scriptName, data->mQueueID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success =
+ boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID());
- LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(data->mTaskId, data->mItem->getUUID(), asset_id,
- (queue->mMono) ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2,
- true, scriptName, data->mQueueID, data->mExperienceId, proc));
+ LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure =
+ boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID());
- LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+ LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url,
+ success, failure);
+ return TRUE;
}
- }
- else
- {
- if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
- {
- LLSD args;
- args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound");
- LLNotificationsUtil::add("SystemMessage", args);
-
- buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mItem->getName();
- }
- else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
- {
- LLSD args;
- args["MESSAGE"] = LLTrans::getString("CompileQueueInsufficientPermDownload");
- LLNotificationsUtil::add("SystemMessage", args);
-
- buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mItem->getName();
- }
- else
- {
- buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mItem->getName();
- }
-
- LL_WARNS() << "Problem downloading script asset." << LL_ENDL;
- if(queue) queue->removeItemByItemID(data->mItem->getUUID());
- }
- if(queue && (buffer.size() > 0))
- {
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
- }
- delete data;
+ }
+
+ return true;
}
@@ -514,40 +576,42 @@ LLFloaterResetQueue::~LLFloaterResetQueue()
{
}
-void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv)
+bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
+{
+ LLFloaterScriptQueue *that = hfloater.get();
+ if (that)
+ {
+ std::string buffer;
+ buffer = that->getString("Resetting") + (": ") + inventory->getName();
+ that->addStringMessage(buffer);
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ScriptReset);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_Script);
+ msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+ msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID());
+ msg->sendReliable(object->getRegion()->getHost());
+
+ return true;
+}
+
+bool LLFloaterResetQueue::startQueue()
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
+ fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts,
+ getDerivedHandle<LLFloaterScriptQueue>(), _1, _2, _3);
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
-
- if (object)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- std::string buffer;
- buffer = getString("Resetting") + (": ") + item->getName();
- getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ScriptReset);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, viewer_obj->getID());
- msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID());
- msg->sendReliable(object->getRegion()->getHost());
- }
- }
- }
+ LLCoros::instance().launch("ScriptResetQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ mStartString,
+ getDerivedHandle<LLFloaterScriptQueue>(),
+ mObjectList,
+ fn));
- nextObject();
+ return true;
}
///----------------------------------------------------------------------------
@@ -565,44 +629,46 @@ LLFloaterRunQueue::~LLFloaterRunQueue()
{
}
-void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv)
+bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
-
- if (object)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
- std::string buffer;
- buffer = getString("Running") + (": ") + item->getName();
- list->addSimpleElement(buffer, ADD_BOTTOM);
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_SetScriptRunning);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, viewer_obj->getID());
- msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID());
- msg->addBOOLFast(_PREHASH_Running, TRUE);
- msg->sendReliable(object->getRegion()->getHost());
- }
- }
- }
+ LLFloaterScriptQueue *that = hfloater.get();
+ if (that)
+ {
+ std::string buffer;
+ buffer = that->getString("Running") + (": ") + inventory->getName();
+ that->addStringMessage(buffer);
+ }
- nextObject();
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_SetScriptRunning);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_Script);
+ msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+ msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID());
+ msg->addBOOLFast(_PREHASH_Running, TRUE);
+ msg->sendReliable(object->getRegion()->getHost());
+
+ return true;
}
+bool LLFloaterRunQueue::startQueue()
+{
+ LLHandle<LLFloaterScriptQueue> hFloater(getDerivedHandle<LLFloaterScriptQueue>());
+ fnQueueAction_t fn = boost::bind(LLFloaterRunQueue::runObjectScripts, hFloater, _1, _2, _3);
+
+ LLCoros::instance().launch("ScriptRunQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ mStartString,
+ hFloater,
+ mObjectList,
+ fn));
+
+ return true;
+}
+
+
///----------------------------------------------------------------------------
/// Class LLFloaterNotRunQueue
///----------------------------------------------------------------------------
@@ -618,96 +684,171 @@ LLFloaterNotRunQueue::~LLFloaterNotRunQueue()
{
}
-void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id)
+bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- LL_INFOS() << "LLFloaterCompileQueue::removeItemByAssetID()" << LL_ENDL;
- for(S32 i = 0; i < mCurrentScripts.size(); )
- {
- if(asset_id == mCurrentScripts.at(i)->getUUID())
- {
- vector_replace_with_last(mCurrentScripts, mCurrentScripts.begin() + i);
- }
- else
- {
- ++i;
- }
- }
- if(mCurrentScripts.empty())
- {
- nextObject();
- }
+ LLFloaterScriptQueue *that = hfloater.get();
+ if (that)
+ {
+ std::string buffer;
+ buffer = that->getString("NotRunning") + (": ") + inventory->getName();
+ that->addStringMessage(buffer);
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_SetScriptRunning);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_Script);
+ msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+ msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID());
+ msg->addBOOLFast(_PREHASH_Running, FALSE);
+ msg->sendReliable(object->getRegion()->getHost());
+
+ return true;
}
-BOOL LLFloaterCompileQueue::startQueue()
+bool LLFloaterNotRunQueue::startQueue()
{
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string lookup_url=region->getCapability("GetCreatorExperiences");
- if(!lookup_url.empty())
- {
- LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success =
- boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID());
+ LLHandle<LLFloaterScriptQueue> hFloater(getDerivedHandle<LLFloaterScriptQueue>());
- LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure =
- boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID());
+ fnQueueAction_t fn = boost::bind(&LLFloaterNotRunQueue::stopObjectScripts, hFloater, _1, _2, _3);
+ LLCoros::instance().launch("ScriptQueueNotRun", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ mStartString,
+ hFloater,
+ mObjectList,
+ fn));
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url,
- success, failure);
- return TRUE;
- }
- }
- return nextObject();
+ return true;
}
-/*static*/
-void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent)
+///----------------------------------------------------------------------------
+/// Local function definitions
+///----------------------------------------------------------------------------
+void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data)
{
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", parent);
- if (!queue)
- return;
+ mInventoryList.clear();
+ mInventoryList.assign(inventory->begin(), inventory->end());
+
+ mPump.post(LLSD().with("changed", LLSD::Boolean(true)));
- queue->experienceIdsReceived(result["experience_ids"]);
}
-void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv)
+void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, LLHandle<LLFloaterScriptQueue> hfloater,
+ object_data_list_t objectList, fnQueueAction_t func)
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
-
- if (object)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
- std::string buffer;
- buffer = getString("NotRunning") + (": ") +item->getName();
- list->addSimpleElement(buffer, ADD_BOTTOM);
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_SetScriptRunning);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, viewer_obj->getID());
- msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID());
- msg->addBOOLFast(_PREHASH_Running, FALSE);
- msg->sendReliable(object->getRegion()->getHost());
- }
- }
- }
+ LLCoros::set_consuming(true);
+ LLFloaterScriptQueue * floater(NULL);
+ LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true);
+ F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
+
+// floater = hfloater.get();
+// floater->addProcessingMessage("Starting",
+// LLSD()
+// .with("[START]", action)
+// .with("[COUNT]", LLSD::Integer(objectList.size())));
+// floater = NULL;
+
+ for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj)
+ {
+ bool firstForObject = true;
+ LLUUID object_id = (*itObj).mObjectId;
+ LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL;
- nextObject();
-}
+ LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id);
+ LLInventoryObject::object_list_t inventory;
+ if (obj)
+ {
+ ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL));
-///----------------------------------------------------------------------------
-/// Local function definitions
-///----------------------------------------------------------------------------
+ fetcher->fetchInventory();
+
+ floater = hfloater.get();
+ if (floater)
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = (*itObj).mObjectName;
+ floater->addStringMessage(floater->getString("LoadingObjInv", args));
+ }
+
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
+ LLSD().with("timeout", LLSD::Boolean(true)));
+
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() <<
+ ". Skipping to next object." << LL_ENDL;
+
+ // floater could have been closed
+ floater = hfloater.get();
+ if (floater)
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = (*itObj).mObjectName;
+ floater->addStringMessage(floater->getString("Timeout", args));
+ }
+
+ continue;
+ }
+
+ inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end());
+ }
+ else
+ {
+ LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id <<
+ ". Skipping to next." << LL_ENDL;
+ continue;
+ }
+
+ // TODO: Get the name of the object we are looking at here so that we can display it below.
+ //std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName();
+ LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL;
+
+ for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin();
+ itInv != inventory.end(); ++itInv)
+ {
+ floater = hfloater.get();
+ if (!floater)
+ {
+ LL_WARNS("SCRIPTQ") << "Script Queue floater closed! Canceling remaining ops" << LL_ENDL;
+ break;
+ }
+
+ // note, we have a smart pointer to the obj above... but if we didn't we'd check that
+ // it still exists here.
+
+ if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT))
+ {
+ LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL;
+ if (firstForObject)
+ {
+ //floater->addStringMessage(objName + ":");
+ firstForObject = false;
+ }
+
+ if (!func(obj, (*itInv), maildrop))
+ {
+ continue;
+ }
+ }
+
+ llcoro::suspend();
+ }
+ // Just test to be sure the floater is still present before calling the func
+ if (!hfloater.get())
+ {
+ LL_WARNS("SCRIPTQ") << "Script Queue floater dismissed." << LL_ENDL;
+ break;
+ }
+
+ }
+
+ floater = hfloater.get();
+ if (floater)
+ {
+ floater->addStringMessage("Done");
+ floater->getChildView("close")->setEnabled(TRUE);
+ }
+}
diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h
index 46bcb9746b..1b3d8f83a0 100644
--- a/indra/newview/llcompilequeue.h
+++ b/indra/newview/llcompilequeue.h
@@ -37,6 +37,8 @@
#include "llviewerinventory.h"
+#include "llevents.h"
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFloaterScriptQueue
//
@@ -48,7 +50,7 @@
// scripts manipulated.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLFloaterScriptQueue : public LLFloater, public LLVOInventoryListener
+class LLFloaterScriptQueue : public LLFloater/*, public LLVOInventoryListener*/
{
public:
LLFloaterScriptQueue(const LLSD& key);
@@ -59,34 +61,23 @@ public:
void setMono(bool mono) { mMono = mono; }
// addObject() accepts an object id.
- void addObject(const LLUUID& id);
+ void addObject(const LLUUID& id, std::string name);
// start() returns TRUE if the queue has started, otherwise FALSE.
BOOL start();
-protected:
- // This is the callback method for the viewer object currently
- // being worked on.
- /*virtual*/ void inventoryChanged(LLViewerObject* obj,
- LLInventoryObject::object_list_t* inv,
- S32 serial_num,
- void* queue);
-
- // This is called by inventoryChanged
- virtual void handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv) = 0;
+ void addProcessingMessage(const std::string &message, const LLSD &args);
+ void addStringMessage(const std::string &message);
+ std::string getStartString() const { return mStartString; }
+
+protected:
static void onCloseBtn(void* user_data);
// returns true if this is done
BOOL isDone() const;
- virtual BOOL startQueue();
-
- // go to the next object. If no objects left, it falls out
- // silently and waits to be killed by the deleteIfDone() callback.
- BOOL nextObject();
- BOOL popNext();
+ virtual bool startQueue() = 0;
void setStartString(const std::string& s) { mStartString = s; }
@@ -96,12 +87,23 @@ protected:
LLButton* mCloseBtn;
// Object Queue
- std::vector<LLUUID> mObjectIDs;
+ struct ObjectData
+ {
+ LLUUID mObjectId;
+ std::string mObjectName;
+ };
+ typedef std::vector<ObjectData> object_data_list_t;
+
+ object_data_list_t mObjectList;
LLUUID mCurrentObjectID;
bool mDone;
std::string mStartString;
bool mMono;
+
+ typedef boost::function<bool(const LLPointer<LLViewerObject> &, LLInventoryObject*, LLEventPump &)> fnQueueAction_t;
+ static void objectScriptProcessingQueueCoro(std::string action, LLHandle<LLFloaterScriptQueue> hfloater, object_data_list_t objectList, fnQueueAction_t func);
+
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -122,8 +124,6 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue
{
friend class LLFloaterReg;
public:
- // remove any object in mScriptScripts with the matching uuid.
- void removeItemByItemID(const LLUUID& item_id);
void experienceIdsReceived( const LLSD& content );
BOOL hasExperience(const LLUUID& id)const;
@@ -132,27 +132,17 @@ protected:
LLFloaterCompileQueue(const LLSD& key);
virtual ~LLFloaterCompileQueue();
- // This is called by inventoryChanged
- virtual void handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv);
-
- static void requestAsset(struct LLScriptQueueData* datap, const LLSD& experience);
+ virtual bool startQueue();
+ static bool processScript(LLHandle<LLFloaterCompileQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump);
- static void finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId);
-
- // This is the callback for when each script arrives
- static void scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
- LLAssetType::EType type,
- void* user_data, S32 status, LLExtStat ext_status);
-
- virtual BOOL startQueue();
-protected:
- LLViewerInventoryItem::item_array_t mCurrentScripts;
+ //bool checkAssetId(const LLUUID &assetId);
+ static void handleHTTPResponse(std::string pumpName, const LLSD &expresult);
+ static void handleScriptRetrieval(LLVFS *vfs, const LLUUID& assetId, LLAssetType::EType type, void* userData, S32 status, LLExtStat extStatus);
private:
static void processExperienceIdResults(LLSD result, LLUUID parent);
-
+ //uuid_list_t mAssetIds; // list of asset IDs processed.
uuid_list_t mExperienceIds;
};
@@ -169,9 +159,9 @@ protected:
LLFloaterResetQueue(const LLSD& key);
virtual ~LLFloaterResetQueue();
- // This is called by inventoryChanged
- virtual void handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv);
+ static bool resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump);
+
+ virtual bool startQueue();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -186,10 +176,10 @@ class LLFloaterRunQueue : public LLFloaterScriptQueue
protected:
LLFloaterRunQueue(const LLSD& key);
virtual ~LLFloaterRunQueue();
-
- // This is called by inventoryChanged
- virtual void handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv);
+
+ static bool runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump);
+
+ virtual bool startQueue();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -205,9 +195,9 @@ protected:
LLFloaterNotRunQueue(const LLSD& key);
virtual ~LLFloaterNotRunQueue();
- // This is called by inventoryChanged
- virtual void handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv);
+ static bool stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump);
+
+ virtual bool startQueue();
};
#endif // LL_LLCOMPILEQUEUE_H
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 33675bd261..b716a76543 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -62,28 +62,15 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
LLFacePool(POOL_TERRAIN),
mTexturep(texturep)
{
- U32 format = GL_ALPHA8;
- U32 int_format = GL_ALPHA;
-
// Hack!
sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale");
sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
- mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga",
- FTT_LOCAL_FILE,
- TRUE, LLGLTexture::BOOST_UI,
- LLViewerTexture::FETCHED_TEXTURE,
- format, int_format,
- LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb"));
+ mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD);
//gGL.getTexUnit(0)->bind(mAlphaRampImagep.get());
mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
- m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c",
- FTT_LOCAL_FILE,
- TRUE, LLGLTexture::BOOST_UI,
- LLViewerTexture::FETCHED_TEXTURE,
- format, int_format,
- LLUUID("38b86f85-2575-52a9-a531-23108d8da837"));
+ m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD_2D);
//gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 7178042b32..cc77b407ae 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -40,12 +40,14 @@
#include "llcorehttputil.h"
#include "lleventfilter.h"
+#include "boost/make_shared.hpp"
+
namespace LLEventPolling
{
namespace Details
{
- class LLEventPollImpl
+ class LLEventPollImpl: public boost::enable_shared_from_this<LLEventPollImpl>
{
public:
LLEventPollImpl(const LLHost &sender);
@@ -113,7 +115,7 @@ namespace Details
{
std::string coroname =
LLCoros::instance().launch("LLEventPollImpl::eventPollCoro",
- boost::bind(&LLEventPollImpl::eventPollCoro, this, url));
+ boost::bind(&LLEventPollImpl::eventPollCoro, this->shared_from_this(), url));
LL_INFOS("LLEventPollImpl") << coroname << " with url '" << url << LL_ENDL;
}
}
@@ -273,8 +275,7 @@ namespace Details
LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender):
mImpl()
{
- mImpl = boost::unique_ptr<LLEventPolling::Details::LLEventPollImpl>
- (new LLEventPolling::Details::LLEventPollImpl(sender));
+ mImpl = boost::make_shared<LLEventPolling::Details::LLEventPollImpl>(sender);
mImpl->start(poll_url);
}
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index e2afd9226b..65766dbb2a 100644
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -27,12 +27,6 @@
#ifndef LL_LLEVENTPOLL_H
#define LL_LLEVENTPOLL_H
-#include "boost/move/unique_ptr.hpp"
-
-namespace boost
-{
- using ::boost::movelib::unique_ptr; // move unique_ptr into the boost namespace.
-}
class LLHost;
@@ -57,7 +51,7 @@ public:
private:
- boost::unique_ptr<LLEventPolling::Details::LLEventPollImpl> mImpl;
+ boost::shared_ptr<LLEventPolling::Details::LLEventPollImpl> mImpl;
};
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 7f1c981a3c..d4ba230feb 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -809,3 +809,62 @@ void LLFeatureManager::applyBaseMasks()
maskFeatures("safe");
}
}
+
+LLSD LLFeatureManager::getRecommendedSettingsMap()
+{
+ // Create the map and fill it with the hardware recommended settings.
+ // It's needed to create an initial Default graphics preset (MAINT-6435).
+ // The process is similar to the one LLFeatureManager::applyRecommendedSettings() does.
+
+ LLSD map(LLSD::emptyMap());
+
+ loadGPUClass();
+ U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5));
+ LL_INFOS("RenderInit") << "Getting the map of recommended settings for level " << level << LL_ENDL;
+
+ applyBaseMasks();
+ std::string features(isValidGraphicsLevel(level) ? getNameForGraphicsLevel(level) : "Low");
+
+ maskFeatures(features);
+
+ LLControlVariable* ctrl = gSavedSettings.getControl("RenderQualityPerformance"); // include the quality value for correct preset loading
+ map["RenderQualityPerformance"]["Value"] = (LLSD::Integer)level;
+ map["RenderQualityPerformance"]["Comment"] = ctrl->getComment();;
+ map["RenderQualityPerformance"]["Persist"] = 1;
+ map["RenderQualityPerformance"]["Type"] = LLControlGroup::typeEnumToString(ctrl->type());
+
+
+
+ for (feature_map_t::iterator mIt = mFeatures.begin(); mIt != mFeatures.end(); ++mIt)
+ {
+ LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first);
+ if (ctrl == NULL)
+ {
+ LL_WARNS() << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL;
+ continue;
+ }
+
+ if (ctrl->isType(TYPE_BOOLEAN))
+ {
+ map[mIt->first]["Value"] = (LLSD::Boolean)getRecommendedValue(mIt->first);
+ }
+ else if (ctrl->isType(TYPE_S32) || ctrl->isType(TYPE_U32))
+ {
+ map[mIt->first]["Value"] = (LLSD::Integer)getRecommendedValue(mIt->first);
+ }
+ else if (ctrl->isType(TYPE_F32))
+ {
+ map[mIt->first]["Value"] = (LLSD::Real)getRecommendedValue(mIt->first);
+ }
+ else
+ {
+ LL_WARNS() << "AHHH! Control variable is not a numeric type!" << LL_ENDL;
+ continue;
+ }
+ map[mIt->first]["Comment"] = ctrl->getComment();;
+ map[mIt->first]["Persist"] = 1;
+ map[mIt->first]["Type"] = LLControlGroup::typeEnumToString(ctrl->type());
+ }
+
+ return map;
+}
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index 12ea691b49..c3d87cea0b 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -157,7 +157,9 @@ public:
// load the dynamic GPU/feature table from a website
void fetchHTTPTables();
-
+
+ LLSD getRecommendedSettingsMap();
+
protected:
bool loadGPUClass();
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index 7da65a9a7c..d842106146 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -528,7 +528,8 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
LLInventoryItem* item = gInventory.getItem(*it);
if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
{
- LLClipboard::instance().addToClipboard(item->getUUID(),LLAssetType::AT_GESTURE);
+ LLWString item_name = utf8str_to_wstring(item->getName());
+ LLClipboard::instance().addToClipboard(item_name, 0, item_name.size());
}
}
}
diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp
index 1f85c5ac1b..9fd731ed56 100644
--- a/indra/newview/llfloaterimnearbychathandler.cpp
+++ b/indra/newview/llfloaterimnearbychathandler.cpp
@@ -601,12 +601,31 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
toast_msg = chat_msg.mText;
}
+ bool chat_overlaps = false;
+ if(nearby_chat->getChatHistory())
+ {
+ LLRect chat_rect = nearby_chat->getChatHistory()->calcScreenRect();
+ for (std::list<LLView*>::const_iterator child_iter = gFloaterView->getChildList()->begin();
+ child_iter != gFloaterView->getChildList()->end(); ++child_iter)
+ {
+ LLView *view = *child_iter;
+ const LLRect& rect = view->getRect();
+ if(view->isInVisibleChain() && (rect.overlaps(chat_rect)))
+ {
+ if(!nearby_chat->getChatHistory()->hasAncestor(view))
+ {
+ chat_overlaps = true;
+ }
+ break;
+ }
+ }
+ }
//Don't show nearby toast, if conversation is visible and selected
if ((nearby_chat->hasFocus()) ||
(LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()) ||
- ((im_box->getSelectedSession().isNull() &&
- ((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())
- || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost())))))
+ ((im_box->getSelectedSession().isNull() && !chat_overlaps &&
+ ((LLFloater::isVisible(im_box) && !nearby_chat->isTornOff() && !im_box->isMinimized())
+ || (LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized())))))
{
if(nearby_chat->isMessagePaneExpanded())
{
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 357b635594..2cd94c592a 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -1094,6 +1094,12 @@ void LLFloaterIMSessionTab::saveCollapsedState()
gSavedPerAccountSettings.setBOOL("NearbyChatIsNotCollapsed", isMessagePaneExpanded());
}
}
+
+LLView* LLFloaterIMSessionTab::getChatHistory()
+{
+ return mChatHistory;
+}
+
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
{
BOOL handled = FALSE;
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index e7b05a584b..1b4922fd73 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -103,6 +103,8 @@ public:
void restoreFloater();
void saveCollapsedState();
+ LLView* getChatHistory();
+
protected:
// callback for click on any items of the visual states menu
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 135bbb335e..4a5732aecf 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -42,6 +42,8 @@
#include "llfloaterperms.h"
#include "llviewercontrol.h"
#include "llviewermenufile.h" // upload_new_resource()
+#include "llstatusbar.h" // can_afford_transaction()
+#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
#include "llstring.h"
#include "lleconomy.h"
@@ -161,12 +163,15 @@ void LLFloaterNameDesc::onBtnOK( )
LLAssetStorage::LLStoreAssetCallback callback = NULL;
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).
- void *nruserdata = NULL;
- std::string display_name = LLStringUtil::null;
- LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+ if (can_afford_transaction(expected_upload_cost))
+ {
+ void *nruserdata = NULL;
+ std::string display_name = LLStringUtil::null;
+
+ LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
mFilenameAndPath,
- getChild<LLUICtrl>("name_form")->getValue().asString(),
+ getChild<LLUICtrl>("name_form")->getValue().asString(),
getChild<LLUICtrl>("description_form")->getValue().asString(), 0,
LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
LLFloaterPerms::getNextOwnerPerms("Uploads"),
@@ -174,7 +179,14 @@ void LLFloaterNameDesc::onBtnOK( )
LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost));
- upload_new_resource(uploadInfo, callback, nruserdata);
+ upload_new_resource(uploadInfo, callback, nruserdata);
+ }
+ else
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", expected_upload_cost);
+ LLNotificationsUtil::add("ErrorTextureCannotAfford", args);
+ }
closeFloater(false);
}
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 4eacd728c3..843dbbf25e 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -412,6 +412,11 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
panel->getChild<LLUICtrl>("object_bonus_spin")->setValue(LLSD(object_bonus_factor) );
panel->getChild<LLUICtrl>("access_combo")->setValue(LLSD(sim_access) );
+ LLPanelRegionGeneralInfo* panel_general = LLFloaterRegionInfo::getPanelGeneral();
+ if (panel)
+ {
+ panel_general->setObjBonusFactor(object_bonus_factor);
+ }
// detect teen grid for maturity
@@ -465,6 +470,16 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant()
}
// static
+LLPanelRegionGeneralInfo* LLFloaterRegionInfo::getPanelGeneral()
+{
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
+ if (!floater) return NULL;
+ LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
+ LLPanelRegionGeneralInfo* panel = (LLPanelRegionGeneralInfo*)tab->getChild<LLPanel>("General");
+ return panel;
+}
+
+// static
LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain()
{
LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
@@ -717,7 +732,42 @@ BOOL LLPanelRegionGeneralInfo::postBuild()
childSetAction("im_btn", onClickMessage, this);
// childSetAction("manage_telehub_btn", onClickManageTelehub, this);
- return LLPanelRegionInfo::postBuild();
+ LLUICtrl* apply_btn = findChild<LLUICtrl>("apply_btn");
+ if (apply_btn)
+ {
+ apply_btn->setCommitCallback(boost::bind(&LLPanelRegionGeneralInfo::onBtnSet, this));
+ }
+
+ refresh();
+ return TRUE;
+}
+
+void LLPanelRegionGeneralInfo::onBtnSet()
+{
+ if(mObjBonusFactor == getChild<LLUICtrl>("object_bonus_spin")->getValue().asReal())
+ {
+ if (sendUpdate())
+ {
+ disableButton("apply_btn");
+ }
+ }
+ else
+ {
+ LLNotificationsUtil::add("ChangeObjectBonusFactor", LLSD(), LLSD(), boost::bind(&LLPanelRegionGeneralInfo::onChangeObjectBonus, this, _1, _2));
+ }
+}
+
+bool LLPanelRegionGeneralInfo::onChangeObjectBonus(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ if (sendUpdate())
+ {
+ disableButton("apply_btn");
+ }
+ }
+ return false;
}
void LLPanelRegionGeneralInfo::onClickKick()
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 46f2b42137..dbb0ad05e9 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -95,6 +95,7 @@ public:
static LLPanelEstateCovenant* getPanelCovenant();
static LLPanelRegionTerrainInfo* getPanelRegionTerrain();
static LLPanelRegionExperiences* getPanelExperiences();
+ static LLPanelRegionGeneralInfo* getPanelGeneral();
// from LLPanel
virtual void refresh();
@@ -183,6 +184,9 @@ public:
// LLPanel
virtual BOOL postBuild();
+ void onBtnSet();
+ void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;}
+
protected:
virtual BOOL sendUpdate();
void onClickKick();
@@ -191,6 +195,9 @@ protected:
bool onKickAllCommit(const LLSD& notification, const LLSD& response);
static void onClickMessage(void* userdata);
bool onMessageCommit(const LLSD& notification, const LLSD& response);
+ bool onChangeObjectBonus(const LLSD& notification, const LLSD& response);
+
+ F32 mObjBonusFactor;
};
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index afec981d56..b906671c7f 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1418,6 +1418,20 @@ void LLFloaterSnapshot::postPanelSwitch()
}
// static
+void LLFloaterSnapshot::inventorySaveFailed()
+{
+ LLFloaterSnapshot* instance = findInstance();
+ if (!instance)
+ {
+ llassert(instance != NULL);
+ return;
+ }
+
+ instance->impl.updateControls(instance);
+ instance->impl.setStatus(Impl::STATUS_FINISHED, false, "inventory");
+}
+
+// static
LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData()
{
// FIXME: May not work for textures.
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 0bb9474bb5..eb3a94999b 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -61,6 +61,7 @@ public:
static BOOL saveLocal();
static void postSave();
static void postPanelSwitch();
+ static void inventorySaveFailed();
static LLPointer<LLImageFormatted> getImageData();
static const LLVector3d& getPosTakenGlobal();
static void setAgentEmail(const std::string& email);
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 024e315632..dece3fc1ea 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -55,7 +55,8 @@ LLFloaterWebContent::_Params::_Params()
preferred_media_size("preferred_media_size"),
trusted_content("trusted_content", false),
show_page_title("show_page_title", true),
- clean_browser("clean_browser", false)
+ clean_browser("clean_browser", false),
+ dev_mode("dev_mode", false)
{}
LLFloaterWebContent::LLFloaterWebContent( const Params& params )
@@ -74,14 +75,16 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )
mShowPageTitle(params.show_page_title),
mAllowNavigation(true),
mCurrentURL(""),
- mDisplayURL("")
+ mDisplayURL(""),
+ mDevelopMode(params.dev_mode) // if called from "Develop" Menu, set a flag and change things to be more useful for devs
{
mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
- mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
+ mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind(&LLFloaterWebContent::onPopExternal, this));
+ mCommitCallbackRegistrar.add( "WebContent.TestURL", boost::bind(&LLFloaterWebContent::onTestURL, this, _2));
}
BOOL LLFloaterWebContent::postBuild()
@@ -195,8 +198,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
width + getRect().getWidth() - browser_rect.getWidth(),
height + getRect().getHeight() - browser_rect.getHeight());
- LL_DEBUGS() << "geometry change: " << geom << LL_ENDL;
-
LLRect new_rect;
getParent()->screenRectToLocal(geom, &new_rect);
setShape(new_rect);
@@ -205,8 +206,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
// static
void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
{
- LL_DEBUGS() << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << LL_ENDL;
-
if (!p.id.isProvided())
{
p.id = LLUUID::generateNewID().asString();
@@ -224,12 +223,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
// and close the least recently opened one if this will put us over the limit.
LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class);
- LL_DEBUGS() << "total instance count is " << instances.size() << LL_ENDL;
-
- for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
- {
- LL_DEBUGS() << " " << (*iter)->getKey()["target"] << LL_ENDL;
- }
if(instances.size() >= (size_t)browser_window_limit)
{
@@ -241,16 +234,19 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
void LLFloaterWebContent::open_media(const Params& p)
{
- // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
LLViewerMedia::proxyWindowOpened(p.target(), p.id());
- mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML);
+ mWebBrowser->setHomePageUrl(p.url);
mWebBrowser->setTarget(p.target);
- mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser);
+ mWebBrowser->navigateTo(p.url);
set_current_url(p.url);
getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);
getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome);
+
+ // turn additional debug controls on but only for Develop mode (Develop menu open)
+ getChild<LLLayoutPanel>("debug_controls")->setVisible(mDevelopMode);
+
bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;
mAllowNavigation = p.allow_back_forward_navigation;
getChildView("address")->setEnabled(address_entry_enabled);
@@ -499,7 +495,7 @@ void LLFloaterWebContent::onEnterAddress()
LLStringUtil::trim(url);
if ( url.length() > 0 )
{
- mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
+ mWebBrowser->navigateTo(url);
};
}
@@ -508,9 +504,18 @@ void LLFloaterWebContent::onPopExternal()
// make sure there is at least something there.
// (perhaps this test should be for minimum length of a URL)
std::string url = mAddressCombo->getValue().asString();
- LLStringUtil::trim(url);
- if ( url.length() > 0 )
+ LLStringUtil::trim(url);
+ if (url.length() > 0)
+ {
+ LLWeb::loadURLExternal(url);
+ };
+}
+
+void LLFloaterWebContent::onTestURL(std::string url)
+{
+ LLStringUtil::trim(url);
+ if (url.length() > 0)
{
- LLWeb::loadURLExternal( url );
+ mWebBrowser->navigateTo(url);
};
}
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index 4291fd9f2c..0bf93504c2 100644
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -58,7 +58,8 @@ public:
allow_back_forward_navigation,
trusted_content,
show_page_title,
- clean_browser;
+ clean_browser,
+ dev_mode;
Optional<LLRect> preferred_media_size;
_Params();
@@ -92,6 +93,7 @@ protected:
void onClickStop();
void onEnterAddress();
void onPopExternal();
+ void onTestURL(std::string url);
static void preCreate(Params& p);
void open_media(const Params& );
@@ -113,6 +115,7 @@ protected:
std::string mUUID;
bool mShowPageTitle;
bool mAllowNavigation;
+ bool mDevelopMode;
};
#endif // LL_LLFLOATERWEBCONTENT_H
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index ece3e10faa..c67feb8158 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -963,10 +963,10 @@ F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination,
}
-void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
+void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui, BOOL dest_reached)
{
LLCtrlListInterface *list = mListSearchResults;
- if (list)
+ if (list && (!dest_reached || (list->getItemCount() == 1)))
{
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 7ce8dae9a9..c5801c8819 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -94,7 +94,7 @@ public:
// A z_attenuation of 0.0f collapses the distance into the X-Y plane
F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const;
- void clearLocationSelection(BOOL clear_ui = FALSE);
+ void clearLocationSelection(BOOL clear_ui = FALSE, BOOL dest_reached = FALSE);
void clearAvatarSelection(BOOL clear_ui = FALSE);
void clearLandmarkSelection(BOOL clear_ui = FALSE);
diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp
index a12ec390af..b64df2bd47 100644
--- a/indra/newview/llinspectremoteobject.cpp
+++ b/indra/newview/llinspectremoteobject.cpp
@@ -181,7 +181,7 @@ void LLInspectRemoteObject::update()
getChild<LLUICtrl>("map_btn")->setEnabled(! mSLurl.empty());
// disable the Block button if we don't have the object ID (will this ever happen?)
- getChild<LLUICtrl>("block_btn")->setEnabled(! mObjectID.isNull());
+ getChild<LLUICtrl>("block_btn")->setEnabled(!mObjectID.isNull() && !LLMuteList::getInstance()->isMuted(mObjectID));
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index e3cb4d57ef..d8f019374e 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -287,7 +287,11 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc
LL_INFOS("SLM") << "Unlist and clear version folder as the version folder is not at the right place anymore!!" << LL_ENDL;
LLMarketplaceData::instance().setVersionFolder(listing_uuid, LLUUID::null,1);
}
- else if (version_folder_uuid.notNull() && LLMarketplaceData::instance().getActivationState(version_folder_uuid) && (count_descendants_items(version_folder_uuid) == 0) && !LLMarketplaceData::instance().isUpdating(version_folder_uuid,version_depth))
+ else if (version_folder_uuid.notNull()
+ && gInventory.isCategoryComplete(version_folder_uuid)
+ && LLMarketplaceData::instance().getActivationState(version_folder_uuid)
+ && (count_descendants_items(version_folder_uuid) == 0)
+ && !LLMarketplaceData::instance().isUpdating(version_folder_uuid,version_depth))
{
LL_INFOS("SLM") << "Unlist as the version folder is empty of any item!!" << LL_ENDL;
LLNotificationsUtil::add("AlertMerchantVersionFolderEmpty");
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 8d21fda8f9..53b2ca2b74 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -64,6 +64,9 @@
#include "llurllineeditorctrl.h"
#include "llagentui.h"
+#include "llmenuoptionpathfindingrebakenavmesh.h"
+#include "llpathfindingmanager.h"
+
//============================================================================
/*
* "ADD LANDMARK" BUTTON UPDATING LOGIC
@@ -1194,6 +1197,18 @@ bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata)
return false;
}
+void LLLocationInputCtrl::callbackRebakeRegion(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0) // OK
+ {
+ if (LLPathfindingManager::getInstance() != NULL)
+ {
+ LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh();
+ }
+ }
+}
+
void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
{
switch (icon)
@@ -1211,6 +1226,16 @@ void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
LLNotificationsUtil::add("NoBuild");
break;
case PATHFINDING_DIRTY_ICON:
+ if (LLPathfindingManager::getInstance() != NULL)
+ {
+ LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance();
+ if (rebakeInstance && rebakeInstance->canRebakeRegion() && (rebakeInstance->getMode() == LLMenuOptionPathfindingRebakeNavmesh::kRebakeNavMesh_Available))
+ {
+ LLNotificationsUtil::add("PathfindingDirtyRebake", LLSD(), LLSD(),
+ boost::bind(&LLLocationInputCtrl::callbackRebakeRegion, this, _1, _2));
+ break;
+ }
+ }
LLNotificationsUtil::add("PathfindingDirty");
break;
case PATHFINDING_DISABLED_ICON:
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index cd6fd24077..da71bab6c1 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -166,6 +166,7 @@ private:
// callbacks
bool onLocationContextMenuItemEnabled(const LLSD& userdata);
void onLocationContextMenuItemClicked(const LLSD& userdata);
+ void callbackRebakeRegion(const LLSD& notification, const LLSD& response);
void onParcelIconClick(EParcelIcon icon);
void createNavMeshStatusListenerForCurrentRegion();
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 4116e38f11..639641d1c2 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -904,7 +904,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
std::string stuff = matches[IDX_STUFF];
boost::match_results<std::string::const_iterator> name_and_text;
if (!boost::regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false;
-
+
bool has_name = name_and_text[IDX_NAME].matched;
std::string name = name_and_text[IDX_NAME];
@@ -956,7 +956,6 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
im[LL_IM_FROM] = name;
}
-
im[LL_IM_TEXT] = name_and_text[IDX_TEXT];
return true; //parsed name and message text, maybe have a timestamp too
}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 0aaed3e286..54f8fb93d0 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -3935,7 +3935,7 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
{
LLMutexLock lock(mHeaderMutex);
mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
- if (iter != mMeshHeader.end())
+ if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0)
{
return iter->second;
}
@@ -3956,10 +3956,11 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
{
- if (mThread)
+ if (mThread && mesh_id.notNull())
{
+ LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
- if (iter != mThread->mMeshHeader.end())
+ if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
{
LLSD& header = iter->second;
@@ -4031,9 +4032,30 @@ void LLMeshRepository::uploadError(LLSD& args)
mUploadErrorQ.push(args);
}
+F32 LLMeshRepository::getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
+{
+ if (mThread && mesh_id.notNull())
+ {
+ LLMutexLock lock(mThread->mHeaderMutex);
+ LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
+ if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+ {
+ return getStreamingCost(iter->second, radius, bytes, bytes_visible, lod, unscaled_value);
+ }
+ }
+ return 0.f;
+}
+
//static
F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
{
+ if (header.has("404")
+ || !header.has("lowest_lod")
+ || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION))
+ {
+ return 0.f;
+ }
+
F32 max_distance = 512.f;
F32 dlowest = llmin(radius/0.03f, max_distance);
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index d35c44397b..a762042597 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -475,6 +475,7 @@ public:
static LLDeadmanTimer sQuiescentTimer; // Time-to-complete-mesh-downloads after significant events
+ F32 getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
LLMeshRepository();
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 4229419fce..c779ba5cdd 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -150,6 +150,7 @@ BOOL LLPanelMainInventory::postBuild()
LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
if (recent_items_panel)
{
+ // assign default values until we will be sure that we have setting to restore
recent_items_panel->setSinceLogoff(TRUE);
recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);
recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
@@ -181,6 +182,7 @@ BOOL LLPanelMainInventory::postBuild()
LLParamSDParser parser;
parser.readSD(recent_items, p);
recent_items_panel->getFilter().fromParams(p);
+ recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER));
}
}
@@ -372,7 +374,14 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
}
getActivePanel()->setSortOrder(sort_order_mask);
- gSavedSettings.setU32("InventorySortOrder", sort_order_mask);
+ if ("Recent Items" == getActivePanel()->getName())
+ {
+ gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask);
+ }
+ else
+ {
+ gSavedSettings.setU32("InventorySortOrder", sort_order_mask);
+ }
}
// static
@@ -1143,6 +1152,15 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
}
}
+void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
+{
+ if(!new_visibility)
+ {
+ mMenuAdd->setVisible(FALSE);
+ getActivePanel()->getRootFolder()->finishRenamingItem();
+ }
+}
+
bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)
{
LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 21f0ca0cae..290e2e5f47 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -72,6 +72,7 @@ public:
std::string& tooltip_msg);
/*virtual*/ void changed(U32);
/*virtual*/ void draw();
+ /*virtual*/ void onVisibilityChange ( BOOL new_visibility );
LLInventoryPanel* getPanel() { return mActivePanel; }
LLInventoryPanel* getActivePanel() { return mActivePanel; }
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 73b928f014..bc177abc57 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -611,9 +611,11 @@ BOOL LLPanelPeople::postBuild()
mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
mOnlineFriendList->setShowIcons("FriendsListShowIcons");
mOnlineFriendList->showPermissions("FriendsListShowPermissions");
+ mOnlineFriendList->setShowCompleteName(!gSavedSettings.getBOOL("FriendsListHideUsernames"));
mAllFriendList->setNoItemsCommentText(getString("no_friends"));
mAllFriendList->setShowIcons("FriendsListShowIcons");
mAllFriendList->showPermissions("FriendsListShowPermissions");
+ mAllFriendList->setShowCompleteName(!gSavedSettings.getBOOL("FriendsListHideUsernames"));
LLPanel* nearby_tab = getChild<LLPanel>(NEARBY_TAB_NAME);
nearby_tab->setVisibleCallback(boost::bind(&Updater::setActive, mNearbyListUpdater, _2));
@@ -622,6 +624,7 @@ BOOL LLPanelPeople::postBuild()
mNearbyList->setNoItemsMsg(getString("no_one_near"));
mNearbyList->setNoFilteredItemsMsg(getString("no_one_filtered_near"));
mNearbyList->setShowIcons("NearbyListShowIcons");
+ mNearbyList->setShowCompleteName(!gSavedSettings.getBOOL("NearbyListHideUsernames"));
mMiniMap = (LLNetMap*)getChildView("Net Map",true);
mMiniMap->setToolTipMsg(gSavedSettings.getBOOL("DoubleClickTeleport") ?
getString("AltMiniMapToolTipMsg") : getString("MiniMapToolTipMsg"));
@@ -1342,6 +1345,16 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
mAllFriendList->showPermissions(show_permissions);
mOnlineFriendList->showPermissions(show_permissions);
}
+ else if (chosen_item == "view_usernames")
+ {
+ bool hide_usernames = !gSavedSettings.getBOOL("FriendsListHideUsernames");
+ gSavedSettings.setBOOL("FriendsListHideUsernames", hide_usernames);
+
+ mAllFriendList->setShowCompleteName(!hide_usernames);
+ mAllFriendList->handleDisplayNamesOptionChanged();
+ mOnlineFriendList->setShowCompleteName(!hide_usernames);
+ mOnlineFriendList->handleDisplayNamesOptionChanged();
+ }
}
void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata)
@@ -1374,6 +1387,14 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
{
setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);
}
+ else if (chosen_item == "view_usernames")
+ {
+ bool hide_usernames = !gSavedSettings.getBOOL("NearbyListHideUsernames");
+ gSavedSettings.setBOOL("NearbyListHideUsernames", hide_usernames);
+
+ mNearbyList->setShowCompleteName(!hide_usernames);
+ mNearbyList->handleDisplayNamesOptionChanged();
+ }
}
bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata)
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index a5f59dbf4a..65769ff526 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -38,9 +38,14 @@
#include "llavataractions.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "lllogchat.h"
+#include "llparcel.h"
#include "llviewermenu.h" // for gMenuHolder
#include "llconversationmodel.h"
#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "roles_constants.h"
namespace LLPanelPeopleMenus
{
@@ -77,9 +82,13 @@ LLContextMenu* PeopleContextMenu::createMenu()
registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id));
registrar.add("Avatar.TeleportRequest", boost::bind(&PeopleContextMenu::requestTeleport, this));
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
+ registrar.add("Avatar.Freeze", boost::bind(&LLAvatarActions::freezeAvatar, id));
+ registrar.add("Avatar.Eject", boost::bind(&PeopleContextMenu::eject, this));
+
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2));
+ enable_registrar.add("Avatar.EnableFreezeEject", boost::bind(&PeopleContextMenu::enableFreezeEject, this, _2));
// create the context menu from the XUI
menu = createFromFile("menu_people_nearby.xml");
@@ -258,6 +267,50 @@ bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
return false;
}
+bool PeopleContextMenu::enableFreezeEject(const LLSD& userdata)
+{
+ if((gAgent.getID() == mUUIDs.front()) || (mUUIDs.size() != 1))
+ {
+ return false;
+ }
+
+ const LLUUID& id = mUUIDs.front();
+
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (id.notNull())
+ {
+ LLViewerObject* object = gObjectList.findObject(id);
+ if (object)
+ {
+ if( !object->isAvatar() )
+ {
+ object = NULL;
+ }
+ avatar = (LLVOAvatar*) object;
+ }
+ }
+ if (!avatar) return false;
+
+ // Gods can always freeze
+ if (gAgent.isGodlike()) return true;
+
+ // Estate owners / managers can freeze
+ // Parcel owners can also freeze
+ const LLVector3& pos = avatar->getPositionRegion();
+ const LLVector3d& pos_global = avatar->getPositionGlobal();
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
+ LLViewerRegion* region = avatar->getRegion();
+ if (!region) return false;
+
+ bool new_value = region->isOwnedSelf(pos);
+ if (!new_value || region->isOwnedGroup(pos))
+ {
+ new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
+ }
+ return new_value;
+}
+
void PeopleContextMenu::requestTeleport()
{
// boost::bind cannot recognize overloaded method LLAvatarActions::teleportRequest(),
@@ -272,6 +325,39 @@ void PeopleContextMenu::offerTeleport()
LLAvatarActions::offerTeleport(mUUIDs);
}
+void PeopleContextMenu::eject()
+{
+ if((gAgent.getID() == mUUIDs.front()) || (mUUIDs.size() != 1))
+ {
+ return;
+ }
+
+ const LLUUID& id = mUUIDs.front();
+
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (id.notNull())
+ {
+ LLViewerObject* object = gObjectList.findObject(id);
+ if (object)
+ {
+ if( !object->isAvatar() )
+ {
+ object = NULL;
+ }
+ avatar = (LLVOAvatar*) object;
+ }
+ }
+ if (!avatar) return;
+ LLSD payload;
+ payload["avatar_id"] = avatar->getID();
+ std::string fullname = avatar->getFullname();
+
+ const LLVector3d& pos = avatar->getPositionGlobal();
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
+ LLAvatarActions::ejectAvatar(id ,LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED));
+}
+
void PeopleContextMenu::startConference()
{
uuid_vec_t uuids;
@@ -320,6 +406,8 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("block_unblock"));
+ items.push_back(std::string("freeze"));
+ items.push_back(std::string("eject"));
}
hide_context_entries(menu, items, disabled_items);
diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h
index 9767bab89f..5ed20e0064 100644
--- a/indra/newview/llpanelpeoplemenus.h
+++ b/indra/newview/llpanelpeoplemenus.h
@@ -46,7 +46,9 @@ protected:
private:
bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata);
+ bool enableFreezeEject(const LLSD& userdata);
void offerTeleport();
+ void eject();
void startConference();
void requestTeleport();
};
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 763657ebad..0bcd8a9e63 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -95,7 +95,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mVolumeSliderVisible(0),
mWindowShade(NULL),
mHideImmediately(false),
- mSecureURL(false)
+ mSecureURL(false),
+ mMediaPlaySliderCtrlMouseDownValue(0.0)
{
mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
@@ -109,7 +110,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
- mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MouseDown", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MouseUp", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this));
@@ -1246,26 +1248,38 @@ void LLPanelPrimMediaControls::setCurrentURL()
#endif // USE_COMBO_BOX_FOR_MEDIA_URL
}
-void LLPanelPrimMediaControls::onCommitSlider()
+
+void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown()
{
- focusOnTarget();
+ mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal();
- LLViewerMediaImpl* media_impl = getTargetMediaImpl();
- if (media_impl)
+ mUpdateSlider = false;
+}
+
+void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp()
+{
+ F64 cur_value = mMediaPlaySliderCtrl->getValue().asReal();
+
+ if (mMediaPlaySliderCtrlMouseDownValue != cur_value)
{
- // get slider value
- F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal();
- if(slider_value <= 0.0)
- {
- media_impl->stop();
- }
- else
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
{
- media_impl->seek(slider_value*mMovieDuration);
- //mUpdateSlider= false;
+ if (cur_value <= 0.0)
+ {
+ media_impl->stop();
+ }
+ else
+ {
+ media_impl->seek(cur_value * mMovieDuration);
+ }
}
+
+ mUpdateSlider = true;
}
-}
+}
void LLPanelPrimMediaControls::onCommitVolumeUp()
{
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 6d2eb3430e..21d5236074 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -107,8 +107,10 @@ private:
void updateZoom();
void setCurrentURL();
- void onCommitSlider();
-
+
+ void onMediaPlaySliderCtrlMouseDown();
+ void onMediaPlaySliderCtrlMouseUp();
+
void onCommitVolumeUp();
void onCommitVolumeDown();
void onCommitVolumeSlider();
@@ -219,6 +221,8 @@ private:
S32 mVolumeSliderVisible;
LLNotificationPtr mActiveNotification;
+
+ F64 mMediaPlaySliderCtrlMouseDownValue;
};
#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index e795e7eedb..184238c40c 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -176,6 +176,16 @@ public:
return true;
}
+ if (verb == "unblock")
+ {
+ if (params.size() > 2)
+ {
+ const std::string object_name = params[2].asString();
+ LLMute mute(avatar_id, object_name, LLMute::OBJECT);
+ LLMuteList::getInstance()->remove(mute);
+ }
+ return true;
+ }
return false;
}
};
diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index c55e230b5e..a2d1752c6a 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -34,6 +34,8 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
#include "llviewercontrol.h" // gSavedSettings
+#include "llstatusbar.h" // can_afford_transaction()
+#include "llnotificationsutil.h"
/**
* The panel provides UI for saving snapshot as an inventory texture.
@@ -102,6 +104,17 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
void LLPanelSnapshotInventory::onSend()
{
- LLFloaterSnapshot::saveTexture();
- LLFloaterSnapshot::postSave();
+ S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ if (can_afford_transaction(expected_upload_cost))
+ {
+ LLFloaterSnapshot::saveTexture();
+ LLFloaterSnapshot::postSave();
+ }
+ else
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", expected_upload_cost);
+ LLNotificationsUtil::add("ErrorPhotoCannotAfford", args);
+ LLFloaterSnapshot::inventorySaveFailed();
+ }
}
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index d86a8b4480..d0353259a5 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -94,6 +94,7 @@ protected:
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("Wearing.Edit", boost::bind(&edit_outfit));
+ registrar.add("Wearing.ShowOriginal", boost::bind(show_item_original, mUUIDs.front()));
registrar.add("Wearing.TakeOff",
boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
registrar.add("Wearing.Detach",
@@ -144,6 +145,7 @@ protected:
menu->setItemVisible("take_off", allow_take_off);
menu->setItemVisible("detach", allow_detach);
menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach);
+ menu->setItemVisible("show_original", mUUIDs.size() == 1);
}
};
diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp
index d95546f11d..9957039f72 100644
--- a/indra/newview/llpresetsmanager.cpp
+++ b/indra/newview/llpresetsmanager.cpp
@@ -38,6 +38,7 @@
#include "llviewercontrol.h"
#include "llfloaterpreference.h"
#include "llfloaterreg.h"
+#include "llfeaturemanager.h"
LLPresetsManager::LLPresetsManager()
{
@@ -60,7 +61,7 @@ void LLPresetsManager::createMissingDefault()
LL_INFOS() << "No default preset found -- creating one at " << default_file << LL_ENDL;
// Write current graphic settings as the default
- savePreset(PRESETS_GRAPHIC, PRESETS_DEFAULT);
+ savePreset(PRESETS_GRAPHIC, PRESETS_DEFAULT, true);
}
else
{
@@ -134,7 +135,7 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam
presets = mPresetNames;
}
-bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string name)
+bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string name, bool createDefault)
{
if (LLTrans::getString(PRESETS_DEFAULT) == name)
{
@@ -146,11 +147,10 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n
if(PRESETS_GRAPHIC == subdirectory)
{
- gSavedSettings.setString("PresetGraphicActive", name);
-
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
- if (instance)
+ if (instance && !createDefault)
{
+ gSavedSettings.setString("PresetGraphicActive", name);
instance->getControlNames(name_list);
LL_DEBUGS() << "saving preset '" << name << "'; " << name_list.size() << " names" << LL_ENDL;
name_list.push_back("PresetGraphicActive");
@@ -170,23 +170,36 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n
LL_ERRS() << "Invalid presets directory '" << subdirectory << "'" << LL_ENDL;
}
- if (name_list.size() > 1) // if the active preset name is the only thing in the list, don't save the list
+ if (name_list.size() > 1 // if the active preset name is the only thing in the list, don't save the list
+ || (createDefault && name == PRESETS_DEFAULT && subdirectory == PRESETS_GRAPHIC)) // or create a default graphics preset from hw recommended settings
{
// make an empty llsd
LLSD paramsData(LLSD::emptyMap());
- for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it)
+ if (createDefault)
+ {
+ paramsData = LLFeatureManager::getInstance()->getRecommendedSettingsMap();
+ if (gSavedSettings.getU32("RenderAvatarMaxComplexity") == 0)
+ {
+ // use the recommended setting as an initial one (MAINT-6435)
+ gSavedSettings.setU32("RenderAvatarMaxComplexity", paramsData["RenderAvatarMaxComplexity"]["Value"].asInteger());
+ }
+ }
+ else
{
- std::string ctrl_name = *it;
- LLControlVariable* ctrl = gSavedSettings.getControl(ctrl_name).get();
- std::string comment = ctrl->getComment();
- std::string type = LLControlGroup::typeEnumToString(ctrl->type());
- LLSD value = ctrl->getValue();
-
- paramsData[ctrl_name]["Comment"] = comment;
- paramsData[ctrl_name]["Persist"] = 1;
- paramsData[ctrl_name]["Type"] = type;
- paramsData[ctrl_name]["Value"] = value;
+ for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it)
+ {
+ std::string ctrl_name = *it;
+ LLControlVariable* ctrl = gSavedSettings.getControl(ctrl_name).get();
+ std::string comment = ctrl->getComment();
+ std::string type = LLControlGroup::typeEnumToString(ctrl->type());
+ LLSD value = ctrl->getValue();
+
+ paramsData[ctrl_name]["Comment"] = comment;
+ paramsData[ctrl_name]["Persist"] = 1;
+ paramsData[ctrl_name]["Type"] = type;
+ paramsData[ctrl_name]["Value"] = value;
+ }
}
std::string pathName(getPresetsDir(subdirectory) + gDirUtilp->getDirDelimiter() + LLURI::escape(name) + ".xml");
@@ -203,10 +216,12 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n
LL_DEBUGS() << "saved preset '" << name << "'; " << paramsData.size() << " parameters" << LL_ENDL;
- gSavedSettings.setString("PresetGraphicActive", name);
-
- // signal interested parties
- triggerChangeSignal();
+ if (!createDefault)
+ {
+ gSavedSettings.setString("PresetGraphicActive", name);
+ // signal interested parties
+ triggerChangeSignal();
+ }
}
else
{
diff --git a/indra/newview/llpresetsmanager.h b/indra/newview/llpresetsmanager.h
index ac4f0c010c..21f9885f27 100644
--- a/indra/newview/llpresetsmanager.h
+++ b/indra/newview/llpresetsmanager.h
@@ -56,7 +56,7 @@ public:
static std::string getPresetsDir(const std::string& subdirectory);
void setPresetNamesInComboBox(const std::string& subdirectory, LLComboBox* combo, EDefaultOptions default_option);
void loadPresetNamesFromDir(const std::string& dir, preset_name_list_t& presets, EDefaultOptions default_option);
- bool savePreset(const std::string& subdirectory, std::string name);
+ bool savePreset(const std::string& subdirectory, std::string name, bool createDefault = false);
void loadPreset(const std::string& subdirectory, std::string name);
bool deletePreset(const std::string& subdirectory, std::string name);
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 20c43bc432..ba9845ef04 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -94,7 +94,8 @@ BOOL LLPreviewNotecard::postBuild()
if (item)
{
getChild<LLUICtrl>("desc")->setValue(item->getDescription());
- getChildView("Delete")->setEnabled(true);
+ BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID());
+ getChildView("Delete")->setEnabled(!source_library);
}
getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
@@ -219,6 +220,7 @@ void LLPreviewNotecard::loadAsset()
BOOL is_owner = gAgent.allowOperation(PERM_OWNER, perm, GP_OBJECT_MANIPULATE);
BOOL allow_copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE);
BOOL allow_modify = canModify(mObjectUUID, item);
+ BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID());
if (allow_copy || gAgent.isGodlike())
{
@@ -288,7 +290,7 @@ void LLPreviewNotecard::loadAsset()
getChildView("lock")->setVisible( TRUE);
}
- if(allow_modify || is_owner)
+ if((allow_modify || is_owner) && !source_library)
{
getChildView("Delete")->setEnabled(TRUE);
}
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 2a2c51be40..645a77e42a 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -38,6 +38,7 @@
#include "llimagetga.h"
#include "llimagepng.h"
#include "llinventory.h"
+#include "llinventorymodel.h"
#include "llnotificationsutil.h"
#include "llresmgr.h"
#include "lltrans.h"
@@ -120,18 +121,22 @@ BOOL LLPreviewTexture::postBuild()
childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this);
getChildView("save_tex_btn")->setVisible( true);
getChildView("save_tex_btn")->setEnabled(canSaveAs());
-
- if (!mCopyToInv)
- {
- const LLInventoryItem* item = getItem();
-
- if (item)
- {
- childSetCommitCallback("desc", LLPreview::onText, this);
- getChild<LLUICtrl>("desc")->setValue(item->getDescription());
- getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
- }
- }
+
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ if (!mCopyToInv)
+ {
+ childSetCommitCallback("desc", LLPreview::onText, this);
+ getChild<LLUICtrl>("desc")->setValue(item->getDescription());
+ getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
+ }
+ BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID());
+ if (source_library)
+ {
+ getChildView("Discard")->setEnabled(false);
+ }
+ }
// Fill in ratios list with common aspect ratio values
mRatiosList.clear();
@@ -526,6 +531,15 @@ void LLPreviewTexture::loadAsset()
// check that we can copy inworld items into inventory
getChildView("Keep")->setEnabled(mIsCopyable);
}
+ else
+ {
+ // check that we can remove item
+ BOOL source_library = gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID());
+ if (source_library)
+ {
+ getChildView("Discard")->setEnabled(false);
+ }
+ }
}
LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index 4f9f83b6f2..72d7cf1e45 100644
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -29,6 +29,8 @@
#include "llviewerprecompiledheaders.h"
#include "llsecapi.h"
#include "llsechandler_basic.h"
+#include "llexception.h"
+#include "stringize.h"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <map>
@@ -64,12 +66,12 @@ void initializeSecHandler()
}
catch (LLProtectedDataException e)
{
- exception_msg = e.getMessage();
+ exception_msg = e.what();
}
}
if (!exception_msg.empty()) // an exception was thrown.
{
- throw LLProtectedDataException(exception_msg.c_str());
+ LLTHROW(LLProtectedDataException(exception_msg));
}
}
@@ -101,6 +103,7 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred)
LLSD LLCredential::getLoginParams()
{
LLSD result = LLSD::emptyMap();
+ std::string username;
try
{
if (mIdentifier["type"].asString() == "agent")
@@ -109,17 +112,19 @@ LLSD LLCredential::getLoginParams()
result["passwd"] = "$1$" + mAuthenticator["secret"].asString();
result["first"] = mIdentifier["first_name"];
result["last"] = mIdentifier["last_name"];
-
+ username = result["first"].asString() + " " + result["last"].asString();
}
else if (mIdentifier["type"].asString() == "account")
{
result["username"] = mIdentifier["account_name"];
result["passwd"] = mAuthenticator["secret"];
-
+ username = result["username"].asString();
}
}
catch (...)
{
+ // nat 2016-08-18: not clear what exceptions the above COULD throw?!
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("for '" << username << "'"));
// we could have corrupt data, so simply return a null login param if so
LL_WARNS("AppInit") << "Invalid credential" << LL_ENDL;
}
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index 6fe3ee31cf..6af5a28fa5 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -32,6 +32,7 @@
#include <openssl/x509.h>
#include <ostream>
#include "llpointer.h"
+#include "llexception.h"
#ifdef LL_WINDOWS
#pragma warning(disable:4250)
@@ -116,17 +117,13 @@
-class LLProtectedDataException
+struct LLProtectedDataException: public LLException
{
-public:
- LLProtectedDataException(const char *msg)
+ LLProtectedDataException(const std::string& msg):
+ LLException(msg)
{
- LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL;
- mMsg = (std::string)msg;
+ LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL;
}
- std::string getMessage() { return mMsg; }
-protected:
- std::string mMsg;
};
// class LLCertificate
@@ -334,22 +331,21 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
// All error handling is via exceptions.
-class LLCertException
+class LLCertException: public LLException
{
public:
- LLCertException(LLPointer<LLCertificate> cert, const char* msg)
+ LLCertException(LLPointer<LLCertificate> cert, const std::string& msg):
+ LLException(msg)
{
mCert = cert;
- LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL;
- mMsg = (std::string)msg;
+ LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
}
- LLPointer<LLCertificate> getCert() { return mCert; }
- std::string getMessage() { return mMsg; }
+ virtual ~LLCertException() throw() {}
+ LLPointer<LLCertificate> getCert() const { return mCert; }
protected:
LLPointer<LLCertificate> mCert;
- std::string mMsg;
};
class LLInvalidCertificate : public LLCertException
@@ -358,6 +354,7 @@ public:
LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")
{
}
+ virtual ~LLInvalidCertificate() throw() {}
protected:
};
@@ -367,6 +364,7 @@ public:
LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")
{
}
+ virtual ~LLCertValidationTrustException() throw() {}
protected:
};
@@ -378,7 +376,7 @@ public:
{
mHostname = hostname;
}
-
+ virtual ~LLCertValidationHostnameException() throw() {}
std::string getHostname() { return mHostname; }
protected:
std::string mHostname;
@@ -392,6 +390,7 @@ public:
{
mTime = current_time;
}
+ virtual ~LLCertValidationExpirationException() throw() {}
LLDate GetTime() { return mTime; }
protected:
LLDate mTime;
@@ -403,6 +402,7 @@ public:
LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")
{
}
+ virtual ~LLCertKeyUsageValidationException() throw() {}
protected:
};
@@ -412,6 +412,7 @@ public:
LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")
{
}
+ virtual ~LLCertBasicConstraintsValidationException() throw() {}
protected:
};
@@ -421,6 +422,7 @@ public:
LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")
{
}
+ virtual ~LLCertValidationInvalidSignatureException() throw() {}
protected:
};
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 40516f9bbb..d6fb801cc0 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -35,6 +35,8 @@
#include "llfile.h"
#include "lldir.h"
#include "llviewercontrol.h"
+#include "llexception.h"
+#include "stringize.h"
#include <vector>
#include <ios>
#include <openssl/ossl_typ.h>
@@ -72,14 +74,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert)
if(pem_bio == NULL)
{
LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
- throw LLInvalidCertificate(this);
+ LLTHROW(LLInvalidCertificate(this));
}
mCert = NULL;
PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
BIO_free(pem_bio);
if (!mCert)
{
- throw LLInvalidCertificate(this);
+ LLTHROW(LLInvalidCertificate(this));
}
}
@@ -88,7 +90,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert)
{
if (!pCert || !pCert->cert_info)
{
- throw LLInvalidCertificate(this);
+ LLTHROW(LLInvalidCertificate(this));
}
mCert = X509_dup(pCert);
}
@@ -617,7 +619,7 @@ void LLBasicCertificateStore::load_from_file(const std::string& filename)
}
catch (...)
{
- LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file");
}
X509_free(cert_x509);
cert_x509 = NULL;
@@ -873,22 +875,22 @@ void _validateCert(int validation_policy,
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))
{
- throw LLCertException(cert, "Cert doesn't have a Subject Name");
+ LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name"));
}
if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))
{
- throw LLCertException(cert, "Cert doesn't have an Issuer Name");
+ LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name"));
}
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))
{
- throw LLCertException(cert, "Cert doesn't have an expiration period");
+ LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period"));
}
if (!current_cert_info.has(CERT_SHA1_DIGEST))
{
- throw LLCertException(cert, "No SHA1 digest");
+ LLTHROW(LLCertException(cert, "No SHA1 digest"));
}
if (validation_policy & VALIDATION_POLICY_TIME)
@@ -903,7 +905,7 @@ void _validateCert(int validation_policy,
if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||
(validation_date > current_cert_info[CERT_VALID_TO].asDate()))
{
- throw LLCertValidationExpirationException(cert, validation_date);
+ LLTHROW(LLCertValidationExpirationException(cert, validation_date));
}
}
if (validation_policy & VALIDATION_POLICY_SSL_KU)
@@ -914,14 +916,14 @@ void _validateCert(int validation_policy,
!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
{
- throw LLCertKeyUsageValidationException(cert);
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
// only validate EKU if the cert has it
if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&
(!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
LLSD((std::string)CERT_EKU_SERVER_AUTH))))
{
- throw LLCertKeyUsageValidationException(cert);
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
}
if (validation_policy & VALIDATION_POLICY_CA_KU)
@@ -930,7 +932,7 @@ void _validateCert(int validation_policy,
(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
(std::string)CERT_KU_CERT_SIGN)))
{
- throw LLCertKeyUsageValidationException(cert);
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
}
@@ -942,13 +944,13 @@ void _validateCert(int validation_policy,
if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||
!current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])
{
- throw LLCertBasicConstraintsValidationException(cert);
+ LLTHROW(LLCertBasicConstraintsValidationException(cert));
}
if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&
((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&
(depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))
{
- throw LLCertBasicConstraintsValidationException(cert);
+ LLTHROW(LLCertBasicConstraintsValidationException(cert));
}
}
}
@@ -1018,7 +1020,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(cert_chain->size() < 1)
{
- throw LLCertException(NULL, "No certs in chain");
+ LLTHROW(LLCertException(NULL, "No certs in chain"));
}
iterator current_cert = cert_chain->begin();
LLSD current_cert_info;
@@ -1033,11 +1035,11 @@ void LLBasicCertificateStore::validate(int validation_policy,
(*current_cert)->getLLSD(current_cert_info);
if(!validation_params.has(CERT_HOSTNAME))
{
- throw LLCertException((*current_cert), "No hostname passed in for validation");
+ LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation"));
}
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))
{
- throw LLInvalidCertificate((*current_cert));
+ LLTHROW(LLInvalidCertificate((*current_cert)));
}
LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<
@@ -1054,7 +1056,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
X509* cert_x509 = (*current_cert)->getOpenSSLX509();
if(!cert_x509)
{
- throw LLInvalidCertificate((*current_cert));
+ LLTHROW(LLInvalidCertificate((*current_cert)));
}
std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
X509_free( cert_x509 );
@@ -1075,7 +1077,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if((validation_date < cache_entry->second.first) ||
(validation_date > cache_entry->second.second))
{
- throw LLCertValidationExpirationException((*current_cert), validation_date);
+ LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));
}
}
// successfully found in cache
@@ -1107,7 +1109,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*current_cert),
previous_cert))
{
- throw LLCertValidationInvalidSignatureException(previous_cert);
+ LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));
}
}
_validateCert(local_validation_policy,
@@ -1156,7 +1158,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*found_store_cert),
(*current_cert)))
{
- throw LLCertValidationInvalidSignatureException(*current_cert);
+ LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));
}
// successfully validated.
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
@@ -1173,7 +1175,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if (validation_policy & VALIDATION_POLICY_TRUSTED)
{
// we reached the end without finding a trusted cert.
- throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]);
+ LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));
}
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
@@ -1261,7 +1263,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
if (protected_data_stream.gcount() < STORE_SALT_SIZE)
{
- throw LLProtectedDataException("Config file too short.");
+ LLTHROW(LLProtectedDataException("Config file too short."));
}
cipher.decrypt(salt, STORE_SALT_SIZE);
@@ -1301,7 +1303,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
if (parser->parse(parse_stream, mProtectedDataMap,
LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
{
- throw LLProtectedDataException("Config file cannot be decrypted.");
+ LLTHROW(LLProtectedDataException("Config file cannot be decrypted."));
}
}
}
@@ -1364,7 +1366,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()
}
catch (...)
{
- LL_WARNS() << "LLProtectedDataException(Error writing Protected Data Store)" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION("LLProtectedDataException(Error writing Protected Data Store)");
// it's good practice to clean up any secure information on error
// (even though this file isn't really secure. Perhaps in the future
// it may be, however.
@@ -1372,39 +1374,39 @@ void LLSecAPIBasicHandler::_writeProtectedData()
// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
// Decided throwing an exception here was overkill until we figure out why this happens
- //throw LLProtectedDataException("Error writing Protected Data Store");
+ //LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));
}
- try
- {
- // move the temporary file to the specified file location.
- if((( (LLFile::isfile(mProtectedDataFilename) != 0)
- && (LLFile::remove(mProtectedDataFilename) != 0)))
- || (LLFile::rename(tmp_filename, mProtectedDataFilename)))
- {
- LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL;
- LLFile::remove(tmp_filename);
+ try
+ {
+ // move the temporary file to the specified file location.
+ if((( (LLFile::isfile(mProtectedDataFilename) != 0)
+ && (LLFile::remove(mProtectedDataFilename) != 0)))
+ || (LLFile::rename(tmp_filename, mProtectedDataFilename)))
+ {
+ LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL;
+ LLFile::remove(tmp_filename);
- // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
- // Decided throwing an exception here was overkill until we figure out why this happens
- //throw LLProtectedDataException("Could not overwrite protected data store");
- }
+ // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
+ // Decided throwing an exception here was overkill until we figure out why this happens
+ //LLTHROW(LLProtectedDataException("Could not overwrite protected data store"));
+ }
}
catch (...)
{
- LL_WARNS() << "LLProtectedDataException(Error renaming '" << tmp_filename
- << "' to '" << mProtectedDataFilename << "')" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("renaming '" << tmp_filename << "' to '"
+ << mProtectedDataFilename << "'"));
// it's good practice to clean up any secure information on error
// (even though this file isn't really secure. Perhaps in the future
- // it may be, however.
+ // it may be, however).
LLFile::remove(tmp_filename);
//crash in LLSecAPIBasicHandler::_writeProtectedData()
// Decided throwing an exception here was overkill until we figure out why this happens
- //throw LLProtectedDataException("Error writing Protected Data Store");
+ //LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));
}
}
-
+
// instantiate a certificate from a pem string
LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert)
{
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 88fbd233b8..a2c8e7772e 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -687,6 +687,11 @@ bool idle_startup()
gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
show_connect_box = TRUE;
}
+
+ //setup map of datetime strings to codes and slt & local time offset from utc
+ // *TODO: Does this need to be here?
+ LLStringOps::setupDatetimeInfo(false);
+
// Go to the next startup state
LLStartUp::setStartupState( STATE_BROWSER_INIT );
return FALSE;
@@ -1139,9 +1144,6 @@ bool idle_startup()
LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
}
}
- //setup map of datetime strings to codes and slt & local time offset from utc
- // *TODO: Does this need to be here?
- LLStringOps::setupDatetimeInfo (false);
transition_back_to_login_panel(emsg.str());
show_connect_box = true;
}
@@ -3310,6 +3312,13 @@ bool process_login_success_response()
{
time_t now = time(NULL);
gUTCOffset = (server_utc_time - now);
+
+ // Print server timestamp
+ LLSD substitution;
+ substitution["datetime"] = (S32)server_utc_time;
+ std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]";
+ LLStringUtil::format(timeStr, substitution);
+ LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL;
}
}
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 2d06b8599c..d28a7cc048 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -230,8 +230,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f);
F32 vec[3] = {
- fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
- fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
+ (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
+ (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
0.f
};
F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f);
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index 7020ac0c65..edde7c8076 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -202,6 +202,21 @@ void LLToast::hide()
}
}
+/*virtual*/
+void LLToast::setFocus(BOOL b)
+{
+ if (b && !hasFocus() && mPanel)
+ {
+ LLModalDialog::setFocus(TRUE);
+ // mostly for buttons
+ mPanel->setFocus(TRUE);
+ }
+ else
+ {
+ LLModalDialog::setFocus(b);
+ }
+}
+
void LLToast::onFocusLost()
{
if(mWrapperPanel && !isBackgroundVisible())
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index f02d7c2a1a..cd92189012 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -150,6 +150,8 @@ public:
//
virtual void hide();
+ /*virtual*/ void setFocus(BOOL b);
+
/*virtual*/ void onFocusLost();
/*virtual*/ void onFocusReceived();
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 98ed2f0fc4..e3a856be5c 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -103,7 +103,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
}
// for the scriptdialog buttons we use fixed button size. This is a limit!
- if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > BUTTON_WIDTH)
+ if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > (BUTTON_WIDTH-2*HPAD))
{
p.rect.width = 1;
p.auto_resize = true;
@@ -160,7 +160,11 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair
}
LLButton* btn = it->second;
LLRect btn_rect(btn->getRect());
- if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel
+ if (buttons.size() == 1) // for the one-button forms, center that button
+ {
+ left = (max_width - btn_rect.getWidth()) / 2;
+ }
+ else if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel
{
// looks like we need to add button to the next row
left = 0;
@@ -321,6 +325,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
mTextBox->setContentTrusted(is_content_trusted);
mTextBox->setValue(mNotification->getMessage());
mTextBox->setIsFriendCallback(LLAvatarActions::isFriend);
+ mTextBox->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
// add buttons for a script notification
if (mIsTip)
diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp
index 91ba8c0247..7a3a1d8fd7 100644
--- a/indra/newview/lltoastscriptquestion.cpp
+++ b/indra/newview/lltoastscriptquestion.cpp
@@ -54,6 +54,19 @@ BOOL LLToastScriptQuestion::postBuild()
return TRUE;
}
+
+// virtual
+void LLToastScriptQuestion::setFocus(BOOL b)
+{
+ LLToastPanel::setFocus(b);
+ // toast can fade out and disappear with focus ON, so reset to default anyway
+ LLButton* dfbutton = getDefaultButton();
+ if (dfbutton && dfbutton->getVisible() && dfbutton->getEnabled())
+ {
+ dfbutton->setFocus(b);
+ }
+}
+
void LLToastScriptQuestion::snapToMessageHeight()
{
LLTextBox* mMessage = getChild<LLTextBox>("top_info_message");
@@ -118,6 +131,12 @@ void LLToastScriptQuestion::createButtons()
button->setRect(rect);
buttons_width += rect.getWidth() + LEFT_PAD;
+
+ if (form_element.has("default") && form_element["default"].asBoolean())
+ {
+ button->setFocus(TRUE);
+ setDefaultBtn(button);
+ }
}
}
}
diff --git a/indra/newview/lltoastscriptquestion.h b/indra/newview/lltoastscriptquestion.h
index 3a557f60f6..a756f88415 100644
--- a/indra/newview/lltoastscriptquestion.h
+++ b/indra/newview/lltoastscriptquestion.h
@@ -39,6 +39,8 @@ public:
virtual BOOL postBuild();
virtual ~LLToastScriptQuestion(){};
+ /*virtual*/ void setFocus(BOOL b);
+
private:
void snapToMessageHeight();
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index 2f8e464b71..b0e3b5bf89 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -83,6 +83,7 @@ LLToolMgr::LLToolMgr()
// Not a panel, register these callbacks globally.
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this));
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this));
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.EnabledOrActive", boost::bind(&LLToolMgr::buildEnabledOrActive, this));
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2));
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Marketplace.Enabled", boost::bind(&LLToolMgr::canAccessMarketplace, this));
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Marketplace.Toggle", boost::bind(&LLToolMgr::toggleMarketplace, this, _2));
@@ -264,17 +265,21 @@ bool LLToolMgr::canEdit()
return LLViewerParcelMgr::getInstance()->allowAgentBuild();
}
+bool LLToolMgr::buildEnabledOrActive()
+{
+ return inEdit() || canEdit();
+}
+
void LLToolMgr::toggleBuildMode(const LLSD& sdname)
{
const std::string& param = sdname.asString();
+ LLFloaterReg::toggleInstanceOrBringToFront("build");
if (param == "build" && !canEdit())
{
return;
}
- LLFloaterReg::toggleInstanceOrBringToFront("build");
-
bool build_visible = LLFloaterReg::instanceVisible("build");
if (build_visible)
{
diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h
index a3c1045aac..e5b45750d9 100644
--- a/indra/newview/lltoolmgr.h
+++ b/indra/newview/lltoolmgr.h
@@ -54,6 +54,7 @@ public:
bool inEdit();
bool canEdit();
+ bool buildEnabledOrActive();
bool canAccessMarketplace();
void toggleBuildMode(const LLSD& sdname);
void toggleMarketplace(const LLSD& sdname);
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index f611d0503f..b015cde45d 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -183,7 +183,7 @@ void LLTracker::render3D()
F32 dist = gFloaterWorldMap->getDistanceToDestination(pos_global, 0.5f);
if (dist < DESTINATION_REACHED_RADIUS)
{
- instance()->stopTrackingLocation();
+ instance()->stopTrackingLocation(FALSE,TRUE);
}
else
{
@@ -655,13 +655,13 @@ void LLTracker::stopTrackingLandmark(BOOL clear_ui)
}
-void LLTracker::stopTrackingLocation(BOOL clear_ui)
+void LLTracker::stopTrackingLocation(BOOL clear_ui, BOOL dest_reached)
{
purgeBeaconText();
mTrackedLocationName.assign("");
mIsTrackingLocation = FALSE;
mTrackedPositionGlobal.zeroVec();
- gFloaterWorldMap->clearLocationSelection(clear_ui);
+ gFloaterWorldMap->clearLocationSelection(clear_ui, dest_reached);
mTrackingStatus = TRACKING_NOTHING;
mTrackingLocationType = LOCATION_NOTHING;
}
diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h
index 218f3430a6..a1c5052c1b 100644
--- a/indra/newview/lltracker.h
+++ b/indra/newview/lltracker.h
@@ -116,7 +116,7 @@ protected:
void stopTrackingAll(BOOL clear_ui = FALSE);
void stopTrackingAvatar(BOOL clear_ui = FALSE);
- void stopTrackingLocation(BOOL clear_ui = FALSE);
+ void stopTrackingLocation(BOOL clear_ui = FALSE, BOOL dest_reached = FALSE);
void stopTrackingLandmark(BOOL clear_ui = FALSE);
void drawMarker(const LLVector3d& pos_global, const LLColor4& color);
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index f0dafec240..497ff4d2bf 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -837,5 +837,12 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res
}
}
+ // Let the Snapshot floater know we have failed uploading.
+ LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot)
+ {
+ floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
+ }
+
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 99a9ed1d75..697199df6b 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6986,20 +6986,25 @@ class LLAvatarCall : public view_listener_t
namespace
{
- struct QueueObjects : public LLSelectedObjectFunctor
+ struct QueueObjects : public LLSelectedNodeFunctor
{
BOOL scripted;
BOOL modifiable;
LLFloaterScriptQueue* mQueue;
QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
- virtual bool apply(LLViewerObject* obj)
+ virtual bool apply(LLSelectNode* node)
{
+ LLViewerObject* obj = node->getObject();
+ if (!obj)
+ {
+ return true;
+ }
scripted = obj->flagScripted();
modifiable = obj->permModify();
if( scripted && modifiable )
{
- mQueue->addObject(obj->getID());
+ mQueue->addObject(obj->getID(), node->mName);
return false;
}
else
@@ -7015,7 +7020,7 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
QueueObjects func(q);
LLSelectMgr *mgr = LLSelectMgr::getInstance();
LLObjectSelectionHandle selectHandle = mgr->getSelection();
- bool fail = selectHandle->applyToObjects(&func);
+ bool fail = selectHandle->applyToNodes(&func);
if(fail)
{
if ( !func.scripted )
@@ -7901,7 +7906,7 @@ void handle_web_browser_test(const LLSD& param)
void handle_web_content_test(const LLSD& param)
{
std::string url = param.asString();
- LLWeb::loadURLInternal(url);
+ LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true);
}
void handle_show_url(const LLSD& param)
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index 7efa821bbf..814060f4f2 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -441,10 +441,20 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewer
return NULL;
}
+ F32 prev_max_age = pssp->mPartSysData.mMaxAge;
+ F32 prev_start_age = pssp->mPartSysData.mStartAge;
if (!pssp->mPartSysData.unpackBlock(block_num))
{
return NULL;
}
+ else if (pssp->mPartSysData.mMaxAge
+ && (prev_max_age != pssp->mPartSysData.mMaxAge || prev_start_age != pssp->mPartSysData.mStartAge))
+ {
+ // reusing existing pss, so reset time to allow particles to start again
+ pssp->mLastUpdateTime = 0.f;
+ pssp->mLastPartTime = 0.f;
+ }
+
if (pssp->mPartSysData.mTargetUUID.notNull())
{
LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index cac2ed8585..899ab3a371 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -264,17 +264,18 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
}
S32 id = ++mHttpResponderID;
- ++mSeedCapAttempts;
LLSD capabilityNames = LLSD::emptyArray();
buildCapabilityNames(capabilityNames);
LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url
- << " (attempt #" << mSeedCapAttempts << ")" << LL_ENDL;
+ << " (attempt #" << mSeedCapAttempts + 1 << ")" << LL_ENDL;
regionp = NULL;
result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
+ ++mSeedCapAttempts;
+
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index db4b555eca..ed719ae418 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1875,7 +1875,8 @@ bool LLViewerFetchedTexture::updateFetch()
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false);
static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2);
static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3);
- if(textures_decode_disabled)
+ if(textures_decode_disabled ||
+ (gUseWireframe && mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED_SELF)) // don't fetch the surface textures in wireframe mode
{
return false;
}
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 08f6143861..d7080051da 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -171,13 +171,27 @@ void LLViewerTextureList::doPreloadImages()
mImagePreloads.insert(image);
}
image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
- 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"));
+ 0, 0, IMG_TRANSPARENT);
if (image)
{
image->setAddressMode(LLTexUnit::TAM_WRAP);
mImagePreloads.insert(image);
}
-
+ image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
+ GL_ALPHA8, GL_ALPHA, IMG_ALPHA_GRAD);
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mImagePreloads.insert(image);
+ }
+ image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
+ GL_ALPHA8, GL_ALPHA, IMG_ALPHA_GRAD_2D);
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mImagePreloads.insert(image);
+ }
+
LLPointer<LLImageRaw> img_blak_square_tex(new LLImageRaw(2, 2, 3));
memset(img_blak_square_tex->getData(), 0, img_blak_square_tex->getDataSize());
LLPointer<LLViewerFetchedTexture> img_blak_square(new LLViewerFetchedTexture(img_blak_square_tex, FTT_DEFAULT, FALSE));
@@ -188,7 +202,7 @@ void LLViewerTextureList::doPreloadImages()
static std::string get_texture_list_name()
{
- return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "texture_list_" + gSavedSettings.getString("LoginLocation") + ".xml");
+ return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + ".xml");
}
void LLViewerTextureList::doPrefetchImages()
@@ -293,7 +307,7 @@ void LLViewerTextureList::shutdown()
break;
}
- if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty())
+ if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "").empty())
{
std::string filename = get_texture_list_name();
llofstream file;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index b9dd43f061..cdc7e20c2c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7313,7 +7313,6 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
//-----------------------------------------------------------------------------
void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
{
- static S32 largestSelfCOFSeen(LLViewerInventoryCategory::VERSION_UNKNOWN);
LL_DEBUGS("Avatar") << "starts" << LL_ENDL;
bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
@@ -7348,43 +7347,34 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
return;
}
- S32 this_update_cof_version = contents.mCOFVersion;
- S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion;
+ S32 thisAppearanceVersion(contents.mCOFVersion);
+ if (isSelf())
+ { // In the past this was considered to be the canonical COF version,
+ // that is no longer the case. The canonical version is maintained
+ // by the AIS code and should match the COF version there. Even so,
+ // we must prevent rolling this one backwards backwards or processing
+ // stale versions.
- if( isSelf() )
- {
- LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version
- << " last_update_request_cof_version " << last_update_request_cof_version
- << " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL;
+ S32 aisCOFVersion(LLAppearanceMgr::instance().getCOFVersion());
+
+ LL_DEBUGS("Avatar") << "handling self appearance message #" << thisAppearanceVersion <<
+ " (highest seen #" << mLastUpdateReceivedCOFVersion <<
+ ") (AISCOF=#" << aisCOFVersion << ")" << LL_ENDL;
- if (largestSelfCOFSeen > this_update_cof_version)
+ if (mLastUpdateReceivedCOFVersion >= thisAppearanceVersion)
{
- LL_WARNS("Avatar") << "Already processed appearance for COF version " <<
- largestSelfCOFSeen << ", discarding appearance with COF " << this_update_cof_version << LL_ENDL;
+ LL_WARNS("Avatar") << "Stale appearance received #" << thisAppearanceVersion <<
+ " attempt to roll back from #" << mLastUpdateReceivedCOFVersion <<
+ "... dropping." << LL_ENDL;
+ return;
+ }
+ if (isEditingAppearance())
+ {
+ LL_DEBUGS("Avatar") << "Editing appearance. Dropping appearance update." << LL_ENDL;
return;
}
- largestSelfCOFSeen = this_update_cof_version;
-
- }
- else
- {
- LL_DEBUGS("Avatar") << "appearance message received" << LL_ENDL;
- }
-
- // Check for stale update.
- if (isSelf()
- && (this_update_cof_version < last_update_request_cof_version))
- {
- LL_WARNS() << "Stale appearance update, wanted version " << last_update_request_cof_version
- << ", got " << this_update_cof_version << LL_ENDL;
- return;
- }
- if (isSelf() && isEditingAppearance())
- {
- LL_DEBUGS("Avatar") << "ignoring appearance message while in appearance edit" << LL_ENDL;
- return;
- }
+ }
// SUNSHINE CLEANUP - is this case OK now?
S32 num_params = contents.mParamWeights.size();
@@ -7399,13 +7389,17 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
}
// No backsies zone - if we get here, the message should be valid and usable, will be processed.
- LL_INFOS("Avatar") << "Processing appearance message version " << this_update_cof_version << LL_ENDL;
+ LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL;
- // Note:
- // RequestAgentUpdateAppearanceResponder::onRequestRequested()
- // assumes that cof version is only updated with server-bake
- // appearance messages.
- mLastUpdateReceivedCOFVersion = this_update_cof_version;
+ if (isSelf())
+ {
+ // Note:
+ // locally the COF is maintained via LLInventoryModel::accountForUpdate
+ // which is called from various places. This should match the simhost's
+ // idea of what the COF version is. AIS however maintains its own version
+ // of the COF that should be considered canonical.
+ mLastUpdateReceivedCOFVersion = thisAppearanceVersion;
+ }
if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE))
{
@@ -7528,7 +7522,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
// Got an update for some other avatar
// Ignore updates for self, because we have a more authoritative value in the preferences.
setHoverOffset(contents.mHoverOffset);
- LL_INFOS("Avatar") << avString() << "setting hover to " << contents.mHoverOffset[2] << LL_ENDL;
+ LL_DEBUGS("Avatar") << avString() << "setting hover to " << contents.mHoverOffset[2] << LL_ENDL;
}
if (!contents.mHoverOffsetWasSet && !isSelf())
@@ -8151,6 +8145,7 @@ U32 LLVOAvatar::getPartitionType() const
//static
void LLVOAvatar::updateImpostors()
{
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
LLCharacter::sAllowInstancesChange = FALSE;
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 07427e0377..189ed54993 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -427,7 +427,7 @@ void LLVivoxVoiceClient::connectorCreate()
void LLVivoxVoiceClient::connectorShutdown()
{
- if(!mConnectorEstablished)
+ if(mConnectorEstablished)
{
std::ostringstream stream;
stream
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 8f0b233f01..e69a8d1d1d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3627,10 +3627,8 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_v
F32 radius = getScale().length()*0.5f;
if (isMesh())
- {
- LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
-
- return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value);
+ {
+ return gMeshRepo.getStreamingCost(getVolume()->getParams().getSculptID(), radius, bytes, visible_bytes, mLOD, unscaled_value);
}
else
{
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index b37e41fb85..8026dc3ea8 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -104,10 +104,10 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std
// static
// Explicitly open a Web URL using the Web content floater
-void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
+void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode)
{
LLFloaterWebContent::Params p;
- p.url(url).target(target).id(uuid);
+ p.url(url).target(target).id(uuid).dev_mode(dev_mode);
LLFloaterReg::showInstance("web_content", p);
}
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 7c90badbfe..7149ce9baf 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -57,7 +57,7 @@ public:
static void loadURL(const std::string& url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);
// load content using built-in browser
- static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);
+ static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null, bool dev_mode = false);
/// Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 11d3706821..cee47a591e 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -957,10 +957,10 @@ void LLWorld::updateWaterObjects()
center_y = min_y + (wy >> 1);
S32 add_boundary[4] = {
- 512 - (max_x - region_x),
- 512 - (max_y - region_y),
- 512 - (region_x - min_x),
- 512 - (region_y - min_y) };
+ (S32)(512 - (max_x - region_x)),
+ (S32)(512 - (max_y - region_y)),
+ (S32)(512 - (region_x - min_x)),
+ (S32)(512 - (region_y - min_y)) };
S32 dir;
for (dir = 0; dir < 8; dir++)
diff --git a/indra/newview/skins/default/textures/icons/Video_URL_Off.png b/indra/newview/skins/default/textures/icons/Video_URL_Off.png
new file mode 100644
index 0000000000..40e5df7d81
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Video_URL_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 72037a84b3..01e8c16937 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -676,7 +676,10 @@ with the same filename but different name
<texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" />
<texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" />
- <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
+
+ <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" />
+
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
<texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml
index f4aca7bb3d..0982683a7f 100644
--- a/indra/newview/skins/default/xui/en/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml
@@ -29,6 +29,14 @@
name="NotRunning">
Not running
</floater.string>
+ <floater.string
+ name="Timeout">
+ Timeout: [OBJECT_NAME]
+ </floater.string>
+ <floater.string
+ name="LoadingObjInv">
+ Loading inventory for: [OBJECT_NAME]
+ </floater.string>
<button
follows="right|bottom"
height="24"
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
index a80440e844..4473ce0cda 100644
--- a/indra/newview/skins/default/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -154,6 +154,136 @@
</button>
</layout_panel>
<layout_panel
+ height="22"
+ layout="topleft"
+ left_delta="0"
+ name="debug_controls"
+ top_delta="0"
+ auto_resize="false"
+ width="585">
+ <button
+ image_overlay="Home_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Web tests home page"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="1"
+ name="web_test_home_page"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ </button>
+
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MPEG4 Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="27"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MKV Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="WebM Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="75"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MP3 audio Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="99"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="FLV Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="123"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/>
+ </button>
+ </layout_panel>
+ <layout_panel
height="40"
layout="topleft"
left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index 170b7177fb..5d05ecf127 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -12,6 +12,7 @@
<os name="Mac">
<file>ヒラギノ角ゴ Pro W3.otf</file>
<file>ヒラギノ角ゴ ProN W3.otf</file>
+ <file>ヒラギノ明朝 ProN W3.ttc</file>
<file>AppleGothic.dfont</file>
<file>AppleGothic.ttf</file>
<file>AppleSDGothicNeo-Regular.otf</file>
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 419ec359a6..a39ee5fddd 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -140,13 +140,6 @@
function="Advanced.ShowDebugSettings"
parameter="all" />
</menu_item_call>
- <menu_item_call
- label="UI/Color Settings"
- name="UI/Color Settings">
- <menu_item_call.on_click
- function="Advanced.ShowDebugSettings"
- parameter="skin" />
- </menu_item_call>
<menu_item_separator />
<menu_item_call
label="XUI Preview Tool"
@@ -232,11 +225,11 @@
parameter="message_critical" />
</menu_item_call>
<menu_item_call
- label="Web Content Floater Debug Test"
- name="Web Content Floater Debug Test">
+ label="Media Browser"
+ name="Media Browser">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ parameter="http://google.com"/>
</menu_item_call>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml
index 2d4f1792c2..5137aea72a 100644
--- a/indra/newview/skins/default/xui/en/menu_object_icon.xml
+++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml
@@ -23,6 +23,20 @@
<menu_item_call.on_click
function="ObjectIcon.Action"
parameter="block" />
+ <menu_item_call.on_visible
+ function="ObjectIcon.Visible"
+ parameter="not_blocked" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unblock"
+ layout="topleft"
+ name="Unblock">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="unblock" />
+ <menu_item_call.on_visible
+ function="ObjectIcon.Visible"
+ parameter="is_blocked" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml
index 8790fde7c5..b5a4b87acd 100644
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml
@@ -40,6 +40,14 @@
function="CheckControl"
parameter="FriendsListShowPermissions" />
</menu_item_check>
+ <menu_item_check name="view_usernames" label="Hide usernames">
+ <menu_item_check.on_click
+ function="People.Friends.ViewSort.Action"
+ parameter="view_usernames" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="FriendsListHideUsernames" />
+ </menu_item_check>
<menu_item_check name="view_conversation" label="View Conversation Log...">
<menu_item_check.on_check
function="Floater.Visible"
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
index f12226ebeb..c1500d4e7c 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
@@ -143,4 +143,20 @@
function="Avatar.EnableItem"
parameter="can_block" />
</menu_item_check>
+ <menu_item_call
+ label="Freeze"
+ name="freeze">
+ <menu_item_call.on_click
+ function="Avatar.Freeze" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="eject">
+ <menu_item_call.on_click
+ function="Avatar.Eject" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
index da88ca9f4d..a9f6b8045d 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
@@ -50,4 +50,12 @@
function="ToggleControl"
parameter="NearbyListShowMap" />
</menu_item_check>
+ <menu_item_check name="view_usernames" label="Hide usernames">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="view_usernames" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="NearbyListHideUsernames" />
+ </menu_item_check>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
index b9d003b841..41d40b389a 100644
--- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
@@ -16,6 +16,13 @@
<menu_item_call.on_click
function="Url.Block" />
</menu_item_call>
+ <menu_item_call
+ label="Unblock"
+ layout="topleft"
+ name="unblock_object">
+ <menu_item_call.on_click
+ function="Url.Unblock" />
+ </menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 0a492fb37b..8a649a57d1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -806,7 +806,7 @@
<menu_item_check.on_click
function="Build.Toggle" />
<menu_item_check.on_enable
- function="Build.Enabled" />
+ function="Build.EnabledOrActive" />
</menu_item_check>
<menu
create_jump_keys="true"
@@ -3141,30 +3141,13 @@
label="UI"
name="UI"
tear_off="true">
- <!-- <menu_item_check
- label="New Bottom Bar"
- name="New Bottom Bar">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="BottomPanelNew" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="BottomPanelNew" />
- </menu_item_check>-->
- <menu_item_call
- label="Media Browser Test"
- name="Web Browser Test">
- <menu_item_call.on_click
- function="Advanced.WebBrowserTest"
- parameter="http://secondlife.com/app/search/slurls.html"/>
- </menu_item_call>
<menu_item_call
- label="Web Content Browser"
- name="Web Content Browser"
- shortcut="control|shift|Z">
+ label="Media Browser"
+ name="Media Browser"
+ shortcut="control|alt|shift|Z">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ parameter="http://google.com"/>
</menu_item_call>
<menu_item_call
label="FB Connect Test"
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
index 2d54e69601..44b2727671 100644
--- a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
@@ -27,4 +27,11 @@
<on_click
function="Wearing.Edit" />
</menu_item_call>
+ <menu_item_call
+ label="Show Original"
+ layout="topleft"
+ name="show_original">
+ <on_click
+ function="Wearing.ShowOriginal" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml
index 7cb4a6e53b..c27fac6731 100644
--- a/indra/newview/skins/default/xui/en/mime_types.xml
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -130,10 +130,21 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</scheme>
- <mimetype name="blank">
+ <scheme name="libvlc">
+ <label name="libvlc_label">
+ LibVLC supported media
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_libvlc
+ </impl>
+ </scheme>
+ <mimetype name="blank">
<label name="blank_label">
- None -
</label>
@@ -163,7 +174,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/*">
@@ -174,7 +185,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="image/*">
@@ -196,7 +207,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/javascript">
@@ -218,7 +229,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/pdf">
@@ -295,7 +306,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@@ -306,7 +317,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@@ -317,7 +328,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@@ -328,7 +339,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@@ -438,7 +449,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/mp4">
@@ -449,10 +460,21 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
- <mimetype menu="1" name="video/quicktime">
+ <mimetype name="application/octet-stream">
+ <label name="video/octet-stream">
+ Movie
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_libvlc
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/quicktime">
<label name="video/quicktime_label">
Movie (QuickTime)
</label>
@@ -460,7 +482,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@@ -471,7 +493,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@@ -482,7 +504,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +515,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml
index 84aeaf3b54..7188b1e699 100644
--- a/indra/newview/skins/default/xui/en/mime_types_linux.xml
+++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml
@@ -130,7 +130,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</scheme>
<mimetype name="blank">
@@ -163,7 +163,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/*">
@@ -174,7 +174,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="image/*">
@@ -196,7 +196,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/javascript">
@@ -218,7 +218,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/pdf">
@@ -295,7 +295,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@@ -306,7 +306,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@@ -317,7 +317,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@@ -328,7 +328,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@@ -438,7 +438,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/mp4">
@@ -449,7 +449,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="video/quicktime">
@@ -460,7 +460,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@@ -471,7 +471,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@@ -482,7 +482,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +493,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 492d963653..dfde38bc5f 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1150,6 +1150,22 @@ Error encoding snapshot.
<notification
icon="alertmodal.tga"
+ name="ErrorPhotoCannotAfford"
+ type="alertmodal">
+ You need L$[COST] to save a photo to your inventory. You may either buy L$ or save the photo to your computer instead.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorTextureCannotAfford"
+ type="alertmodal">
+ You need L$[COST] to save a texture to your inventory. You may either buy L$ or save the photo to your computer instead.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="ErrorUploadingPostcard"
type="alertmodal">
There was a problem sending a snapshot due to the following reason: [REASON]
@@ -3523,6 +3539,19 @@ Teleport all Residents in this region home?
<notification
icon="alertmodal.tga"
+ name="ChangeObjectBonusFactor"
+ type="alertmodal">
+ Lowering the object bonus after builds have been established in a region may cause objects to be returned or deleted. Are you sure you want to change object bonus?
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm changing object bonus factor"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="EstateObjectReturn"
type="alertmodal">
Are you sure you want to return objects owned by [USER_NAME]?
@@ -6881,6 +6910,19 @@ This area has building disabled. You can&apos;t build or rez objects here.
</notification>
<notification
+ icon="notify.tga"
+ name="PathfindingDirtyRebake"
+ persist="true"
+ type="notify">
+ <unique/>
+ The region has pending pathfinding changes. If you have build rights, you may rebake the region by clicking on the “Rebake region” button.
+ <usetemplate
+ name="okbutton"
+ yestext="Rebake region"
+ />
+ </notification>
+
+ <notification
icon="notify.tga"
name="DynamicPathfindingDisabled"
persist="true"
@@ -8272,8 +8314,18 @@ Appearance has been saved to XML to [PATH]
<notification icon="notifytip.tga"
name="AppearanceToXMLFailed" type="notifytip">
Failed to save appearance to XML.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="PresetNotSaved"
+ type="notifytip">
+Error saving preset [NAME].
+ </notification>
+
+ <notification
icon="notifytip.tga"
- name="PresetNotDeleted"
+ name="PresetNotDeleted"
type="notifytip">
Error deleting preset [NAME].
</notification>
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 183ae2e824..ded814bbeb 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -67,7 +67,7 @@
follows="left|top"
height="32"
left_pad="-11"
- max_length_bytes="16"
+ max_length_chars="16"
text_pad_left="8"
name="password_edit"
label="Password"
diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml
index d1416ece82..35b80c56ab 100644
--- a/indra/newview/skins/default/xui/en/panel_login_first.xml
+++ b/indra/newview/skins/default/xui/en/panel_login_first.xml
@@ -124,7 +124,7 @@
width="200"
height="32"
left="220"
- max_length_bytes="16"
+ max_length_chars="16"
name="password_edit"
label="Password"
text_pad_left="8"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 3e96160834..4a5117adac 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -138,7 +138,7 @@
initial_value="1"
layout="topleft"
left_pad="0"
- max_val="1.5"
+ max_val="2.0"
min_val="0.75"
name="ui_scale_slider"
top_pad="-14"
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
index eb67d07601..068e4420bc 100644
--- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -374,9 +374,11 @@
layout="topleft"
tool_tip="Movie play progress"
width="200">
- <slider_bar.commit_callback
- function="MediaCtrl.JumpProgress" />
- </slider_bar>
+ <slider_bar.mouse_down_callback
+ function="MediaCtrl.MouseDown" />
+ <slider_bar.mouse_up_callback
+ function="MediaCtrl.MouseUp" />
+ </slider_bar>
</layout_panel>
<layout_panel
name="skip_back"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ae63546082..0a17c202c3 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -51,12 +51,14 @@ OpenGL Version: [OPENGL_VERSION]
J2C Decoder Version: [J2C_VERSION]
Audio Driver Version: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF Version: [LLCEFLIB_VERSION]
+LibVLC Version: [LIBVLC_VERSION]
Voice Server Version: [VOICE_VERSION]
</string>
<string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string>
+ <string name="AboutTime">[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second,datetime,slt]</string>
<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>
<string name="BuildConfiguration">Build Configuration</string>
-
+
<!-- progress -->
<string name="ProgressRestoring">Restoring...</string>
<string name="ProgressChangingResolution">Changing resolution...</string>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 1c77cf805e..66d730d1ac 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -30,6 +30,7 @@ import sys
import os.path
import shutil
import errno
+import json
import re
import tarfile
import time
@@ -181,9 +182,16 @@ class ViewerManifest(LLManifest):
self.path("*.tga")
self.end_prefix("local_assets")
- # Files in the newview/ directory
+ # File in the newview/ directory
self.path("gpu_table.txt")
- # The summary.json file gets left in the build directory by newview/CMakeLists.txt.
+
+ #summary.json. Standard with exception handling is fine. If we can't open a new file for writing, we have worse problems
+ summary_dict = {"Type":"viewer","Version":'.'.join(self.args['version']),"Channel":self.channel_with_pkg_suffix()}
+ with open(os.path.join(os.pardir,'summary.json'), 'w') as summary_handle:
+ json.dump(summary_dict,summary_handle)
+
+ #we likely no longer need the test, since we will throw an exception above, but belt and suspenders and we get the
+ #return code for free.
if not self.path2basename(os.pardir, "summary.json"):
print "No summary.json file"
@@ -436,6 +444,11 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("media_plugin_cef.dll")
self.end_prefix()
+ # Media plugins - LibVLC
+ if self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"):
+ self.path("media_plugin_libvlc.dll")
+ self.end_prefix()
+
# winmm.dll shim
if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
self.path("winmm.dll")
@@ -542,6 +555,12 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("zh-TW.pak")
self.end_prefix()
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"):
+ self.path("libvlc.dll")
+ self.path("libvlccore.dll")
+ self.path("plugins/")
+ self.end_prefix()
+
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
@@ -1081,8 +1100,18 @@ class LinuxManifest(ViewerManifest):
# plugins
if self.prefix(src="", dst="bin/llplugin"):
self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
+ self.path("../media_plugins/libvlc/libmedia_plugin_libvlc.so", "libmedia_plugin_libvlc.so")
self.end_prefix("bin/llplugin")
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"):
+ self.path( "plugins.dat" )
+ self.path( "*/*.so" )
+ self.end_prefix()
+
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib' ), dst="lib"):
+ self.path( "libvlc*.so*" )
+ self.end_prefix()
+
# llcommon
if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"):
print "Skipping llcommon.so (assuming llcommon was linked statically)"
@@ -1136,7 +1165,7 @@ class LinuxManifest(ViewerManifest):
def strip_binaries(self):
if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
- self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
+ self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
class Linux_i686_Manifest(LinuxManifest):
def construct(self):
diff --git a/indra/test/llapp_tut.cpp b/indra/test/llapp_tut.cpp
index aa5c0672e6..98e714a497 100644
--- a/indra/test/llapp_tut.cpp
+++ b/indra/test/llapp_tut.cpp
@@ -41,7 +41,7 @@ namespace tut
public:
virtual bool init() { return true; }
virtual bool cleanup() { return true; }
- virtual bool mainLoop() { return true; }
+ virtual bool frame() { return true; }
};
LLTestApp* mApp;
application()
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 53d4acc9e0..c767d52c7b 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -42,6 +42,8 @@
#include "llevents.h"
#include "lleventfilter.h"
#include "lleventcoro.h"
+#include "llexception.h"
+#include "stringize.h"
//*********************
// LLLogin
@@ -128,30 +130,23 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
{
- try
- {
- LLSD printable_params = login_params;
- //if(printable_params.has("params")
- // && printable_params["params"].has("passwd"))
- //{
- // printable_params["params"]["passwd"] = "*******";
- //}
- LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
+ LLSD printable_params = login_params;
+ if (printable_params.has("params")
+ && printable_params["params"].has("passwd"))
+ {
+ printable_params["params"]["passwd"] = "*******";
+ }
+ try
+ {
+ LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
<< " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
- // Arriving in SRVRequest state
- LLEventStream replyPump("SRVreply", true);
- // Should be an array of one or more uri strings.
-
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
// EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
// to share them -- but the EXT-3934 fix made it possible for an abandoned
// SRV response to arrive just as we were expecting the XMLRPC response.
LLEventStream loginReplyPump("loginreply", true);
- // Loop through the rewrittenURIs, counting attempts along the way.
- // Because of possible redirect responses, we may make more than one
- // attempt per rewrittenURIs entry.
LLSD::Integer attempts = 0;
LLSD request(login_params);
@@ -167,11 +162,11 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
LLSD progress_data;
progress_data["attempt"] = attempts;
progress_data["request"] = request;
- if(progress_data["request"].has("params")
- && progress_data["request"]["params"].has("passwd"))
- {
- progress_data["request"]["params"]["passwd"] = "*******";
- }
+ if (progress_data["request"].has("params")
+ && progress_data["request"]["params"].has("passwd"))
+ {
+ progress_data["request"]["params"]["passwd"] = "*******";
+ }
sendProgressEvent("offline", "authenticating", progress_data);
// We expect zero or more "Downloading" status events, followed by
@@ -189,8 +184,8 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
// Still Downloading -- send progress update.
sendProgressEvent("offline", "downloading");
}
-
- LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
+
+ LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
status = mAuthResponse["status"].asString();
// Okay, we've received our final status event for this
@@ -202,7 +197,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
break;
}
- sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
+ sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
// Here the login service at the current URI is redirecting us
// to some other URI ("indeterminate" -- why not "redirect"?).
@@ -212,8 +207,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
request["method"] = mAuthResponse["responses"]["next_method"].asString();
} // loop back to try the redirected URI
- // Here we're done with redirects for the current rewrittenURIs
- // entry.
+ // Here we're done with redirects.
if (status == "Complete")
{
// StatusComplete does not imply auth success. Check the
@@ -230,14 +224,14 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
return; // Done!
}
-// /* Sometimes we end with "Started" here. Slightly slow server?
-// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
-// */
-// if( status == "Started")
-// {
-// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
-// continue;
-// }
+// /* Sometimes we end with "Started" here. Slightly slow server?
+// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
+// */
+// if( status == "Started")
+// {
+// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
+// continue;
+// }
// If we don't recognize status at all, trouble
if (! (status == "CURLError"
@@ -250,27 +244,25 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
}
// Here status IS one of the errors tested above.
-
- // Here we got through all the rewrittenURIs without succeeding. Tell
- // caller this didn't work out so well. Of course, the only failure data
- // we can reasonably show are from the last of the rewrittenURIs.
-
- // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
- // llsd with no "responses" node. To make the output from an incomplete login symmetrical
- // to success, add a data/message and data/reason fields.
- LLSD error_response;
- error_response["reason"] = mAuthResponse["status"];
- error_response["errorcode"] = mAuthResponse["errorcode"];
- error_response["message"] = mAuthResponse["error"];
- if(mAuthResponse.has("certificate"))
- {
- error_response["certificate"] = mAuthResponse["certificate"];
- }
- sendProgressEvent("offline", "fail.login", error_response);
- }
- catch (...) {
- LL_ERRS() << "login exception caught" << LL_ENDL;
- }
+ // Tell caller this didn't work out so well.
+
+ // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
+ // llsd with no "responses" node. To make the output from an incomplete login symmetrical
+ // to success, add a data/message and data/reason fields.
+ LLSD error_response;
+ error_response["reason"] = mAuthResponse["status"];
+ error_response["errorcode"] = mAuthResponse["errorcode"];
+ error_response["message"] = mAuthResponse["error"];
+ if(mAuthResponse.has("certificate"))
+ {
+ error_response["certificate"] = mAuthResponse["certificate"];
+ }
+ sendProgressEvent("offline", "fail.login", error_response);
+ }
+ catch (...) {
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << uri << "', " << printable_params << ")"));
+ }
}
void LLLogin::Impl::disconnect()
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index 382689afa0..04e0395c50 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -27,7 +27,7 @@
#include "llupdatedownloader.h"
#include "httpcommon.h"
-#include <stdexcept>
+#include "llexception.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <curl/curl.h>
@@ -85,11 +85,11 @@ private:
namespace {
class DownloadError:
- public std::runtime_error
+ public LLException
{
public:
DownloadError(const char * message):
- std::runtime_error(message)
+ LLException(message)
{
; // No op.
}
@@ -467,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
if(!mCurl)
{
- throw DownloadError("failed to initialize curl");
+ LLTHROW(DownloadError("failed to initialize curl"));
}
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true));
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true));
@@ -508,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
if(mHeaderList == 0)
{
- throw DownloadError("cannot add Range header");
+ LLTHROW(DownloadError("cannot add Range header"));
}
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList));
@@ -524,7 +524,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std
mDownloadData["hash"] = hash;
mDownloadData["current_version"] = ll_get_version();
LLSD path = uri.pathArray();
- if(path.size() == 0) throw DownloadError("no file path");
+ if(path.size() == 0) LLTHROW(DownloadError("no file path"));
std::string fileName = path[path.size() - 1].asString();
std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);
mDownloadData["path"] = filePath;
@@ -547,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
if(code != CURLE_OK) {
const char * errorString = curl_easy_strerror(code);
if(errorString != 0) {
- throw DownloadError(curl_easy_strerror(code));
+ LLTHROW(DownloadError(curl_easy_strerror(code)));
} else {
- throw DownloadError("unknown curl error");
+ LLTHROW(DownloadError("unknown curl error"));
}
} else {
; // No op.
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index a0e2c0b362..1c7629da23 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -30,23 +30,25 @@
#include "llupdateinstaller.h"
#include "lldir.h"
#include "llsd.h"
+#include "llexception.h"
#if defined(LL_WINDOWS)
#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!).
#endif
#include <boost/lexical_cast.hpp>
-
namespace {
- class RelocateError {};
-
-
+ struct RelocateError: public LLException
+ {
+ RelocateError(): LLException("llupdateinstaller: RelocateError") {}
+ };
+
std::string copy_to_temp(std::string const & path)
{
std::string scriptFile = gDirUtilp->getBaseFileName(path);
std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
- if(status != APR_SUCCESS) throw RelocateError();
+ if(status != APR_SUCCESS) LLTHROW(RelocateError());
return newPath;
}
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 788955a1b2..1665e41e70 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -32,6 +32,7 @@
#include "lltimer.h"
#include "llupdatechecker.h"
#include "llupdateinstaller.h"
+#include "llexception.h"
#include <boost/scoped_ptr.hpp>
#include <boost/weak_ptr.hpp>
@@ -190,8 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string& channel,
{
if(mIsChecking || mIsDownloading)
{
- throw LLUpdaterService::UsageError("LLUpdaterService::initialize call "
- "while updater is running.");
+ LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call "
+ "while updater is running."));
}
mChannel = channel;
@@ -222,8 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
{
if(mChannel.empty() || mVersion.empty())
{
- throw LLUpdaterService::UsageError("Set params before call to "
- "LLUpdaterService::startCheck().");
+ LLTHROW(LLUpdaterService::UsageError("Set params before call to "
+ "LLUpdaterService::startCheck()."));
}
mIsChecking = true;
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 95bbe1695c..78e8c6b290 100644
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -29,16 +29,17 @@
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include "llhasheduniqueid.h"
+#include "llexception.h"
class LLUpdaterServiceImpl;
class LLUpdaterService
{
public:
- class UsageError: public std::runtime_error
+ class UsageError: public LLException
{
public:
- UsageError(const std::string& msg) : std::runtime_error(msg) {}
+ UsageError(const std::string& msg) : LLException(msg) {}
};
// Name of the event pump through which update events will be delivered.
diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp
index 23c29e6b18..167acf6ac7 100644
--- a/indra/win_crash_logger/llcrashloggerwindows.cpp
+++ b/indra/win_crash_logger/llcrashloggerwindows.cpp
@@ -454,7 +454,7 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles()
//mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); //Not initialized.
}
-bool LLCrashLoggerWindows::mainLoop()
+bool LLCrashLoggerWindows::frame()
{
LL_INFOS() << "CrashSubmitBehavior is " << mCrashBehavior << LL_ENDL;
@@ -503,14 +503,14 @@ bool LLCrashLoggerWindows::mainLoop()
TranslateMessage(&msg);
DispatchMessage(&msg);
}
- return msg.wParam;
+ return true; // msg.wParam;
}
else
{
LL_WARNS() << "Unknown crash behavior " << mCrashBehavior << LL_ENDL;
- return 1;
+ return true; // 1;
}
- return 0;
+ return true; // 0;
}
void LLCrashLoggerWindows::updateApplication(const std::string& message)
diff --git a/indra/win_crash_logger/llcrashloggerwindows.h b/indra/win_crash_logger/llcrashloggerwindows.h
index 1812e2737e..f89b8708dc 100644
--- a/indra/win_crash_logger/llcrashloggerwindows.h
+++ b/indra/win_crash_logger/llcrashloggerwindows.h
@@ -46,7 +46,7 @@ public:
static LLCrashLoggerWindows* sInstance;
virtual bool init();
- virtual bool mainLoop();
+ virtual bool frame();
virtual void updateApplication(const std::string& message = LLStringUtil::null);
virtual bool cleanup();
virtual void gatherPlatformSpecificFiles();
diff --git a/indra/win_crash_logger/win_crash_logger.cpp b/indra/win_crash_logger/win_crash_logger.cpp
index 366edd894b..7466dbb766 100644
--- a/indra/win_crash_logger/win_crash_logger.cpp
+++ b/indra/win_crash_logger/win_crash_logger.cpp
@@ -52,7 +52,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
}
app.processingLoop();
- app.mainLoop();
+ app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
return 0;