diff options
105 files changed, 2369 insertions, 2423 deletions
@@ -346,29 +346,23 @@ b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release 32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217 704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1 -d799593b53ed733862e9a13871e318e886469377 DRTVWR-208 -e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223 288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216 e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2 -93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240 0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242 710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3 -2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209 -f7bedce18ad52283e6072814db23318907261487 DRTVWR-238 -7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210 e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243 73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4 16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release +d799593b53ed733862e9a13871e318e886469377 DRTVWR-208 +e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223 +93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240 +2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209 +f7bedce18ad52283e6072814db23318907261487 DRTVWR-238 +7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210 5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241 f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232 4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245 94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1 -4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229 -f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246 -39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247 -7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249 -f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230 -b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255 965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252 bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251 ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 @@ -377,23 +371,50 @@ ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 44e764a6ac9e672a4f3bce821a4b6a218590c374 DRTVWR-258 c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257 452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259 -9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265 9afbdc4e24cc04feacfb2b7a10b78a64f780901a DRTVWR-266 73280db02501f5ad041fc18b1eba68e73a81996c DRTVWR-267 870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3 0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release +4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229 +f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246 +39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247 +7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249 +f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230 +b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255 +9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260 84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244 083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1 -391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268 b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270 cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2 2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271 2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3 35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273 -a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272 -37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269 c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275 05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4 +e1bb1ae7d8b12faeb37933a737c199cc9b9f89cc 3.4.4-release +391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268 +a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272 +37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269 7c6dfdc1b7a2ce0d8e3a8f3ce3058547ea065c0f DRTVWR-250 +b9ff9730daa53a541925300cbd02bb14575a5705 DRTVWR-277 +af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276 +8302fefde6c8f4a64bfc7f04929f8bc85f5c6c7b DRTVWR-279 +c296133849d1f103c0e2abc41e6599daed00b67b DRTVWR-280 +40a2265058abc9fde4914c10185f916435818621 3.4.5-beta1 +5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281 +7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283 +6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2 +ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286 +2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287 +e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3 +a676b4d6c037b39fe5b8e42cf8839a9303936089 DRTVWR-289 +28fa8b944a0c1869636ab00cc400f5aa71f6fa3c DRTVWR-290 +7f09bbc28c297f14b67961be7b6575445fa160e8 DRTVWR-291 +b23419a2748483c98f3b84b630468a21c88feba5 DRTVWR-292 +1567de5700c273b583dac41b64275c223287306e 3.4.5-beta4 +1cce8447f8f574673e3f47d6fe584262e6964fe2 DRTVWR-296 +0a5d409161ef2a89b28c9a741051dd2dedc707d6 DRTVWR-297 +852b69ef0b5fe6b13b69cc2217282cc64de6afab 3.4.5-beta5 +a49c715243a36a8a380504d14cb7416b3039c956 3.4.5-release e6b8a92acffd693cd1459e4212e3dff1050acf67 DRTVWR-278 diff --git a/BuildParams b/BuildParams index c8edfeaa2f..7c77f6c186 100644 --- a/BuildParams +++ b/BuildParams @@ -21,50 +21,43 @@ email_status_this_is_os = true # Limit extent of codeticket updates to revisions after... codeticket_since = 3.3.0-release -# ======================================== -# Viewer Development -# ======================================== +################################################################ +#### Examples of how to set the viewer_channel #### +# +# To build a Release or Release candidate in build bingo: +# bingo.viewer_channel = "Second Life Release" +# +# To build a Beta for the 'Bingo' project in build bingo: +# bingo.viewer_channel = "Second Life Beta Bingo" +# +# To build a Project viewer for the 'Bingo' project in build bingo: +# bingo.viewer_channel = "Second Life Project Bingo" +# +# If left unset, viewer_channel defaults to 'Second Life Test', +# which is appropriate for individual developer builds. +# +# All Linden Lab builds (and only Linden Lab builds) +# should use a viewer_channel that begins with "Second Life" +################################################################ # Report changes since... viewer-development.show_changes_since = last_sprint # Build Settings -viewer-development_coverity.coverity_product = viewer -viewer-development_coverity.run_tests = false viewer-development.build_debug_release_separately = true # Notifications - to configure email notices, add a setting like this: # <username>_<reponame>.email = <email-address> - -# ================================================================= -# Canonical viewer integration builds - Oz Linden -# ================================================================= -integration_viewer-development.viewer_channel = "Second Life Development" -integration_viewer-development.login_channel = "Second Life Development" -integration_viewer-development.build_viewer_update_version_manager = false -integration_viewer-development.email = viewer-development-builds@lists.secondlife.com -integration_viewer-development.build_enforce_coding_policy = false -integration_viewer-development.codeticket_add_context = false - -viewer-beta.viewer_channel = "Second Life Beta Viewer" -viewer-beta.login_channel = "Second Life Beta Viewer" -viewer-beta.build_debug_release_separately = true -viewer-beta.build_viewer_update_version_manager = true -viewer-beta.codeticket_add_context = false - viewer-release.viewer_channel = "Second Life Release" -viewer-release.login_channel = "Second Life Release" viewer-release.build_debug_release_separately = true viewer-release.build_viewer_update_version_manager = true viewer-release.codeticket_add_context = false - # ======================================== # mesh-development # ======================================== mesh-development.viewer_channel = "Project Viewer - Mesh" -mesh-development.login_channel = "Project Viewer - Mesh" mesh-development.viewer_grid = aditi mesh-development.build_debug_release_separately = true mesh-development.build_CYGWIN_Debug = false @@ -74,7 +67,6 @@ mesh-development.build_viewer_update_version_manager = false # mesh-development-release-1-candidate # ======================================== mesh-development-release-1-candidate.viewer_channel = "Project Viewer - Mesh" -mesh-development-release-1-candidate.login_channel = "Project Viewer - Mesh" mesh-development-release-1-candidate.viewer_grid = agni mesh-development-release-1-candidate.build_debug_release_separately = true mesh-development-release-1-candidate.build_CYGWIN_Debug = false @@ -84,7 +76,6 @@ mesh-development-release-1-candidate.build_viewer_update_version_manager = false # mesh-development-rc # ======================================== mesh-development-rc.viewer_channel = "Project Viewer - Mesh" -mesh-development-rc.login_channel = "Project Viewer - Mesh" mesh-development-rc.viewer_grid = agni mesh-development-rc.build_debug_release_separately = true mesh-development-rc.build_CYGWIN_Debug = false @@ -94,7 +85,6 @@ mesh-development-rc.build_viewer_update_version_manager = false # mesh-asset-deprecation # ======================================== mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation" -mesh-asset-deprecation.login_channel = "Project Viewer - Mesh Asset Deprecation" mesh-asset-deprecation.viewer_grid = aditi mesh-asset-deprecation.build_debug_release_separately = true mesh-asset-deprecation.build_CYGWIN_Debug = false @@ -112,7 +102,6 @@ viewer-mesh.build_viewer_update_version_manager = false viewer-mesh.build_Debug = false viewer-mesh.build_RelWithDebInfo = false viewer-mesh.viewer_channel = "Project Viewer - Mesh" -viewer-mesh.login_channel = "Project Viewer - Mesh" viewer-mesh.viewer_grid = aditi viewer-mesh.email = shining@lists.lindenlab.com @@ -121,7 +110,6 @@ viewer-mesh.email = shining@lists.lindenlab.com # ======================================== viewer-pathfinding.viewer_channel = "Project Viewer - Pathfinding" -viewer-pathfinding.login_channel = "Project Viewer - Pathfinding" viewer-pathfinding.viewer_grid = agni viewer-pathfinding.build_debug_release_separately = true viewer-pathfinding.build_CYGWIN_Debug = false @@ -131,14 +119,12 @@ viewer-pathfinding.build_viewer_update_version_manager = false # asset delivery 2010 projects # ================================================================= viewer-asset-delivery.viewer_channel = "Second Life Development" -viewer-asset-delivery.login_channel = "Second Life Development" viewer-asset-delivery.build_viewer_update_version_manager = false viewer-asset-delivery.email = monty@lindenlab.com viewer-asset-delivery.build_server = false viewer-asset-delivery.build_server_tests = false viewer-asset-delivery-metrics.viewer_channel = "Second Life Development" -viewer-asset-delivery-metrics.login_channel = "Second Life Development" viewer-asset-delivery-metrics.build_viewer_update_version_manager = false viewer-asset-delivery-metrics.email = monty@lindenlab.com viewer-asset-delivery-metrics.build_server = false @@ -155,34 +141,29 @@ simon_viewer-dev-private.email_status_this_is_os = false # Vir # ======================================== vir-project-1.viewer_channel = "Second Life Release" -vir-project-1.login_channel = "Second Life Release" # ======================================== # THX-1138 / Runway projects # ======================================== viewer-thx1138-runway-shared.viewer_channel = "Project Viewer - THX-1138 Runway" -viewer-thx1138-runway-shared.login_channel = "Project Viewer - THX-1138 Runway" viewer-thx1138-runway-shared.viewer_grid = uma viewer-thx1138-runway-shared.build_debug_release_separately = true viewer-thx1138-runway-shared.build_CYGWIN_Debug = false viewer-thx1138-runway-shared.build_viewer_update_version_manager = false viewer-thx1138.viewer_channel = "Project Viewer - THX-1138" -viewer-thx1138.login_channel = "Project Viewer - THX-1138" viewer-thx1138.viewer_grid = uma viewer-thx1138.build_debug_release_separately = true viewer-thx1138.build_CYGWIN_Debug = false viewer-thx1138.build_viewer_update_version_manager = false runway-merge.viewer_channel = "Project Viewer - Runway Merge" -runway-merge.login_channel = "Project Viewer - Runway Merge" runway-merge.viewer_grid = agni runway-merge.build_debug_release_separately = true runway-merge.build_CYGWIN_Debug = false runway-merge.build_viewer_update_version_manager = false runway.viewer_channel = "Project Viewer - Runway" -runway.login_channel = "Project Viewer - Runway" runway.viewer_grid = agni runway.build_debug_release_separately = true runway.build_CYGWIN_Debug = false diff --git a/autobuild.xml b/autobuild.xml index 017427278e..11c2da52dc 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1463,6 +1463,30 @@ </map> </map> </map> + <key>nvapi</key> + <map> + <key>license</key> + <string>NVAPI</string> + <key>license_file</key> + <string>LICENSES/NVAPI_SDK_License_Agreement.pdf</string> + <key>name</key> + <string>nvapi</string> + <key>platforms</key> + <map> + <key>windows</key> + <map> + <key>archive</key> + <map> + <key>hash</key> + <string>baf519d36dffe4e4a59471450e391d01</string> + <key>url</key> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-nvapi/rev/267102/arch/CYGWIN/installer/nvapi-304-windows-20121116.tar.bz2</string> + </map> + <key>name</key> + <string>windows</string> + </map> + </map> + </map> <key>ogg-vorbis</key> <map> <key>license</key> @@ -71,7 +71,6 @@ pre_build() -DPACKAGE:BOOL=ON \ -DRELEASE_CRASH_REPORTING:BOOL=ON \ -DVIEWER_CHANNEL:STRING="\"$viewer_channel\"" \ - -DVIEWER_LOGIN_CHANNEL:STRING="\"$viewer_login_channel\"" \ -DGRID:STRING="\"$viewer_grid\"" \ -DLL_TESTS:BOOL="$run_tests" \ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url @@ -159,21 +158,6 @@ fi # Check to see if we're skipping the platform eval '$build_'"$arch" || pass -# Run the version number update script -# File no longer exists in code-sep branch, so let's make sure it exists in order to use it. -if test -f scripts/update_version_files.py ; then - begin_section UpdateVer - eval $(python scripts/update_version_files.py \ - --channel="$viewer_channel" \ - --server_channel="$server_channel" \ - --revision=$revision \ - --verbose \ - | sed -n -e "s,Setting viewer channel/version: '\([^']*\)' / '\([^']*\)',VIEWER_CHANNEL='\1';VIEWER_VERSION='\2',p")\ - || fail update_version_files.py - echo "{\"Type\":\"viewer\",\"Version\":\"${VIEWER_VERSION}\"}" > summary.json - end_section UpdateVer -fi - if [ -z "$AUTOBUILD" ] then export autobuild_dir="$here/../../../autobuild/bin/" diff --git a/doc/contributions.txt b/doc/contributions.txt index f53d9f5cfd..e86ef11a72 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -895,6 +895,7 @@ NickyD MAINT-873 Nicky Dasmijn VWR-29228 + MAINT-873 Nicky Perian OPEN-1 STORM-1087 @@ -1250,6 +1251,7 @@ Whimsy Winx Whirly Fizzle STORM-1895 MAINT-873 + STORM-1930 Whoops Babii VWR-631 VWR-1640 diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 45608de674..ae69d0b843 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -3,14 +3,8 @@ # cmake_minimum_required should appear before any # other commands to guarantee full compatibility # with the version specified - -# The "cmake -E touch" command was released with 2.4.8. -cmake_minimum_required(VERSION 2.4.8 FATAL_ERROR) - -# This makes cmake 2.6 not complain about version 2.4 compatibility. -if (COMMAND cmake_policy) - cmake_policy(SET CMP0003 OLD) -endif (COMMAND cmake_policy) +## prior to 2.8, the add_custom_target commands used in setting the version did not work correctly +cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING "The root project/makefile/solution name. Defaults to SecondLife.") @@ -19,13 +13,7 @@ project(${ROOT_PROJECT_NAME}) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") include(Variables) - -if (DARWIN) - # 2.6.4 fixes a Mac bug in get_target_property(... "SLPlugin" LOCATION): - # before that version it returns "pathname/SLPlugin", whereas the correct - # answer is "pathname/SLPlugin.app/Contents/MacOS/SLPlugin". - cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR) -endif (DARWIN) +include(BuildVersion) if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING @@ -82,8 +70,7 @@ if (VIEWER) if (LINUX) add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) - add_subdirectory(${VIEWER_PREFIX}linux_updater) - add_dependencies(viewer linux-crash-logger-strip-target linux-updater) + add_dependencies(viewer linux-crash-logger-strip-target) elseif (DARWIN) add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) add_dependencies(viewer mac-crash-logger) diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake index 60a519c9af..c494355746 100644 --- a/indra/cmake/BuildVersion.cmake +++ b/indra/cmake/BuildVersion.cmake @@ -1,18 +1,48 @@ # -*- cmake -*- +# Construct the viewer version number based on the indra/VIEWER_VERSION file -include(Python) +if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/newview/ + set(VIEWER_VERSION_BASE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/newview/VIEWER_VERSION.txt") -macro (build_version _target) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${SCRIPTS_DIR}/build_version.py - llversion${_target}.h ${LLCOMMON_INCLUDE_DIRS} - OUTPUT_VARIABLE ${_target}_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + if ( EXISTS ${VIEWER_VERSION_BASE_FILE} ) + file(STRINGS ${VIEWER_VERSION_BASE_FILE} VIEWER_SHORT_VERSION REGEX "^[0-9]+\\.[0-9]+\\.[0-9]+") + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" VIEWER_VERSION_MAJOR ${VIEWER_SHORT_VERSION}) + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" VIEWER_VERSION_MINOR ${VIEWER_SHORT_VERSION}) + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" VIEWER_VERSION_PATCH ${VIEWER_SHORT_VERSION}) - if (${_target}_VERSION) - message(STATUS "Version of ${_target} is ${${_target}_VERSION}") - else (${_target}_VERSION) - message(SEND_ERROR "Could not determine ${_target} version") - endif (${_target}_VERSION) -endmacro (build_version) + if (DEFINED ENV{revision}) + set(VIEWER_VERSION_REVISION $ENV{revision}) + message("Revision (from environment): ${VIEWER_VERSION_REVISION}") + + else (DEFINED ENV{revision}) + find_program(MERCURIAL hg) + if (DEFINED MERCURIAL) + execute_process( + COMMAND ${MERCURIAL} parents --template "{rev}" + OUTPUT_VARIABLE VIEWER_VERSION_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if (DEFINED VIEWER_VERSION_REVISION) + message("Revision (from hg) ${VIEWER_VERSION_REVISION}") + else (DEFINED VIEWER_VERSION_REVISION) + set(VIEWER_VERSION_REVISION 0 ) + message("Revision not set, repository not found, using ${VIEWER_VERSION_REVISION}") + endif (DEFINED VIEWER_VERSION_REVISION) + else (DEFINED MERCURIAL) + set(VIEWER_VERSION_REVISION 0) + message("Revision not set, 'hg' not found (${MERCURIAL}), using ${VIEWER_VERSION_REVISION}") + endif (DEFINED MERCURIAL) + endif (DEFINED ENV{revision}) + message("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} ) + + set(VIEWER_CHANNEL_VERSION_DEFINES + "LL_VIEWER_CHANNEL=\"${VIEWER_CHANNEL}\"" + "LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}" + "LL_VIEWER_VERSION_MINOR=${VIEWER_VERSION_MINOR}" + "LL_VIEWER_VERSION_PATCH=${VIEWER_VERSION_PATCH}" + "LL_VIEWER_VERSION_BUILD=${VIEWER_VERSION_REVISION}" + ) +endif (NOT DEFINED VIEWER_SHORT_VERSION) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 569034a6fb..4f567988b7 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -12,7 +12,6 @@ set(cmake_SOURCE_FILES Audio.cmake BerkeleyDB.cmake Boost.cmake - BuildVersion.cmake CARes.cmake CURL.cmake CMakeCopyIfDifferent.cmake diff --git a/indra/cmake/NVAPI.cmake b/indra/cmake/NVAPI.cmake new file mode 100644 index 0000000000..105f442a30 --- /dev/null +++ b/indra/cmake/NVAPI.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- +include(Prebuilt) + +set(NVAPI ON CACHE BOOL "Use NVAPI.") + +if (NVAPI) + if (WINDOWS) + use_prebuilt_binary(nvapi) + set(NVAPI_LIBRARY nvapi) + else (WINDOWS) + set(NVAPI_LIBRARY "") + endif (WINDOWS) +else (NVAPI) + set(NVAPI_LIBRARY "") +endif (NVAPI) + diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 4b459f1a48..296da81e6c 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -141,8 +141,7 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(GRID agni CACHE STRING "Target Grid") set(VIEWER ON CACHE BOOL "Build Second Life viewer.") -set(VIEWER_CHANNEL "LindenDeveloper" CACHE STRING "Viewer Channel Name") -set(VIEWER_LOGIN_CHANNEL ${VIEWER_CHANNEL} CACHE STRING "Fake login channel for A/B Testing") +set(VIEWER_CHANNEL "Second Life Test" CACHE STRING "Viewer Channel Name") if (XCODE_VERSION GREATER 4.2) set(ENABLE_SIGNING OFF CACHE BOOL "Enable signing the viewer") diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index 0f6a8b8a1d..3ec98d8670 100644 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -1 +1,3 @@ Wed Nov 7 00:25:19 UTC 2012 + + diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 97cc31bba0..9cb830a2db 100644 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -84,30 +84,8 @@ def get_default_platform(dummy): 'darwin':'darwin' }[sys.platform] -def get_default_version(srctree): - # look up llversion.h and parse out the version info - paths = [os.path.join(srctree, x, 'llversionviewer.h') for x in ['llcommon', '../llcommon', '../../indra/llcommon.h']] - for p in paths: - if os.path.exists(p): - contents = open(p, 'r').read() - major = re.search("LL_VERSION_MAJOR\s=\s([0-9]+)", contents).group(1) - minor = re.search("LL_VERSION_MINOR\s=\s([0-9]+)", contents).group(1) - patch = re.search("LL_VERSION_PATCH\s=\s([0-9]+)", contents).group(1) - build = re.search("LL_VERSION_BUILD\s=\s([0-9]+)", contents).group(1) - return major, minor, patch, build - -def get_channel(srctree): - # look up llversionserver.h and parse out the version info - paths = [os.path.join(srctree, x, 'llversionviewer.h') for x in ['llcommon', '../llcommon', '../../indra/llcommon.h']] - for p in paths: - if os.path.exists(p): - contents = open(p, 'r').read() - channel = re.search("LL_CHANNEL\s=\s\"(.+)\";\s*$", contents, flags = re.M).group(1) - return channel - - DEFAULT_SRCTREE = os.path.dirname(sys.argv[0]) -DEFAULT_CHANNEL = 'Second Life Release' +RELEASE_CHANNEL = 'Second Life Release' ARGUMENTS=[ dict(name='actions', @@ -140,10 +118,7 @@ ARGUMENTS=[ default=""), dict(name='channel', description="""The channel to use for updates, packaging, settings name, etc.""", - default=get_channel), - dict(name='login_channel', - description="""The channel to use for login handshake/updates only.""", - default=None), + default='CHANNEL UNSET'), dict(name='installer_name', description=""" The name of the file that the installer should be packaged up into. Only used on Linux at the moment.""", @@ -164,10 +139,8 @@ ARGUMENTS=[ contain the name of the final package in a form suitable for use by a .bat file.""", default=None), - dict(name='version', - description="""This specifies the version of Second Life that is - being packaged up.""", - default=get_default_version), + dict(name='versionfile', + description="""The name of a file containing the full version number."""), dict(name='signature', description="""This specifies an identity to sign the viewer with, if any. If no value is supplied, the default signature will be used, if any. Currently @@ -232,9 +205,14 @@ def main(): args[arg['name']] = default # fix up version - if isinstance(args.get('version'), str): - args['version'] = args['version'].split('.') - + if isinstance(args.get('versionfile'), str): + try: # read in the version string + vf = open(args['versionfile'], 'r') + args['version'] = vf.read().strip().split('.') + except: + print "Unable to read versionfile '%s'" % args['versionfile'] + raise + # default and agni are default if args['grid'] in ['default', 'agni']: args['grid'] = '' @@ -291,7 +269,7 @@ class LLManifest(object): def default_grid(self): return self.args.get('grid', None) == '' def default_channel(self): - return self.args.get('channel', None) == DEFAULT_CHANNEL + return self.args.get('channel', None) == RELEASE_CHANNEL def construct(self): """ Meant to be overriden by LLManifest implementors with code that diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt deleted file mode 100644 index 4377a6333c..0000000000 --- a/indra/linux_updater/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -*- cmake -*- - -project(linux_updater) - -include(00-Common) -include(CURL) -include(CARes) -include(OpenSSL) -include(UI) -include(LLCommon) -include(LLVFS) -include(LLXML) -include(LLUI) -include(Linking) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLVFS_INCLUDE_DIRS} - ${LLXML_INCLUDE_DIRS} - ${LLUI_INCLUDE_DIRS} - ${CURL_INCLUDE_DIRS} - ${CARES_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIRS} - ${UI_INCLUDE_DIRS} - ) - -set(linux_updater_SOURCE_FILES linux_updater.cpp) - -set(linux_updater_HEADER_FILES CMakeLists.txt) - -set_source_files_properties(${linux_updater_HEADER_FILES} - PROPERTIES HEADER_FILES_ONLY TRUE) - -list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES}) - -add_executable(linux-updater ${linux_updater_SOURCE_FILES}) - -target_link_libraries(linux-updater - ${CURL_LIBRARIES} - ${CARES_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${CRYPTO_LIBRARIES} - ${UI_LIBRARIES} - ${LLXML_LIBRARIES} - ${LLUI_LIBRARIES} - ${LLVFS_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ) - -add_custom_target(linux-updater-target ALL - DEPENDS linux-updater) diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp deleted file mode 100644 index 991dfd9dce..0000000000 --- a/indra/linux_updater/linux_updater.cpp +++ /dev/null @@ -1,926 +0,0 @@ -/** - * @file linux_updater.cpp - * @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden - * @brief Viewer update program for unix platforms that support GTK+ - * - * $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$ - */ - -#include <unistd.h> -#include <signal.h> -#include <errno.h> - -#include "linden_common.h" -#include "llerrorcontrol.h" -#include "llfile.h" -#include "lldir.h" -#include "lldiriterator.h" - -/*==========================================================================*| -// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy. -// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable. -#include "llxmlnode.h" -#include "lltrans.h" -|*==========================================================================*/ - -static class LLTrans -{ -public: - LLTrans(); - static std::string getString(const std::string& key); - -private: - std::string _getString(const std::string& key) const; - - typedef std::map<std::string, std::string> MessageMap; - MessageMap mMessages; -} sLLTransInstance; - -#include <curl/curl.h> -#include <map> -#include <boost/foreach.hpp> - -extern "C" { -#include <gtk/gtk.h> -} - -const guint UPDATE_PROGRESS_TIMEOUT = 100; -const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000; -const guint ROTATE_IMAGE_TIMEOUT = 8000; - -typedef struct _updater_app_state { - std::string app_name; - std::string url; - std::string file; - std::string image_dir; - std::string dest_dir; - std::string strings_dirs; - std::string strings_file; - - LLDirIterator *image_dir_iter; - - GtkWidget *window; - GtkWidget *progress_bar; - GtkWidget *image; - - double progress_value; - bool activity_mode; - - guint image_rotation_timeout_id; - guint progress_update_timeout_id; - guint update_progress_text_timeout_id; - - bool failure; -} UpdaterAppState; - -// List of entries from strings.xml to always replace -static std::set<std::string> default_trans_args; -void init_default_trans_args() -{ - default_trans_args.insert("SECOND_LIFE"); // World - default_trans_args.insert("APP_NAME"); - default_trans_args.insert("SECOND_LIFE_GRID"); - default_trans_args.insert("SUPPORT_SITE"); -} - -bool translate_init(std::string comma_delim_path_list, - std::string base_xml_name) -{ - return true; -/*==========================================================================*| - init_default_trans_args(); - - // extract paths string vector from comma-delimited flat string - std::vector<std::string> paths; - LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ',' - - for(std::vector<std::string>::iterator it = paths.begin(), end_it = paths.end(); - it != end_it; - ++it) - { - (*it) = gDirUtilp->findSkinnedFilename(*it, base_xml_name); - } - - // suck the translation xml files into memory - LLXMLNodePtr root; - bool success = LLXMLNode::getLayeredXMLNode(root, paths); - if (!success) - { - // couldn't load string table XML - return false; - } - else - { - // get those strings out of the XML - LLTrans::parseStrings(root, default_trans_args); - return true; - } -|*==========================================================================*/ -} - - -void updater_app_ui_init(void); -void updater_app_quit(UpdaterAppState *app_state); -void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state); -std::string next_image_filename(std::string& image_path, LLDirIterator& iter); -void display_error(GtkWidget *parent, std::string title, std::string message); -BOOL install_package(std::string package_file, std::string destination); -BOOL spawn_viewer(UpdaterAppState *app_state); - -extern "C" { - void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state); - gpointer worker_thread_cb(gpointer *data); - int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow); - gboolean rotate_image_cb(gpointer data); - gboolean progress_update_timeout(gpointer data); - gboolean update_progress_text_timeout(gpointer data); -} - -void updater_app_ui_init(UpdaterAppState *app_state) -{ - GtkWidget *vbox; - GtkWidget *summary_label; - GtkWidget *description_label; - GtkWidget *frame; - - llassert(app_state != NULL); - - // set up window and main container - std::string window_title = LLTrans::getString("UpdaterWindowTitle"); - app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(app_state->window), - window_title.c_str()); - gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE); - gtk_window_set_position(GTK_WINDOW(app_state->window), - GTK_WIN_POS_CENTER_ALWAYS); - - gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12); - g_signal_connect(G_OBJECT(app_state->window), "delete-event", - G_CALLBACK(on_window_closed), app_state); - - vbox = gtk_vbox_new(FALSE, 6); - gtk_container_add(GTK_CONTAINER(app_state->window), vbox); - - // set top label - std::ostringstream label_ostr; - label_ostr << "<big><b>" - << LLTrans::getString("UpdaterNowUpdating") - << "</b></big>"; - - summary_label = gtk_label_new(NULL); - gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE); - gtk_label_set_markup(GTK_LABEL(summary_label), - label_ostr.str().c_str()); - gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0); - - // create the description label - description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str()); - gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE); - gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0); - - // If an image path has been set, load the background images - if (!app_state->image_dir.empty()) { - frame = gtk_frame_new(NULL); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - - // load the first image - app_state->image = gtk_image_new_from_file - (next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str()); - gtk_widget_set_size_request(app_state->image, 340, 310); - gtk_container_add(GTK_CONTAINER(frame), app_state->image); - - // rotate the images every 5 seconds - app_state->image_rotation_timeout_id = g_timeout_add - (ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state); - } - - // set up progress bar, and update it roughly every 1/10 of a second - app_state->progress_bar = gtk_progress_bar_new(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), - LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str()); - gtk_box_pack_start(GTK_BOX(vbox), - app_state->progress_bar, FALSE, TRUE, 0); - app_state->progress_update_timeout_id = g_timeout_add - (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state); - app_state->update_progress_text_timeout_id = g_timeout_add - (UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state); - - gtk_widget_show_all(app_state->window); -} - -gboolean rotate_image_cb(gpointer data) -{ - UpdaterAppState *app_state; - std::string filename; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter); - - gdk_threads_enter(); - gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str()); - gdk_threads_leave(); - - return TRUE; -} - -std::string next_image_filename(std::string& image_path, LLDirIterator& iter) -{ - std::string image_filename; - iter.next(image_filename); - return gDirUtilp->add(image_path, image_filename); -} - -void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - updater_app_quit(app_state); -} - -void updater_app_quit(UpdaterAppState *app_state) -{ - if (app_state != NULL) - { - g_source_remove(app_state->progress_update_timeout_id); - - if (!app_state->image_dir.empty()) - { - g_source_remove(app_state->image_rotation_timeout_id); - } - } - - gtk_main_quit(); -} - -void display_error(GtkWidget *parent, std::string title, std::string message) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new(GTK_WINDOW(parent), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", message.c_str()); - gtk_window_set_title(GTK_WINDOW(dialog), title.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - -gpointer worker_thread_cb(gpointer data) -{ - UpdaterAppState *app_state; - CURL *curl; - CURLcode result; - FILE *package_file; - GError *error = NULL; - int fd; - - //g_return_val_if_fail (data != NULL, NULL); - app_state = (UpdaterAppState *) data; - - try { - - if(!app_state->url.empty()) - { - char* tmp_local_filename = NULL; - // create temporary file to store the package. - fd = g_file_open_tmp - ("secondlife-update-XXXXXX", &tmp_local_filename, &error); - if (error != NULL) - { - llerrs << "Unable to create temporary file: " - << error->message - << llendl; - - g_error_free(error); - throw 0; - } - - if(tmp_local_filename != NULL) - { - app_state->file = tmp_local_filename; - g_free(tmp_local_filename); - } - - package_file = fdopen(fd, "wb"); - if (package_file == NULL) - { - llerrs << "Failed to create temporary file: " - << app_state->file.c_str() - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - - // initialize curl and start downloading the package - llinfos << "Downloading package: " << app_state->url << llendl; - - curl = curl_easy_init(); - if (curl == NULL) - { - llerrs << "Failed to initialize libcurl" << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - - curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str()); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, - &download_progress_cb); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state); - - result = curl_easy_perform(curl); - fclose(package_file); - curl_easy_cleanup(curl); - - if (result) - { - llerrs << "Failed to download update: " - << app_state->url - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailDownloadTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - - throw 0; - } - } - - // now pulse the progres bar back and forth while the package is - // being unpacked - gdk_threads_enter(); - std::string installing_msg = LLTrans::getString("UpdaterNowInstalling"); - gtk_progress_bar_set_text( - GTK_PROGRESS_BAR(app_state->progress_bar), - installing_msg.c_str()); - app_state->activity_mode = TRUE; - gdk_threads_leave(); - - // *TODO: if the destination is not writable, terminate this - // thread and show file chooser? - if (!install_package(app_state->file.c_str(), app_state->dest_dir)) - { - llwarns << "Failed to install package to destination: " - << app_state->dest_dir - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailInstallTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - //"Failed to update " + app_state->app_name, - gdk_threads_leave(); - throw 0; - } - - // try to spawn the new viewer - if (!spawn_viewer(app_state)) - { - llwarns << "Viewer was not installed properly in : " - << app_state->dest_dir - << llendl; - - gdk_threads_enter(); - display_error(app_state->window, - LLTrans::getString("UpdaterFailStartTitle"), - LLTrans::getString("UpdaterFailUpdateDescriptive")); - gdk_threads_leave(); - throw 0; - } - } - catch (...) - { - app_state->failure = TRUE; - } - - gdk_threads_enter(); - updater_app_quit(app_state); - gdk_threads_leave(); - - return NULL; -} - - -gboolean less_anal_gspawnsync(gchar **argv, - gchar **stderr_output, - gint *child_exit_status, - GError **spawn_error) -{ - // store current SIGCHLD handler if there is one, replace with default - // handler to make glib happy - struct sigaction sigchld_backup; - struct sigaction sigchld_appease_glib; - sigchld_appease_glib.sa_handler = SIG_DFL; - sigemptyset(&sigchld_appease_glib.sa_mask); - sigchld_appease_glib.sa_flags = 0; - sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); - - gboolean rtn = g_spawn_sync(NULL, - argv, - NULL, - (GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL), - NULL, - NULL, - NULL, - stderr_output, - child_exit_status, - spawn_error); - - // restore SIGCHLD handler - sigaction(SIGCHLD, &sigchld_backup, NULL); - - return rtn; -} - - -// perform a rename, or perform a (prompted) root rename if that fails -int -rename_with_sudo_fallback(const std::string& filename, const std::string& newname) -{ - int rtncode = ::rename(filename.c_str(), newname.c_str()); - lldebugs << "rename result is: " << rtncode << " / " << errno << llendl; - if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno)) - { - llinfos << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << llendl; - // failed due to permissions, try again as a gksudo or kdesu mv wrapper hack - char *sudo_cmd = NULL; - sudo_cmd = g_find_program_in_path("gksudo"); - if (!sudo_cmd) - { - sudo_cmd = g_find_program_in_path("kdesu"); - } - if (sudo_cmd) - { - char *mv_cmd = NULL; - mv_cmd = g_find_program_in_path("mv"); - if (mv_cmd) - { - char *src_string_copy = g_strdup(filename.c_str()); - char *dst_string_copy = g_strdup(newname.c_str()); - char* argv[] = - { - sudo_cmd, - mv_cmd, - src_string_copy, - dst_string_copy, - NULL - }; - - gchar *stderr_output = NULL; - gint child_exit_status = 0; - GError *spawn_error = NULL; - if (!less_anal_gspawnsync(argv, &stderr_output, - &child_exit_status, &spawn_error)) - { - llwarns << "Failed to spawn child process: " - << spawn_error->message - << llendl; - } - else if (child_exit_status) - { - llwarns << "mv command failed: " - << (stderr_output ? stderr_output : "(no reason given)") - << llendl; - } - else - { - // everything looks good, clear the error code - rtncode = 0; - } - - g_free(src_string_copy); - g_free(dst_string_copy); - if (spawn_error) g_error_free(spawn_error); - } - } - } - return rtncode; -} - -gboolean install_package(std::string package_file, std::string destination) -{ - char *tar_cmd = NULL; - std::ostringstream command; - - // Find the absolute path to the 'tar' command. - tar_cmd = g_find_program_in_path("tar"); - if (!tar_cmd) - { - llerrs << "`tar' was not found in $PATH" << llendl; - return FALSE; - } - llinfos << "Found tar command: " << tar_cmd << llendl; - - // Unpack the tarball in a temporary place first, then move it to - // its final destination - std::string tmp_dest_dir = gDirUtilp->getTempFilename(); - if (LLFile::mkdir(tmp_dest_dir, 0744)) - { - llerrs << "Failed to create directory: " - << destination - << llendl; - - return FALSE; - } - - char *package_file_string_copy = g_strdup(package_file.c_str()); - char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str()); - gchar *argv[8] = { - tar_cmd, - const_cast<gchar*>("--strip"), const_cast<gchar*>("1"), - const_cast<gchar*>("-xjf"), - package_file_string_copy, - const_cast<gchar*>("-C"), tmp_dest_dir_string_copy, - NULL, - }; - - llinfos << "Untarring package: " << package_file << llendl; - - // store current SIGCHLD handler if there is one, replace with default - // handler to make glib happy - struct sigaction sigchld_backup; - struct sigaction sigchld_appease_glib; - sigchld_appease_glib.sa_handler = SIG_DFL; - sigemptyset(&sigchld_appease_glib.sa_mask); - sigchld_appease_glib.sa_flags = 0; - sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup); - - gchar *stderr_output = NULL; - gint child_exit_status = 0; - GError *untar_error = NULL; - if (!less_anal_gspawnsync(argv, &stderr_output, - &child_exit_status, &untar_error)) - { - llwarns << "Failed to spawn child process: " - << untar_error->message - << llendl; - return FALSE; - } - - if (child_exit_status) - { - llwarns << "Untar command failed: " - << (stderr_output ? stderr_output : "(no reason given)") - << llendl; - return FALSE; - } - - g_free(tar_cmd); - g_free(package_file_string_copy); - g_free(tmp_dest_dir_string_copy); - g_free(stderr_output); - if (untar_error) g_error_free(untar_error); - - // move the existing package out of the way if it exists - if (gDirUtilp->fileExists(destination)) - { - std::string backup_dir = destination + ".backup"; - int oldcounter = 1; - while (gDirUtilp->fileExists(backup_dir)) - { - // find a foo.backup.N folder name that isn't taken yet - backup_dir = destination + ".backup." + llformat("%d", oldcounter); - ++oldcounter; - } - - if (rename_with_sudo_fallback(destination, backup_dir)) - { - llwarns << "Failed to move directory: '" - << destination << "' -> '" << backup_dir - << llendl; - return FALSE; - } - } - - // The package has been unpacked in a staging directory, now we just - // need to move it to its destination. - if (rename_with_sudo_fallback(tmp_dest_dir, destination)) - { - llwarns << "Failed to move installation to the destination: " - << destination - << llendl; - return FALSE; - } - - // \0/ Success! - return TRUE; -} - -gboolean progress_update_timeout(gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - - app_state = (UpdaterAppState *) data; - - gdk_threads_enter(); - if (app_state->activity_mode) - { - gtk_progress_bar_pulse - (GTK_PROGRESS_BAR(app_state->progress_bar)); - } - else - { - gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar), - app_state->progress_value); - } - gdk_threads_leave(); - - return TRUE; -} - -gboolean update_progress_text_timeout(gpointer data) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - if (app_state->activity_mode == TRUE) - { - // We no longer need this timeout, it will be removed. - return FALSE; - } - - if (!app_state->progress_value) - { - return TRUE; - } - - std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value); - - gdk_threads_enter(); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), - progress_text.c_str()); - gdk_threads_leave(); - - return TRUE; -} - -int download_progress_cb(gpointer data, - double t, - double d, - double utotal, - double ulnow) -{ - UpdaterAppState *app_state; - - llassert(data != NULL); - app_state = (UpdaterAppState *) data; - - if (t <= 0.0) - { - app_state->progress_value = 0; - } - else - { - app_state->progress_value = d * 100.0 / t; - } - return 0; -} - -BOOL spawn_viewer(UpdaterAppState *app_state) -{ - llassert(app_state != NULL); - - std::string cmd = app_state->dest_dir + "/secondlife"; - GError *error = NULL; - - // We want to spawn the Viewer on the same display as the updater app - gboolean success = gdk_spawn_command_line_on_screen - (gtk_widget_get_screen(app_state->window), cmd.c_str(), &error); - - if (!success) - { - llwarns << "Failed to launch viewer: " << error->message - << llendl; - } - - if (error) g_error_free(error); - - return success; -} - -void show_usage_and_exit() -{ - std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE" - << "[--image-dir PATH]" - << std::endl; - exit(1); -} - -void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state) -{ - int i; - - for (i = 1; i < argc; i++) - { - if ((!strcmp(argv[i], "--url")) && (++i < argc)) - { - app_state->url = argv[i]; - } - else if ((!strcmp(argv[i], "--file")) && (++i < argc)) - { - app_state->file = argv[i]; - } - else if ((!strcmp(argv[i], "--name")) && (++i < argc)) - { - app_state->app_name = argv[i]; - } - else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc)) - { - app_state->image_dir = argv[i]; - app_state->image_dir_iter = new LLDirIterator(argv[i], "*.jpg"); - } - else if ((!strcmp(argv[i], "--dest")) && (++i < argc)) - { - app_state->dest_dir = argv[i]; - } - else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc)) - { - app_state->strings_dirs = argv[i]; - } - else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc)) - { - app_state->strings_file = argv[i]; - } - else - { - // show usage, an invalid option was given. - show_usage_and_exit(); - } - } - - if (app_state->app_name.empty() - || (app_state->url.empty() && app_state->file.empty()) - || app_state->dest_dir.empty()) - { - show_usage_and_exit(); - } - - app_state->progress_value = 0.0; - app_state->activity_mode = FALSE; - app_state->failure = FALSE; - - translate_init(app_state->strings_dirs, app_state->strings_file); -} - -int main(int argc, char **argv) -{ - UpdaterAppState* app_state = new UpdaterAppState; - GThread *worker_thread; - - parse_args_and_init(argc, argv, app_state); - - // Initialize logger, and rename old log file - gDirUtilp->initAppDirs("SecondLife"); - LLError::initForApplication - (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - std::string old_log_file = gDirUtilp->getExpandedFilename - (LL_PATH_LOGS, "updater.log.old"); - std::string log_file = - gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log"); - LLFile::rename(log_file, old_log_file); - LLError::logToFile(log_file); - - // initialize gthreads and gtk+ - if (!g_thread_supported()) - { - g_thread_init(NULL); - gdk_threads_init(); - } - - gtk_init(&argc, &argv); - - // create UI - updater_app_ui_init(app_state); - - //llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl; - - // create download thread - worker_thread = g_thread_create - (GThreadFunc(worker_thread_cb), app_state, FALSE, NULL); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - // Delete the file only if created from url download. - if(!app_state->url.empty() && !app_state->file.empty()) - { - if (gDirUtilp->fileExists(app_state->file)) - { - LLFile::remove(app_state->file); - } - } - - bool success = !app_state->failure; - delete app_state->image_dir_iter; - delete app_state; - return success ? 0 : 1; -} - -/***************************************************************************** -* Dummy LLTrans implementation (IQA-490) -*****************************************************************************/ -static LLTrans sStaticStrings; - -// lookup -std::string LLTrans::_getString(const std::string& key) const -{ - MessageMap::const_iterator found = mMessages.find(key); - if (found != mMessages.end()) - { - return found->second; - } - LL_WARNS("linux_updater") << "No message for key '" << key - << "' -- add to LLTrans::LLTrans() in linux_updater.cpp" - << LL_ENDL; - return key; -} - -// static lookup -std::string LLTrans::getString(const std::string& key) -{ - return sLLTransInstance._getString(key); -} - -// initialization -LLTrans::LLTrans() -{ - typedef std::pair<const char*, const char*> Pair; - static const Pair data[] = - { - Pair("UpdaterFailDownloadTitle", - "Failed to download update"), - Pair("UpdaterFailInstallTitle", - "Failed to install update"), - Pair("UpdaterFailStartTitle", - "Failed to start viewer"), - Pair("UpdaterFailUpdateDescriptive", - "An error occurred while updating Second Life. " - "Please download the latest version from www.secondlife.com."), - Pair("UpdaterNowInstalling", - "Installing Second Life..."), - Pair("UpdaterNowUpdating", - "Now updating Second Life..."), - Pair("UpdaterProgressBarText", - "Downloading update"), - Pair("UpdaterProgressBarTextWithEllipses", - "Downloading update..."), - Pair("UpdaterUpdatingDescriptive", - "Your Second Life Viewer is being updated to the latest release. " - "This may take some time, so please be patient."), - Pair("UpdaterWindowTitle", - "Second Life Update") - }; - - BOOST_FOREACH(Pair pair, data) - { - mMessages[pair.first] = pair.second; - } -} diff --git a/indra/llcharacter/llbvhconsts.h b/indra/llcharacter/llbvhconsts.h index d363a6e595..b06c279b8f 100644 --- a/indra/llcharacter/llbvhconsts.h +++ b/indra/llcharacter/llbvhconsts.h @@ -27,7 +27,7 @@ #ifndef LL_LLBVHCONSTS_H #define LL_LLBVHCONSTS_H -const F32 MAX_ANIM_DURATION = 30.f; +const F32 MAX_ANIM_DURATION = 60.f; typedef enum e_constraint_type { diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index 829dda9993..e9fb91ad73 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -42,6 +42,7 @@ const U32 MAX_MOTION_INSTANCES = 32; //----------------------------------------------------------------------------- // Constants and statics //----------------------------------------------------------------------------- +F32 LLMotionController::sCurrentTimeFactor = 1.f; LLMotionRegistry LLMotionController::sRegistry; //----------------------------------------------------------------------------- @@ -125,7 +126,7 @@ LLMotion *LLMotionRegistry::createMotion( const LLUUID &id ) // Class Constructor //----------------------------------------------------------------------------- LLMotionController::LLMotionController() - : mTimeFactor(1.f), + : mTimeFactor(sCurrentTimeFactor), mCharacter(NULL), mAnimTime(0.f), mPrevTimerElapsed(0.f), diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index b996f708d2..52eaf557b1 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -168,6 +168,9 @@ public: const LLFrameTimer& getFrameTimer() { return mTimer; } + static F32 getCurrentTimeFactor() { return sCurrentTimeFactor; }; + static void setCurrentTimeFactor(F32 factor) { sCurrentTimeFactor = factor; }; + protected: // internal operations act on motion instances directly // as there can be duplicate motions per id during blending overlap @@ -187,7 +190,8 @@ protected: void deactivateStoppedMotions(); protected: - F32 mTimeFactor; + F32 mTimeFactor; // 1.f for normal speed + static F32 sCurrentTimeFactor; // Value to use for initialization static LLMotionRegistry sRegistry; LLPoseBlender mPoseBlender; diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5cce8ff2c4..f3afd9c1a9 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -246,7 +246,6 @@ set(llcommon_HEADER_FILES lluuid.h lluuidhashmap.h llversionserver.h - llversionviewer.h llworkerthread.h ll_template_cast.h metaclass.h diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index c96f2191f3..57a6de9060 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -80,6 +80,7 @@ using namespace llsd; # include <sys/sysinfo.h> # include <stdexcept> const char MEMINFO_FILE[] = "/proc/meminfo"; +# include <gnu/libc-version.h> #elif LL_SOLARIS # include <stdio.h> # include <unistd.h> @@ -175,8 +176,41 @@ bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number) } #endif // LL_WINDOWS +// Wrap boost::regex_match() with a function that doesn't throw. +template <typename S, typename M, typename R> +static bool regex_match_no_exc(const S& string, M& match, const R& regex) +{ + try + { + return boost::regex_match(string, match, regex); + } + catch (const std::runtime_error& e) + { + LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': " + << e.what() << ":\n'" << string << "'" << LL_ENDL; + return false; + } +} + +// Wrap boost::regex_search() with a function that doesn't throw. +template <typename S, typename M, typename R> +static bool regex_search_no_exc(const S& string, M& match, const R& regex) +{ + try + { + return boost::regex_search(string, match, regex); + } + catch (const std::runtime_error& e) + { + LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': " + << e.what() << ":\n'" << string << "'" << LL_ENDL; + return false; + } +} + + LLOSInfo::LLOSInfo() : - mMajorVer(0), mMinorVer(0), mBuild(0) + mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("") { #if LL_WINDOWS @@ -412,6 +446,102 @@ LLOSInfo::LLOSInfo() : mOSString = mOSStringSimple; } +#elif LL_LINUX + + struct utsname un; + if(uname(&un) != -1) + { + mOSStringSimple.append(un.sysname); + mOSStringSimple.append(" "); + mOSStringSimple.append(un.release); + + mOSString = mOSStringSimple; + mOSString.append(" "); + mOSString.append(un.version); + mOSString.append(" "); + mOSString.append(un.machine); + + // Simplify 'Simple' + std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0)); + if (ostype == "Linux") + { + // Only care about major and minor Linux versions, truncate at second '.' + std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0); + std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos; + std::string simple = mOSStringSimple.substr(0, idx2); + if (simple.length() > 0) + mOSStringSimple = simple; + } + } + else + { + mOSStringSimple.append("Unable to collect OS info"); + mOSString = mOSStringSimple; + } + + const char OS_VERSION_MATCH_EXPRESSION[] = "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?"; + boost::regex os_version_parse(OS_VERSION_MATCH_EXPRESSION); + boost::smatch matched; + + std::string glibc_version(gnu_get_libc_version()); + if ( regex_match_no_exc(glibc_version, matched, os_version_parse) ) + { + LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL; + + std::string version_value; + + if ( matched[1].matched ) // Major version + { + version_value.assign(matched[1].first, matched[1].second); + if (sscanf(version_value.c_str(), "%d", &mMajorVer) != 1) + { + LL_WARNS("AppInit") << "failed to parse major version '" << version_value << "' as a number" << LL_ENDL; + } + } + else + { + LL_ERRS("AppInit") + << "OS version regex '" << OS_VERSION_MATCH_EXPRESSION + << "' returned true, but major version [1] did not match" + << LL_ENDL; + } + + if ( matched[2].matched ) // Minor version + { + version_value.assign(matched[2].first, matched[2].second); + if (sscanf(version_value.c_str(), "%d", &mMinorVer) != 1) + { + LL_ERRS("AppInit") << "failed to parse minor version '" << version_value << "' as a number" << LL_ENDL; + } + } + else + { + LL_ERRS("AppInit") + << "OS version regex '" << OS_VERSION_MATCH_EXPRESSION + << "' returned true, but minor version [1] did not match" + << LL_ENDL; + } + + if ( matched[4].matched ) // Build version (optional) - note that [3] includes the '.' + { + version_value.assign(matched[4].first, matched[4].second); + if (sscanf(version_value.c_str(), "%d", &mBuild) != 1) + { + LL_ERRS("AppInit") << "failed to parse build version '" << version_value << "' as a number" << LL_ENDL; + } + } + else + { + LL_INFOS("AppInit") + << "OS build version not provided; using zero" + << LL_ENDL; + } + } + else + { + LL_WARNS("AppInit") << "glibc version '" << glibc_version << "' cannot be parsed to three numbers; using all zeros" << LL_ENDL; + } + #else struct utsname un; @@ -444,8 +574,13 @@ LLOSInfo::LLOSInfo() : mOSStringSimple.append("Unable to collect OS info"); mOSString = mOSStringSimple; } + #endif + std::stringstream dotted_version_string; + dotted_version_string << mMajorVer << "." << mMinorVer << "." << mBuild; + mOSVersionString.append(dotted_version_string.str()); + } #ifndef LL_WINDOWS @@ -496,6 +631,11 @@ const std::string& LLOSInfo::getOSStringSimple() const return mOSStringSimple; } +const std::string& LLOSInfo::getOSVersionString() const +{ + return mOSVersionString; +} + const S32 STATUS_SIZE = 8192; //static @@ -687,38 +827,6 @@ private: LLSD mStats; }; -// Wrap boost::regex_match() with a function that doesn't throw. -template <typename S, typename M, typename R> -static bool regex_match_no_exc(const S& string, M& match, const R& regex) -{ - try - { - return boost::regex_match(string, match, regex); - } - catch (const std::runtime_error& e) - { - LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': " - << e.what() << ":\n'" << string << "'" << LL_ENDL; - return false; - } -} - -// Wrap boost::regex_search() with a function that doesn't throw. -template <typename S, typename M, typename R> -static bool regex_search_no_exc(const S& string, M& match, const R& regex) -{ - try - { - return boost::regex_search(string, match, regex); - } - catch (const std::runtime_error& e) - { - LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': " - << e.what() << ":\n'" << string << "'" << LL_ENDL; - return false; - } -} - LLMemoryInfo::LLMemoryInfo() { refresh(); diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 739e795d3a..cfed0fff17 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -49,6 +49,8 @@ public: const std::string& getOSString() const; const std::string& getOSStringSimple() const; + const std::string& getOSVersionString() const; + S32 mMajorVer; S32 mMinorVer; S32 mBuild; @@ -62,6 +64,7 @@ public: private: std::string mOSString; std::string mOSStringSimple; + std::string mOSVersionString; }; diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 9b755e9ca5..29060d4ef5 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -122,13 +122,10 @@ namespace tut // finding indra/lib/python. Use our __FILE__, with // raw-string syntax to deal with Windows pathnames. "mydir = os.path.dirname(r'" << __FILE__ << "')\n" - "try:\n" - " from llbase import llsd\n" - "except ImportError:\n" // We expect mydir to be .../indra/llcommon/tests. - " sys.path.insert(0,\n" - " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" - " from indra.base import llsd\n" + "sys.path.insert(0,\n" + " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" + "from indra.base import llsd\n" "\n" "class ProtocolError(Exception):\n" " def __init__(self, msg, data):\n" diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 99186ed434..6f1e7d46b8 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -608,6 +608,9 @@ namespace tut void object::test<5>() { set_test_name("exit(2)"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif PythonProcessLauncher py(get_test_name(), "import sys\n" "sys.exit(2)\n"); @@ -620,6 +623,9 @@ namespace tut void object::test<6>() { set_test_name("syntax_error:"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif PythonProcessLauncher py(get_test_name(), "syntax_error:\n"); py.mParams.files.add(LLProcess::FileParam()); // inherit stdin @@ -641,6 +647,9 @@ namespace tut void object::test<7>() { set_test_name("explicit kill()"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif PythonProcessLauncher py(get_test_name(), "from __future__ import with_statement\n" "import sys, time\n" @@ -685,6 +694,9 @@ namespace tut void object::test<8>() { set_test_name("implicit kill()"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif NamedTempFile out("out", "not started"); LLProcess::handle phandle(0); { diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index e625545763..4d436e8897 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -1523,10 +1523,7 @@ namespace tut "sys.path.insert(0,\n" " os.path.join(os.path.dirname(r'" __FILE__ "'),\n" " os.pardir, os.pardir, 'lib', 'python'))\n" - "try:\n" - " from llbase import llsd\n" - "except ImportError:\n" - " from indra.base import llsd\n") + "from indra.base import llsd\n") {} ~TestPythonCompatible() {} diff --git a/indra/llcorehttp/tests/test_httpstatus.hpp b/indra/llcorehttp/tests/test_httpstatus.hpp index f7b542d3b5..887315befc 100644 --- a/indra/llcorehttp/tests/test_httpstatus.hpp +++ b/indra/llcorehttp/tests/test_httpstatus.hpp @@ -91,6 +91,9 @@ template <> template <> void HttpStatusTestObjectType::test<2>() { set_test_name("HttpStatus memory structure"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif // Require that an HttpStatus object can be trivially // returned as a function return value in registers. @@ -104,6 +107,9 @@ template <> template <> void HttpStatusTestObjectType::test<3>() { set_test_name("HttpStatus valid error string conversion"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif HttpStatus status; status.mType = HttpStatus::EXT_CURL_EASY; @@ -136,6 +142,9 @@ template <> template <> void HttpStatusTestObjectType::test<4>() { set_test_name("HttpStatus invalid error string conversion"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif HttpStatus status; status.mType = HttpStatus::EXT_CURL_EASY; @@ -161,6 +170,9 @@ template <> template <> void HttpStatusTestObjectType::test<5>() { set_test_name("HttpStatus equality/inequality testing"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif // Make certain equality/inequality tests do not pass // through the bool conversion. Distinct successful @@ -181,6 +193,9 @@ template <> template <> void HttpStatusTestObjectType::test<6>() { set_test_name("HttpStatus basic HTTP status encoding"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif HttpStatus status; status.mType = 200; @@ -228,6 +243,9 @@ template <> template <> void HttpStatusTestObjectType::test<7>() { set_test_name("HttpStatus HTTP error text strings"); +#if LL_WINDOWS + skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif HttpStatus status(100, HE_REPLY_ERROR); std::string msg(status.toString()); diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 5831c3c1c1..227efdb07a 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -356,7 +356,8 @@ LLIOPipe::EStatus LLURLRequest::process_impl( } } - while(1) + bool keep_looping = true; + while(keep_looping) { CURLcode result; @@ -408,8 +409,9 @@ LLIOPipe::EStatus LLURLRequest::process_impl( case CURLE_FAILED_INIT: case CURLE_COULDNT_CONNECT: status = STATUS_NO_CONNECTION; + keep_looping = false; break; - default: + default: // CURLE_URL_MALFORMAT llwarns << "URLRequest Error: " << result << ", " << LLCurl::strerror(result) @@ -417,6 +419,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( << (mDetail->mURL.empty() ? "<EMPTY URL>" : mDetail->mURL) << llendl; status = STATUS_ERROR; + keep_looping = false; break; } } diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index b9cddc8e45..00b9d81611 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -886,8 +886,17 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user return; } - - std::string expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename ); + // If we want to use a special path (e.g. LL_PATH_CACHE), we want to make sure we create the + // proper expanded filename. + std::string expanded_filename; + if (local_path != LL_PATH_NONE) + { + expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename ); + } + else + { + expanded_filename = local_filename; + } llinfos << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << llendl; BOOL delete_local_on_completion = FALSE; diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 5b7424acbb..93b9d36939 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -50,14 +50,15 @@ LLSplashScreen *gSplashScreenp = NULL; BOOL gDebugClicks = FALSE; BOOL gDebugWindowProc = FALSE; -const S32 gURLProtocolWhitelistCount = 3; -const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" }; +const S32 gURLProtocolWhitelistCount = 4; +const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:" }; // CP: added a handler list - this is what's used to open the protocol and is based on registry entry // only meaningful difference currently is that file: protocols are opened using http: // since no protocol handler exists in registry for file: // Important - these lists should match - protocol to handler -const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" }; +// Maestro: This list isn't referenced anywhere that I could find +//const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" }; S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 4da87f4e06..e9147d552e 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -280,7 +280,7 @@ extern BOOL gDebugWindowProc; // Protocols, like "http" and "https" we support in URLs extern const S32 gURLProtocolWhitelistCount; extern const std::string gURLProtocolWhitelist[]; -extern const std::string gURLProtocolWhitelistHandler[]; +//extern const std::string gURLProtocolWhitelistHandler[]; void simpleEscapeString ( std::string& stringIn ); diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 39f8a36a6e..a15114cb9b 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2516,6 +2516,23 @@ void exec_cmd(const std::string& cmd, const std::string& arg) // Must begin with protocol identifier. void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) { + bool found = false; + S32 i; + for (i = 0; i < gURLProtocolWhitelistCount; i++) + { + if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos) + { + found = true; + break; + } + } + + if (!found) + { + llwarns << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << llendl; + return; + } + llinfos << "spawn_web_browser: " << escaped_url << llendl; #if LL_LINUX || LL_SOLARIS diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp index 5fb84756ee..0cfb810906 100644 --- a/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ b/indra/media_plugins/webkit/windows_volume_catcher.cpp @@ -48,18 +48,37 @@ private: set_volume_func_t mSetVolumeFunc; set_mute_func_t mSetMuteFunc; + // tests if running on Vista, 7, 8 + once in CTOR + bool isWindowsVistaOrHigher(); + F32 mVolume; F32 mPan; + bool mSystemIsVistaOrHigher; }; + +bool VolumeCatcherImpl::isWindowsVistaOrHigher() +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + return osvi.dwMajorVersion >= 6; +} + VolumeCatcherImpl::VolumeCatcherImpl() -: mVolume(1.0f), // default volume is max - mPan(0.f) // default pan is centered +: mVolume(1.0f), // default volume is max + mPan(0.f) // default pan is centered { - HMODULE handle = ::LoadLibrary(L"winmm.dll"); - if(handle) + mSystemIsVistaOrHigher = isWindowsVistaOrHigher(); + + if ( ! mSystemIsVistaOrHigher ) { - mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); - mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + HMODULE handle = ::LoadLibrary(L"winmm.dll"); + if(handle) + { + mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); + mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + } } } @@ -67,18 +86,29 @@ VolumeCatcherImpl::~VolumeCatcherImpl() { } - void VolumeCatcherImpl::setVolume(F32 volume) { mVolume = volume; - if (mSetMuteFunc) + if ( mSystemIsVistaOrHigher ) { - mSetMuteFunc(volume == 0.f); + // set both left/right to same volume + // TODO: use pan value to set independently + DWORD left_channel = (DWORD)(mVolume * 65535.0f); + DWORD right_channel = (DWORD)(mVolume * 65535.0f); + DWORD hw_volume = left_channel << 16 | right_channel; + ::waveOutSetVolume(NULL, hw_volume); } - if (mSetVolumeFunc) + else { - mSetVolumeFunc(mVolume); + if (mSetMuteFunc) + { + mSetMuteFunc(volume == 0.f); + } + if (mSetVolumeFunc) + { + mSetVolumeFunc(mVolume); + } } } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ab79cbde78..0b21d6c8fb 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -4,7 +4,6 @@ project(viewer) include(00-Common) include(Boost) -include(BuildVersion) include(DBusGlib) include(DirectX) include(OpenSSL) @@ -35,6 +34,7 @@ include(LLXML) include(LScript) include(Linking) include(NDOF) +include(NVAPI) include(GooglePerfTools) include(TemplateCheck) include(UI) @@ -82,6 +82,7 @@ include_directories( ${LIBS_PREBUILD_DIR}/include/hunspell ${OPENAL_LIB_INCLUDE_DIRS} ${LIBS_PREBUILT_DIR}/include/collada/1.4 + ${CMAKE_CURRENT_SOURCE_DIR} ) set(viewer_SOURCE_FILES @@ -278,6 +279,7 @@ set(viewer_SOURCE_FILES llgroupiconctrl.cpp llgrouplist.cpp llgroupmgr.cpp + llhasheduniqueid.cpp llhints.cpp llhomelocationresponder.cpp llhudeffect.cpp @@ -854,6 +856,7 @@ set(viewer_HEADER_FILES llgroupiconctrl.h llgrouplist.h llgroupmgr.h + llhasheduniqueid.h llhints.h llhomelocationresponder.h llhudeffect.h @@ -1227,6 +1230,18 @@ set(viewer_HEADER_FILES source_group("CMake Rules" FILES ViewerInstall.cmake) +add_custom_target(generate_viewer_version ALL + COMMAND echo "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}" > ${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + COMMENT Generating viewer_version.txt for manifest processing + ) + +set_source_files_properties( + llversioninfo.cpp tests/llversioninfo_test.cpp + PROPERTIES + DEPENDS generate_viewer_version # dummy dependency to force recompile every time + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) + if (DARWIN) LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp) @@ -1304,15 +1319,17 @@ if (WINDOWS) # Replace the icons with the appropriate ones for the channel # ('test' is the default) set(ICON_PATH "test") + set(VIEWER_MACOSX_PHASE "d") string(TOLOWER ${VIEWER_CHANNEL} channel_lower) if(channel_lower MATCHES "^second life release") set(ICON_PATH "release") - elseif(channel_lower MATCHES "^second life beta viewer") + set(VIEWER_MACOSX_PHASE "f") + elseif(channel_lower MATCHES "^second life beta") set(ICON_PATH "beta") - elseif(channel_lower MATCHES "^second life development") - set(ICON_PATH "development") - elseif(channel_lower MATCHES "project") + set(VIEWER_MACOSX_PHASE "b") + elseif(channel_lower MATCHES "^second life project") set(ICON_PATH "project") + set(VIEWER_MACOSX_PHASE "a") endif() message("Copying icons for ${ICON_PATH}") execute_process( @@ -1381,11 +1398,18 @@ if (WINDOWS) set_source_files_properties(${viewer_RESOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/res/viewerRes.rc + ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc + ) set(viewer_RESOURCE_FILES - res/viewerRes.rc + ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc ${viewer_RESOURCE_FILES} ) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc + PROPERTIES COMPILE_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/res" + ) + SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES}) if (NOT STANDALONE) @@ -1694,10 +1718,13 @@ if (WINDOWS) --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} --grid=${GRID} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + generate_viewer_version stage_third_party_libs ${COPY_INPUT_DEPENDENCIES} COMMENT "Performing viewer_manifest copy" @@ -1756,21 +1783,23 @@ if (WINDOWS) --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} --grid=${GRID} - --login_channel=${VIEWER_LOGIN_CHANNEL} --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt ${COPY_INPUT_DEPENDENCIES} ) add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat windows-setup-build-all + generate_viewer_version ) # temporarily disable packaging of event_host until hg subrepos get # sorted out on the parabuild cluster... @@ -1817,6 +1846,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLCOREHTTP_LIBRARIES} ${LLCOMMON_LIBRARIES} ${NDOF_LIBRARY} + ${NVAPI_LIBRARY} ${HUNSPELL_LIBRARY} ${viewer_LIBRARIES} ${BOOST_PROGRAM_OPTIONS_LIBRARY} @@ -1852,20 +1882,16 @@ else (USE_KDU) ) endif (USE_KDU) -build_version(viewer) - set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Path to artwork files.") - if (LINUX) - set(product SecondLife-${ARCH}-${viewer_VERSION}) + set(product SecondLife-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) # These are the generated targets that are copied to package/ set(COPY_INPUT_DEPENDENCIES ${VIEWER_BINARY_NAME} linux-crash-logger - linux-updater SLPlugin media_plugin_webkit media_plugin_gstreamer010 @@ -1882,20 +1908,22 @@ if (LINUX) --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --grid=${GRID} --installer_name=${product} - --login_channel=${VIEWER_LOGIN_CHANNEL} --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + generate_viewer_version ${COPY_INPUT_DEPENDENCIES} ) if (PACKAGE) endif (PACKAGE) + add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched COMMAND ${PYTHON_EXECUTABLE} @@ -1909,9 +1937,12 @@ if (LINUX) --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --grid=${GRID} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + generate_viewer_version ${COPY_INPUT_DEPENDENCIES} COMMENT "Performing viewer_manifest copy" ) @@ -1928,20 +1959,26 @@ endif (LINUX) if (DARWIN) set(product "Second Life") + set_target_properties( ${VIEWER_BINARY_NAME} PROPERTIES OUTPUT_NAME "${product}" - MACOSX_BUNDLE_INFO_STRING "info string - localize me" + MACOSX_BUNDLE_INFO_STRING "Second Life Viewer" MACOSX_BUNDLE_ICON_FILE "secondlife.icns" - MACOSX_BUNDLE_GUI_IDENTIFIER "Second Life" - MACOSX_BUNDLE_LONG_VERSION_STRING "ververver" + MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer" + MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}" MACOSX_BUNDLE_BUNDLE_NAME "Second Life" - MACOSX_BUNDLE_SHORT_VERSION_STRING "asdf" - MACOSX_BUNDLE_BUNDLE_VERSION "asdf" - MACOSX_BUNDLE_COPYRIGHT "copyright linden lab 2007 - localize me and run me through a legal wringer" + MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}" + MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}" + MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007" ) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" + "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app/Contents/Info.plist" + ) + add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD COMMAND ${PYTHON_EXECUTABLE} @@ -1954,8 +1991,13 @@ if (DARWIN) --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --grid=${GRID} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + DEPENDS + ${VIEWER_BINARY_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + generate_viewer_version ) add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-crash-logger) @@ -1968,6 +2010,7 @@ if (DARWIN) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) + add_dependencies(package generate_viewer_version) add_custom_command( TARGET package POST_BUILD @@ -1981,12 +2024,14 @@ if (DARWIN) --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --grid=${GRID} - --login_channel=${VIEWER_LOGIN_CHANNEL} + --channel=${VIEWER_CHANNEL} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched ${SIGNING_SETTING} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + generate_viewer_version ) endif (PACKAGE) endif (DARWIN) diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 5c7cacedec..041b8cea0b 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.1.0.13828"; -CFBundleGetInfoString = "Second Life version 2.1.0.13828, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version %%VERSION%%"; +CFBundleGetInfoString = "Second Life version %%VERSION%%, Copyright 2004 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index f7b11b217c..a19844f11c 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -60,7 +60,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.1.0.13828</string> + <string>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt new file mode 100644 index 0000000000..d5c0c99142 --- /dev/null +++ b/indra/newview/VIEWER_VERSION.txt @@ -0,0 +1 @@ +3.5.1 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 557a698d6d..45e77aded4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12109,6 +12109,17 @@ <key>Value</key> <integer>3</integer> </map> + <key>UpdaterWillingToTest</key> + <map> + <key>Comment</key> + <string>Allow upgrades to release candidate viewers with new features and fixes.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>UpdaterServiceCheckPeriod</key> <map> <key>Comment</key> @@ -12142,17 +12153,6 @@ <key>Value</key> <string>update</string> </map> - <key>UpdaterServiceProtocolVersion</key> - <map> - <key>Comment</key> - <string>The update protocol version to use.</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>v1.0</string> - </map> <key>UploadBakedTexOld</key> <map> <key>Comment</key> @@ -14070,6 +14070,18 @@ <real>1.0</real> </array> </map> + + <key>HideUIControls</key> + <map> + <key>Comment</key> + <string>Hide all menu items and buttons</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>SimulateFBOFailure</key> <map> diff --git a/indra/llcommon/llversionviewer.h b/indra/newview/app_settings/shaders/class1/objects/previewF.glsl index 39f9de3bc2..284da3d0ac 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/newview/app_settings/shaders/class1/objects/previewF.glsl @@ -1,10 +1,9 @@ /** - * @file llversionviewer.h - * @brief + * @file previewF.glsl * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2011, 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 @@ -24,18 +23,19 @@ * $/LicenseInfo$ */ -#ifndef LL_LLVERSIONVIEWER_H -#define LL_LLVERSIONVIEWER_H - -const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 4; -const S32 LL_VERSION_PATCH = 5; -const S32 LL_VERSION_BUILD = 0; +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif -const char * const LL_CHANNEL = "Second Life Developer"; +uniform sampler2D diffuseMap; -#if LL_DARWIN -const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer"; -#endif +VARYING vec4 vertex_color; +VARYING vec2 vary_texcoord0; -#endif +void main() +{ + vec4 color = texture2D(diffuseMap,vary_texcoord0.xy) * vertex_color; + frag_color = color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl index 5dcfa87066..7f3f84398b 100644 --- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl @@ -32,12 +32,51 @@ ATTRIBUTE vec3 position; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; +uniform vec4 color; + VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +uniform vec4 light_position[8]; +uniform vec3 light_direction[8]; +uniform vec3 light_attenuation[8]; +uniform vec3 light_diffuse[8]; + +//=================================================================================================== +//declare these here explicitly to separate them from atmospheric lighting elsewhere to work around +//drivers that are picky about functions being declared but not defined even if they aren't called +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float da = clamp(1.0/(la * d), 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} +//==================================================================================================== -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); void main() { @@ -45,13 +84,15 @@ void main() vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - + vec3 norm = normalize(normal_matrix * normal); - calcAtmospherics(pos.xyz); - - vec4 color = calcLighting(pos.xyz, norm, vec4(1,1,1,1), vec4(0.)); - vertex_color = color; + vec4 col = vec4(0,0,0,1); - + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz); + col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z); + col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z); + + vertex_color = col*color; } diff --git a/indra/newview/icons/development/secondlife.icns b/indra/newview/icons/development/secondlife.icns Binary files differdeleted file mode 100644 index 44f63d384c..0000000000 --- a/indra/newview/icons/development/secondlife.icns +++ /dev/null diff --git a/indra/newview/icons/development/secondlife.ico b/indra/newview/icons/development/secondlife.ico Binary files differdeleted file mode 100644 index b53f23ae58..0000000000 --- a/indra/newview/icons/development/secondlife.ico +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_128.png b/indra/newview/icons/development/secondlife_128.png Binary files differdeleted file mode 100644 index 9b9fe656fc..0000000000 --- a/indra/newview/icons/development/secondlife_128.png +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_16.png b/indra/newview/icons/development/secondlife_16.png Binary files differdeleted file mode 100644 index 91493a033c..0000000000 --- a/indra/newview/icons/development/secondlife_16.png +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_256.BMP b/indra/newview/icons/development/secondlife_256.BMP Binary files differdeleted file mode 100644 index 174b22319a..0000000000 --- a/indra/newview/icons/development/secondlife_256.BMP +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_256.png b/indra/newview/icons/development/secondlife_256.png Binary files differdeleted file mode 100644 index 29ed40abdc..0000000000 --- a/indra/newview/icons/development/secondlife_256.png +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_32.png b/indra/newview/icons/development/secondlife_32.png Binary files differdeleted file mode 100644 index 3b84f5ec77..0000000000 --- a/indra/newview/icons/development/secondlife_32.png +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_48.png b/indra/newview/icons/development/secondlife_48.png Binary files differdeleted file mode 100644 index d2636d9d72..0000000000 --- a/indra/newview/icons/development/secondlife_48.png +++ /dev/null diff --git a/indra/newview/icons/development/secondlife_512.png b/indra/newview/icons/development/secondlife_512.png Binary files differdeleted file mode 100644 index 75f9b231f4..0000000000 --- a/indra/newview/icons/development/secondlife_512.png +++ /dev/null diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 20936c6460..98c8674fa5 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -113,7 +113,7 @@ export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" # Have to deal specially with gridargs.dat; typical contents look like: -# --channel "Second Life Developer" --settings settings_developer.xml +# --channel "Second Life Test" --settings settings_test.xml # Simply embedding $(<etc/gridargs.dat) into a command line treats each of # Second, Life and Developer as separate args -- no good. We need bash to # process quotes using eval. diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 751b73e1eb..9025c7af8b 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -35,6 +35,7 @@ #include "llfloaterreg.h" #include "llhudmanager.h" #include "lljoystickbutton.h" +#include "llmoveview.h" #include "llselectmgr.h" #include "llsmoothstep.h" #include "lltoolmgr.h" @@ -2113,6 +2114,11 @@ void LLAgentCamera::changeCameraToDefault() { changeCameraToThirdPerson(); } + if (gSavedSettings.getBOOL("HideUIControls")) + { + gViewerWindow->setUIVisibility(false); + LLPanelStandStopFlying::getInstance()->setVisible(false); + } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f203ac224b..18314904a7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -30,7 +30,6 @@ // Viewer includes #include "llversioninfo.h" -#include "llversionviewer.h" #include "llfeaturemanager.h" #include "lluictrlfactory.h" #include "lltexteditor.h" @@ -122,6 +121,7 @@ #include <boost/bind.hpp> #include <boost/foreach.hpp> #include <boost/algorithm/string.hpp> +#include <boost/regex.hpp> #if LL_WINDOWS @@ -251,6 +251,7 @@ static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); // viewer.cpp - these are only used in viewer, should be easily moved. #if LL_DARWIN +const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer"; extern void init_apple_menu(const char* product); #endif // LL_DARWIN @@ -1030,11 +1031,20 @@ bool LLAppViewer::init() } #if LL_WINDOWS - if (gGLManager.mIsIntel && - LLFeatureManager::getInstance()->getGPUClass() > 0 && - gGLManager.mGLVersion <= 3.f) + if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) { - LLNotificationsUtil::add("IntelOldDriver"); + if (gGLManager.mIsIntel) + { + LLNotificationsUtil::add("IntelOldDriver"); + } + else if (gGLManager.mIsNVIDIA) + { + LLNotificationsUtil::add("NVIDIAOldDriver"); + } + else if (gGLManager.mIsATI) + { + LLNotificationsUtil::add("AMDOldDriver"); + } } #endif @@ -2822,25 +2832,46 @@ namespace { std::string notification_name; void (*apply_callback)(LLSD const &, LLSD const &) = NULL; + /* Build up the notification name... + * it can be any of these, which are included here for the sake of grep: + * RequiredUpdateDownloadedDialog + * RequiredUpdateDownloadedVerboseDialog + * OtherChannelRequiredUpdateDownloadedDialog + * OtherChannelRequiredUpdateDownloadedVerbose + * DownloadBackgroundTip + * DownloadBackgroundDialog + * OtherChannelDownloadBackgroundTip + * OtherChannelDownloadBackgroundDialog + */ + { + LL_DEBUGS("UpdaterService") << "data = "; + std::ostringstream data_dump; + LLSDSerialize::toNotation(data, data_dump); + LL_CONT << data_dump.str() << LL_ENDL; + } + if(data["channel"].asString() != LLVersionInfo::getChannel()) + { + notification_name.append("OtherChannel"); + } if(data["required"].asBoolean()) { if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT) { // The user never saw the progress bar. apply_callback = &apply_update_ok_callback; - notification_name = "RequiredUpdateDownloadedVerboseDialog"; + notification_name += "RequiredUpdateDownloadedVerboseDialog"; } else if(LLStartUp::getStartupState() < STATE_WORLD_INIT) { // The user is logging in but blocked. apply_callback = &apply_update_ok_callback; - notification_name = "RequiredUpdateDownloadedDialog"; + notification_name += "RequiredUpdateDownloadedDialog"; } else { // The user is already logged in; treat like an optional update. apply_callback = &apply_update_callback; - notification_name = "DownloadBackgroundTip"; + notification_name += "DownloadBackgroundTip"; } } else @@ -2850,36 +2881,47 @@ namespace { { // CHOP-262 we need to use a different notification // method prior to login. - notification_name = "DownloadBackgroundDialog"; + notification_name += "DownloadBackgroundDialog"; } else { - notification_name = "DownloadBackgroundTip"; + notification_name += "DownloadBackgroundTip"; } } LLSD substitutions; substitutions["VERSION"] = data["version"]; - - // truncate version at the rightmost '.' - std::string version_short(data["version"]); - size_t short_length = version_short.rfind('.'); - if (short_length != std::string::npos) + std::string new_channel = data["channel"].asString(); + substitutions["NEW_CHANNEL"] = new_channel; + std::string info_url = data["info_url"].asString(); + if ( !info_url.empty() ) { - version_short.resize(short_length); + substitutions["INFO_URL"] = info_url; } + else + { + LL_WARNS("UpdaterService") << "no info url supplied - defaulting to hard coded release notes pattern" << LL_ENDL; - LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]"); - relnotes_url.setArg("[VERSION_SHORT]", version_short); + // truncate version at the rightmost '.' + std::string version_short(data["version"]); + size_t short_length = version_short.rfind('.'); + if (short_length != std::string::npos) + { + version_short.resize(short_length); + } - // *TODO thread the update service's response through to this point - std::string const & channel = LLVersionInfo::getChannel(); - boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free); + LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]"); + relnotes_url.setArg("[VERSION_SHORT]", version_short); - relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get()); - relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL")); - substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString(); + // *TODO thread the update service's response through to this point + std::string const & channel = LLVersionInfo::getChannel(); + boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free); + relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get()); + relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL")); + substitutions["INFO_URL"] = relnotes_url.getString(); + } + LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback); } @@ -2927,16 +2969,39 @@ void LLAppViewer::initUpdater() std::string url = gSavedSettings.getString("UpdaterServiceURL"); std::string channel = LLVersionInfo::getChannel(); std::string version = LLVersionInfo::getVersion(); - std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion"); std::string service_path = gSavedSettings.getString("UpdaterServicePath"); U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod"); + bool willing_to_test; + LL_DEBUGS("UpdaterService") << "channel " << channel << LL_ENDL; + static const boost::regex is_test_channel("\\bTest$"); + if (boost::regex_search(channel, is_test_channel)) + { + LL_INFOS("UpdaterService") << "Test build: overriding willing_to_test by sending testno" << LL_ENDL; + willing_to_test = false; + } + else + { + willing_to_test = gSavedSettings.getBOOL("UpdaterWillingToTest"); + } + unsigned char unique_id[MD5HEX_STR_SIZE]; + if ( ! llHashedUniqueID(unique_id) ) + { + if ( willing_to_test ) + { + LL_WARNS("UpdaterService") << "Unable to provide a unique id; overriding willing_to_test by sending testno" << LL_ENDL; + } + willing_to_test = false; + } mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this)); - mUpdater->initialize(protocol_version, - url, + mUpdater->initialize(url, service_path, channel, - version); + version, + getOSInfo().getOSVersionString(), + unique_id, + willing_to_test + ); mUpdater->setCheckPeriod(check_period); mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8)); gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()-> diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index b70c81e84d..8326be433e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -46,6 +46,11 @@ #include "llviewercontrol.h" #include "lldxhardware.h" +#include "nvapi/nvapi.h" +#include "nvapi/NvApiDriverSettings.h" + +#include <stdlib.h> + #include "llweb.h" #include "llsecondlifeurls.h" @@ -60,6 +65,7 @@ #include "llwindebug.h" #endif + // *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib // The lib was compiled under VS2005 - in VS2003 we need to remap assert #ifdef LL_DEBUG @@ -75,6 +81,20 @@ extern "C" { const std::string LLAppViewerWin32::sWindowClass = "Second Life"; +/* + This function is used to print to the command line a text message + describing the nvapi error and quits +*/ +void nvapi_error(NvAPI_Status status) +{ + NvAPI_ShortString szDesc = {0}; + NvAPI_GetErrorMessage(status, szDesc); + llwarns << szDesc << llendl; + + //should always trigger when asserts are enabled + llassert(status == NVAPI_OK); +} + // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -96,6 +116,79 @@ bool create_app_mutex() return result; } +void ll_nvapi_init(NvDRSSessionHandle hSession) +{ + // (2) load all the system settings into the session + NvAPI_Status status = NvAPI_DRS_LoadSettings(hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + NvAPI_UnicodeString profile_name; + std::string app_name = LLTrans::getString("APP_NAME"); + llutf16string w_app_name = utf8str_to_utf16str(app_name); + wsprintf(profile_name, L"%s", w_app_name.c_str()); + status = NvAPI_DRS_SetCurrentGlobalProfile(hSession, profile_name); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + // (3) Obtain the current profile. + NvDRSProfileHandle hProfile = 0; + status = NvAPI_DRS_GetCurrentGlobalProfile(hSession, &hProfile); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + // load settings for querying + status = NvAPI_DRS_LoadSettings(hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + //get the preferred power management mode for Second Life + NVDRS_SETTING drsSetting = {0}; + drsSetting.version = NVDRS_SETTING_VER; + status = NvAPI_DRS_GetSetting(hSession, hProfile, PREFERRED_PSTATE_ID, &drsSetting); + if (status == NVAPI_SETTING_NOT_FOUND) + { //only override if the user hasn't specifically set this setting + // (4) Specify that we want the VSYNC disabled setting + // first we fill the NVDRS_SETTING struct, then we call the function + drsSetting.version = NVDRS_SETTING_VER; + drsSetting.settingId = PREFERRED_PSTATE_ID; + drsSetting.settingType = NVDRS_DWORD_TYPE; + drsSetting.u32CurrentValue = PREFERRED_PSTATE_PREFER_MAX; + status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting); + if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + } + else if (status != NVAPI_OK) + { + nvapi_error(status); + return; + } + + + + // (5) Now we apply (or save) our changes to the system + status = NvAPI_DRS_SaveSettings(hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + } +} + //#define DEBUGGING_SEH_FILTER 1 #if DEBUGGING_SEH_FILTER # define WINMAIN DebuggingWinMain @@ -165,6 +258,27 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, return -1; } + NvAPI_Status status; + + // Initialize NVAPI + status = NvAPI_Initialize(); + NvDRSSessionHandle hSession = 0; + + if (status == NVAPI_OK) + { + // Create the session handle to access driver settings + status = NvAPI_DRS_CreateSession(&hSession); + if (status != NVAPI_OK) + { + nvapi_error(status); + } + else + { + //override driver setting as needed + ll_nvapi_init(hSession); + } + } + // Have to wait until after logging is initialized to display LFH info if (num_heaps > 0) { @@ -232,6 +346,15 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, LLAppViewer::sUpdaterInfo = NULL ; } + + + // (NVAPI) (6) We clean up. This is analogous to doing a free() + if (hSession) + { + NvAPI_DRS_DestroySession(hSession); + hSession = 0; + } + return 0; } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 7cfb58e544..d041baea90 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -524,6 +524,7 @@ F32 LLDrawable::updateXform(BOOL undamped) dist_squared = dist_vec_squared(new_pos, target_pos); LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); + // FIXME: This can be negative! It is be possible for some rots to 'cancel out' pos or size changes. dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); @@ -547,6 +548,15 @@ F32 LLDrawable::updateXform(BOOL undamped) } } } + else + { + // The following fixes MAINT-1742 but breaks vehicles similar to MAINT-2275 + // dist_squared = dist_vec_squared(old_pos, target_pos); + + // The following fixes MAINT-2247 but causes MAINT-2275 + //dist_squared += (1.f - dot(old_rot, target_rot)) * 10.f; + //dist_squared += dist_vec_squared(old_scale, target_scale); + } LLVector3 vec = mCurrentScale-target_scale; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 2b39b771e7..a4cadcd5dc 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -479,6 +479,7 @@ void LLFeatureManager::parseGPUTable(std::string filename) mGPUString = label; mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10); mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10); + sscanf(expected_gl_version.c_str(), "%f", &mExpectedGLVersion); } } #if LL_EXPORT_GPU_TABLE diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 6f9d2e49c6..ad72c16743 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -103,7 +103,8 @@ public: mTableVersion(0), mSafe(FALSE), mGPUClass(GPU_CLASS_UNKNOWN), - mGPUSupported(FALSE) + mExpectedGLVersion(0.f), + mGPUSupported(FALSE) { } ~LLFeatureManager() {cleanupFeatureTables();} @@ -118,6 +119,7 @@ public: EGPUClass getGPUClass() { return mGPUClass; } std::string& getGPUString() { return mGPUString; } BOOL isGPUSupported() { return mGPUSupported; } + F32 getExpectedGLVersion() { return mExpectedGLVersion; } void cleanupFeatureTables(); @@ -157,6 +159,7 @@ protected: S32 mTableVersion; BOOL mSafe; // Reinitialize everything to the "safe" mask EGPUClass mGPUClass; + F32 mExpectedGLVersion; //expected GL version according to gpu table std::string mGPUString; BOOL mGPUSupported; }; diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index bca4b5e447..fffd724b22 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -80,6 +80,7 @@ BOOL LLFloaterBuyContents::postBuild() LLFloaterBuyContents::~LLFloaterBuyContents() { + removeVOInventoryListener(); } @@ -147,23 +148,26 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, return; } - if (!inv) + LLScrollListCtrl* item_list = getChild<LLScrollListCtrl>("item_list"); + if (!item_list) { - llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged" - << llendl; removeVOInventoryListener(); return; } - LLCtrlListInterface *item_list = childGetListInterface("item_list"); - if (!item_list) + item_list->deleteAllItems(); + + if (!inv) { - removeVOInventoryListener(); + llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged" + << llendl; + return; } // default to turning off the buy button. - getChildView("buy_btn")->setEnabled(FALSE); + LLView* buy_btn = getChildView("buy_btn"); + buy_btn->setEnabled(FALSE); LLUUID owner_id; BOOL is_group_owned; @@ -204,7 +208,7 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, // There will be at least one item shown in the display, so go // ahead and enable the buy button. - getChildView("buy_btn")->setEnabled(TRUE); + buy_btn->setEnabled(TRUE); // Create the line in the list LLSD row; @@ -255,8 +259,6 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, getChildView("wear_check")->setEnabled(TRUE); getChild<LLUICtrl>("wear_check")->setValue(LLSD(false) ); } - - removeVOInventoryListener(); } diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 6b2492d927..2575f6f817 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -901,11 +901,13 @@ BOOL LLImagePreviewSculpted::render() { gObjectPreviewProgram.bind(); } + gPipeline.enableLightsPreview(); + gGL.pushMatrix(); const F32 SCALE = 1.25f; gGL.scalef(SCALE, SCALE, SCALE); const F32 BRIGHTNESS = 0.9f; - gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); + gGL.diffuseColor3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 449173f9b4..ea839e6f5a 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -3884,15 +3884,30 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim U32 triangle_count = 0; - for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) + U32 instanced_triangle_count = 0; + + //get the triangle count for the whole scene + for (LLModelLoader::scene::iterator iter = mBaseScene.begin(), endIter = mBaseScene.end(); iter != endIter; ++iter) { - LLModel* mdl = *iter; - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) { - triangle_count += mdl->getVolumeFace(i).mNumIndices/3; + LLModel* mdl = instance->mModel; + if (mdl) + { + instanced_triangle_count += mdl->getNumTriangles(); + } } } + //get the triangle count for the non-instanced set of models + for (U32 i = 0; i < mBaseModel.size(); ++i) + { + triangle_count += mBaseModel[i]->getNumTriangles(); + } + + //get ratio of uninstanced triangles to instanced triangles + F32 triangle_ratio = (F32) triangle_count / (F32) instanced_triangle_count; + U32 base_triangle_count = triangle_count; U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -3926,6 +3941,8 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim if (which_lod > -1 && which_lod < NUM_LOD) { limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger(); + //convert from "scene wide" to "non-instanced" triangle limit + limit = (S32) ( (F32) limit*triangle_ratio ); } } else @@ -4031,7 +4048,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim U32 actual_verts = 0; U32 submeshes = 0; - mRequestedTriangleCount[lod] = triangle_count; + mRequestedTriangleCount[lod] = (S32) ( (F32) triangle_count / triangle_ratio ); mRequestedErrorThreshold[lod] = lod_error_threshold; glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode); @@ -4213,28 +4230,36 @@ void LLModelPreview::updateStatusMessages() //initialize total for this lod to 0 total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; - for (U32 i = 0; i < mModel[lod].size(); ++i) - { //for each model in the lod - S32 cur_tris = 0; - S32 cur_verts = 0; - S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces(); - - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); - cur_tris += face.mNumIndices/3; - cur_verts += face.mNumVertices; - } + for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter) + { + for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) + { + LLModel* model = instance->mModel; + if (model) + { + //for each model in the lod + S32 cur_tris = 0; + S32 cur_verts = 0; + S32 cur_submeshes = model->getNumVolumeFaces(); + + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = model->getVolumeFace(j); + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; + } - //add this model to the lod total - total_tris[lod] += cur_tris; - total_verts[lod] += cur_verts; - total_submeshes[lod] += cur_submeshes; + //add this model to the lod total + total_tris[lod] += cur_tris; + total_verts[lod] += cur_verts; + total_submeshes[lod] += cur_submeshes; - //store this model's counts to asset data - tris[lod].push_back(cur_tris); - verts[lod].push_back(cur_verts); - submeshes[lod].push_back(cur_submeshes); + //store this model's counts to asset data + tris[lod].push_back(cur_tris); + verts[lod].push_back(cur_verts); + submeshes[lod].push_back(cur_submeshes); + } + } } } @@ -4411,34 +4436,38 @@ void LLModelPreview::updateStatusMessages() } //add up physics triangles etc - S32 start = 0; - S32 end = mModel[LLModel::LOD_PHYSICS].size(); - S32 phys_tris = 0; S32 phys_hulls = 0; S32 phys_points = 0; - for (S32 i = start; i < end; ++i) - { //add up hulls and points and triangles for selected mesh(es) - LLModel* model = mModel[LLModel::LOD_PHYSICS][i]; - S32 cur_submeshes = model->getNumVolumeFaces(); - - LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull; - - if (!decomp.empty()) + //get the triangle count for the whole scene + for (LLModelLoader::scene::iterator iter = mScene[LLModel::LOD_PHYSICS].begin(), endIter = mScene[LLModel::LOD_PHYSICS].end(); iter != endIter; ++iter) + { + for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) { - phys_hulls += decomp.size(); - for (U32 i = 0; i < decomp.size(); ++i) + LLModel* model = instance->mModel; + if (model) { - phys_points += decomp[i].size(); - } - } - else - { //choose physics shape OR decomposition, can't use both - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = model->getVolumeFace(j); - phys_tris += face.mNumIndices/3; + S32 cur_submeshes = model->getNumVolumeFaces(); + + LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull; + + if (!decomp.empty()) + { + phys_hulls += decomp.size(); + for (U32 i = 0; i < decomp.size(); ++i) + { + phys_points += decomp[i].size(); + } + } + else + { //choose physics shape OR decomposition, can't use both + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = model->getVolumeFace(j); + phys_tris += face.mNumIndices/3; + } + } } } } @@ -5087,6 +5116,11 @@ BOOL LLModelPreview::render() refresh(); } + if (use_shaders) + { + gObjectPreviewProgram.bind(); + } + gGL.loadIdentity(); gPipeline.enableLightsPreview(); @@ -5112,11 +5146,6 @@ BOOL LLModelPreview::render() const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; - if (use_shaders) - { - gObjectPreviewProgram.bind(); - } - LLGLEnable normalize(GL_NORMALIZE); if (!mBaseModel.empty() && mVertexBuffer[5].empty()) @@ -5305,7 +5334,7 @@ BOOL LLModelPreview::render() hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); } - glColor4ubv(hull_colors[i].mV); + gGL.diffuseColor4ubv(hull_colors[i].mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); if (explode > 0.f) diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 48484786f6..1eb7f4469a 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1055,6 +1055,17 @@ void commit_grid_mode(LLUICtrl *ctrl) LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); } +// static +void LLFloaterTools::setGridMode(S32 mode) +{ + LLFloaterTools* tools_floater = LLFloaterReg::getTypedInstance<LLFloaterTools>("build"); + if (!tools_floater || !tools_floater->mComboGridMode) + { + return; + } + + tools_floater->mComboGridMode->setCurrentByIndex(mode); +} void LLFloaterTools::onClickGridOptions() { diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 7a19d093a4..ecb0092a6f 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -107,6 +107,8 @@ public: bool selectedMediaEditable(); void updateLandImpacts(); + static void setGridMode(S32 mode); + private: void refresh(); void refreshMedia(); diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 151cd2a1cd..e85d849c9a 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -219,7 +219,8 @@ void LLFloaterURLEntry::onBtnOK( void* userdata ) } // Discover the MIME type only for "http" scheme. - if(scheme == "http" || scheme == "https") + if(!media_url.empty() && + (scheme == "http" || scheme == "https")) { LLHTTPClient::getHeaderOnly( media_url, new LLMediaTypeResponder(self->getHandle())); diff --git a/indra/newview/llhasheduniqueid.cpp b/indra/newview/llhasheduniqueid.cpp new file mode 100644 index 0000000000..5db5d22332 --- /dev/null +++ b/indra/newview/llhasheduniqueid.cpp @@ -0,0 +1,54 @@ +/** + * @file llhasheduniqueid.cpp + * @brief retrieves an obfuscated unique id for the system + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llhasheduniqueid.h" +#include "llviewernetwork.h" +#include "lluuid.h" +#include "llmachineid.h" + +bool llHashedUniqueID(unsigned char id[MD5HEX_STR_SIZE]) +{ + bool idIsUnique = true; + LLMD5 hashed_unique_id; + unsigned char unique_id[MAC_ADDRESS_BYTES]; + if ( LLUUID::getNodeID(unique_id) + || LLMachineID::getUniqueID(unique_id, sizeof(unique_id)) + ) + { + hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES); + hashed_unique_id.finalize(); + hashed_unique_id.hex_digest((char*)id); + } + else + { + idIsUnique = false; + memcpy(id,"00000000000000000000000000000000", MD5HEX_STR_SIZE); + llwarns << "Failed to get an id; cannot uniquely identify this machine." << llendl; + } + return idIsUnique; +} + diff --git a/indra/newview/llhasheduniqueid.h b/indra/newview/llhasheduniqueid.h new file mode 100644 index 0000000000..8ef706c1f3 --- /dev/null +++ b/indra/newview/llhasheduniqueid.h @@ -0,0 +1,34 @@ +/** + * @file llhasheduniqueid.h + * @brief retrieves obfuscated but unique id for the system + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LL_LLHASHEDUNIQUEID_H +#define LL_LLHASHEDUNIQUEID_H +#include "llmd5.h" + +/// Get an obfuscated identifier for this system +bool llHashedUniqueID(unsigned char id[MD5HEX_STR_SIZE]); +///< @returns true if the id is considered valid (if false, the id is all zeros) + +#endif // LL_LLHASHEDUNIQUEID_H diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 419641d23c..b27a566c23 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -30,7 +30,6 @@ // llcommon #include "llevents.h" -#include "llmd5.h" #include "stringize.h" // llmessage (!) @@ -40,6 +39,7 @@ #include "lllogin.h" // newview +#include "llhasheduniqueid.h" #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llversioninfo.h" @@ -202,7 +202,7 @@ MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance, void MandatoryUpdateMachine::start(void) { - llinfos << "starting manditory update machine" << llendl; + llinfos << "starting mandatory update machine" << llendl; if(mUpdaterService.isChecking()) { switch(mUpdaterService.getState()) { @@ -579,24 +579,17 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia // (re)initialize the request params with creds. LLSD request_params = user_credential->getLoginParams(); - char hashed_unique_id_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ - LLMD5 hashed_unique_id; - unsigned char unique_id[MAC_ADDRESS_BYTES]; - if(LLUUID::getNodeID(unique_id) == 0) { - if(LLMachineID::getUniqueID(unique_id, sizeof(unique_id)) == 0) { - llerrs << "Failed to get an id; cannot uniquely identify this machine." << llendl; - } + unsigned char hashed_unique_id_string[MD5HEX_STR_SIZE]; + if ( ! llHashedUniqueID(hashed_unique_id_string) ) + { + llwarns << "Not providing a unique id in request params" << llendl; } - hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES); - hashed_unique_id.finalize(); - hashed_unique_id.hex_digest(hashed_unique_id_string); - request_params["start"] = construct_start_string(); request_params["skipoptional"] = mSkipOptionalUpdate; request_params["agree_to_tos"] = false; // Always false here. Set true in request_params["read_critical"] = false; // handleTOSResponse request_params["last_exec_event"] = mLastExecEvent; - request_params["mac"] = hashed_unique_id_string; + request_params["mac"] = (char*)hashed_unique_id_string; request_params["version"] = LLVersionInfo::getChannelAndVersion(); // Includes channel name request_params["channel"] = LLVersionInfo::getChannel(); request_params["id0"] = mSerialNumber; @@ -784,20 +777,20 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) LLSD payload; payload["mandatory"] = mandatory; -/* - We're constructing one of the following 9 strings here: - "DownloadWindowsMandatory" - "DownloadWindowsReleaseForDownload" - "DownloadWindows" - "DownloadMacMandatory" - "DownloadMacReleaseForDownload" - "DownloadMac" - "DownloadLinuxMandatory" - "DownloadLinuxReleaseForDownload" - "DownloadLinux" - - I've called them out explicitly in this comment so that they can be grepped for. - */ + /* + * We're constructing one of the following 9 strings here: + * "DownloadWindowsMandatory" + * "DownloadWindowsReleaseForDownload" + * "DownloadWindows" + * "DownloadMacMandatory" + * "DownloadMacReleaseForDownload" + * "DownloadMac" + * "DownloadLinuxMandatory" + * "DownloadLinuxReleaseForDownload" + * "DownloadLinux" + * + * I've called them out explicitly in this comment so that they can be grepped for. + */ std::string notification_name = "Download"; #if LL_WINDOWS diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index 6e0f360cbc..9ec5d7c20c 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -72,7 +72,6 @@ void LLManip::rebuild(LLViewerObject* vobj) LLDrawable* drawablep = vobj->mDrawable; if (drawablep && drawablep->getVOVolume()) { - gPipeline.markRebuild(drawablep,LLDrawable::REBUILD_VOLUME, TRUE); drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED drawablep->updateMove(); @@ -82,6 +81,14 @@ void LLManip::rebuild(LLViewerObject* vobj) group->dirtyGeom(); gPipeline.markRebuild(group, TRUE); } + + LLViewerObject::const_child_list_t& child_list = vobj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(), endIter = child_list.end(); + iter != endIter; ++iter) + { + LLViewerObject* child = *iter; + rebuild(child); + } } } diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 92ac435f08..1223615079 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -204,16 +204,30 @@ class LLMeshHeaderResponder : public LLCurl::Responder { public: LLVolumeParams mMeshParams; - + bool mProcessed; + LLMeshHeaderResponder(const LLVolumeParams& mesh_params) : mMeshParams(mesh_params) { - LLMeshRepoThread::sActiveHeaderRequests++; + LLMeshRepoThread::incActiveHeaderRequests(); + mProcessed = false; } ~LLMeshHeaderResponder() { - LLMeshRepoThread::sActiveHeaderRequests--; + if (!LLApp::isQuitting()) + { + if (!mProcessed) + { //something went wrong, retry + llwarns << "Timeout or service unavailable, retrying." << llendl; + LLMeshRepository::sHTTPRetryCount++; + LLMeshRepoThread::HeaderRequest req(mMeshParams); + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->mHeaderReqQ.push(req); + } + + LLMeshRepoThread::decActiveHeaderRequests(); + } } virtual void completedRaw(U32 status, const std::string& reason, @@ -229,16 +243,27 @@ public: S32 mLOD; U32 mRequestedBytes; U32 mOffset; + bool mProcessed; LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes) : mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes) { - LLMeshRepoThread::sActiveLODRequests++; + LLMeshRepoThread::incActiveLODRequests(); + mProcessed = false; } ~LLMeshLODResponder() { - LLMeshRepoThread::sActiveLODRequests--; + if (!LLApp::isQuitting()) + { + if (!mProcessed) + { + llwarns << "Killed without being processed, retrying." << llendl; + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->lockAndLoadMeshLOD(mMeshParams, mLOD); + } + LLMeshRepoThread::decActiveLODRequests(); + } } virtual void completedRaw(U32 status, const std::string& reason, @@ -253,10 +278,17 @@ public: LLUUID mMeshID; U32 mRequestedBytes; U32 mOffset; + bool mProcessed; LLMeshSkinInfoResponder(const LLUUID& id, U32 offset, U32 size) : mMeshID(id), mRequestedBytes(size), mOffset(offset) { + mProcessed = false; + } + + ~LLMeshSkinInfoResponder() + { + llassert(mProcessed); } virtual void completedRaw(U32 status, const std::string& reason, @@ -271,10 +303,17 @@ public: LLUUID mMeshID; U32 mRequestedBytes; U32 mOffset; + bool mProcessed; LLMeshDecompositionResponder(const LLUUID& id, U32 offset, U32 size) : mMeshID(id), mRequestedBytes(size), mOffset(offset) { + mProcessed = false; + } + + ~LLMeshDecompositionResponder() + { + llassert(mProcessed); } virtual void completedRaw(U32 status, const std::string& reason, @@ -289,10 +328,17 @@ public: LLUUID mMeshID; U32 mRequestedBytes; U32 mOffset; + bool mProcessed; LLMeshPhysicsShapeResponder(const LLUUID& id, U32 offset, U32 size) : mMeshID(id), mRequestedBytes(size), mOffset(offset) { + mProcessed = false; + } + + ~LLMeshPhysicsShapeResponder() + { + llassert(mProcessed); } virtual void completedRaw(U32 status, const std::string& reason, @@ -638,16 +684,24 @@ void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id) mPhysicsShapeRequests.insert(mesh_id); } +void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ + if (!LLAppViewer::isQuitting()) + { + loadMeshLOD(mesh_params, lod); + } +} -void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) -{ //protected by mSignal, no locking needed here + +void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //could be called from any thread + LLMutexLock lock(mMutex); mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); if (iter != mMeshHeader.end()) { //if we have the header, request LOD byte range LODRequest req(mesh_params, lod); { - LLMutexLock lock(mMutex); mLODReqQ.push(req); LLMeshRepository::sLODProcessing++; } @@ -665,7 +719,6 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) } else { //if no header request is pending, fetch header - LLMutexLock lock(mMutex); mHeaderReqQ.push(req); mPendingLOD[mesh_params].push_back(lod); } @@ -945,6 +998,34 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) return ret; } +//static +void LLMeshRepoThread::incActiveLODRequests() +{ + LLMutexLock lock(gMeshRepo.mThread->mMutex); + ++LLMeshRepoThread::sActiveLODRequests; +} + +//static +void LLMeshRepoThread::decActiveLODRequests() +{ + LLMutexLock lock(gMeshRepo.mThread->mMutex); + --LLMeshRepoThread::sActiveLODRequests; +} + +//static +void LLMeshRepoThread::incActiveHeaderRequests() +{ + LLMutexLock lock(gMeshRepo.mThread->mMutex); + ++LLMeshRepoThread::sActiveHeaderRequests; +} + +//static +void LLMeshRepoThread::decActiveHeaderRequests() +{ + LLMutexLock lock(gMeshRepo.mThread->mMutex); + --LLMeshRepoThread::sActiveHeaderRequests; +} + //return false if failed to get header bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count) { @@ -1821,6 +1902,8 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + mProcessed = true; + // thread could have already be destroyed during logout if( !gMeshRepo.mThread ) { @@ -1838,11 +1921,13 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, { if (status == 499 || status == 503) { //timeout or service unavailable, try again + llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); } else { + llassert(status == 499 || status == 503); //intentionally trigger a breakpoint llwarns << "Unhandled status " << status << llendl; } return; @@ -1881,6 +1966,8 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + mProcessed = true; + // thread could have already be destroyed during logout if( !gMeshRepo.mThread ) { @@ -1898,11 +1985,13 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason { if (status == 499 || status == 503) { //timeout or service unavailable, try again + llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); } else { + llassert(status == 499 || status == 503); //intentionally trigger a breakpoint llwarns << "Unhandled status " << status << llendl; } return; @@ -1941,6 +2030,8 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + mProcessed = true; + if( !gMeshRepo.mThread ) { return; @@ -1957,11 +2048,13 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r { if (status == 499 || status == 503) { //timeout or service unavailable, try again + llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; gMeshRepo.mThread->loadMeshDecomposition(mMeshID); } else { + llassert(status == 499 || status == 503); //intentionally trigger a breakpoint llwarns << "Unhandled status " << status << llendl; } return; @@ -2000,6 +2093,8 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + mProcessed = true; + // thread could have already be destroyed during logout if( !gMeshRepo.mThread ) { @@ -2017,11 +2112,13 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re { if (status == 499 || status == 503) { //timeout or service unavailable, try again + llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); } else { + llassert(status == 499 || status == 503); //intentionally trigger a breakpoint llwarns << "Unhandled status " << status << llendl; } return; @@ -2060,6 +2157,8 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { + mProcessed = true; + // thread could have already be destroyed during logout if( !gMeshRepo.mThread ) { @@ -2078,8 +2177,12 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, // TODO*: Add maximum retry logic, exponential backoff // and (somewhat more optional than the others) retries // again after some set period of time + + llassert(status == 503 || status == 499); + if (status == 503 || status == 499) { //retry + llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; LLMeshRepoThread::HeaderRequest req(mMeshParams); LLMutexLock lock(gMeshRepo.mThread->mMutex); @@ -2087,6 +2190,10 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, return; } + else + { + llwarns << "Unhandled status." << llendl; + } } S32 data_size = buffer->countAfter(channels.in(), NULL); @@ -2101,7 +2208,11 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, LLMeshRepository::sBytesReceived += llmin(data_size, 4096); - if (!gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size)) + bool success = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size); + + llassert(success); + + if (!success) { llwarns << "Unable to parse mesh header: " diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 6e301c26a2..8602271f84 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -322,7 +322,9 @@ public: virtual void run(); + void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count); bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count); bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size); @@ -351,6 +353,10 @@ public: // (should hold onto mesh_id and try again later if header info does not exist) bool fetchMeshPhysicsShape(const LLUUID& mesh_id); + static void incActiveLODRequests(); + static void decActiveLODRequests(); + static void incActiveHeaderRequests(); + static void decActiveHeaderRequests(); }; @@ -407,7 +413,7 @@ public: void startRequest() { ++mPendingUploads; } void stopRequest() { --mPendingUploads; } - + bool finished() { return mFinished; } virtual void run(); void preStart(); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..36234b9536 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -186,8 +186,11 @@ private: // Populate the menu with items like "New Skin", "New Pants", etc. static void populateCreateWearableSubmenus(LLMenuGL* menu) { - LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); - LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); + // MAINT-2276...these menus are created as dummies because they are not available + // when this function is called. This prevents their parent from popping up later. + // + //LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE); + //LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE); for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) { @@ -200,8 +203,11 @@ private: p.on_click.function_name = "Wearable.Create"; p.on_click.parameter = LLSD(type_name); - LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? - menu_clothes : menu_bp; + //LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; + // This is a work-around for MAINT-2276 wherein the parent toggleable menu does not appear + // It puts everything under one menu, but that menu appears, which is better than not. + // + LLView* parent = menu; LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); } } diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 51ab7649a4..e641370d2e 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -425,7 +425,7 @@ void LLPanelPermissions::refresh() } } - getChildView("button set group")->setEnabled(owners_identical && (mOwnerID == gAgent.getID()) && is_nonpermanent_enforced); + getChildView("button set group")->setEnabled(root_selected && owners_identical && (mOwnerID == gAgent.getID()) && is_nonpermanent_enforced); getChildView("Name:")->setEnabled(TRUE); LLLineEditor* LineEditorObjectName = getChild<LLLineEditor>("Object Name"); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 13845c3b38..343316d30a 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -211,7 +211,6 @@ LLSelectMgr::LLSelectMgr() mGridMode = GRID_MODE_WORLD; gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD); - mGridValid = FALSE; mSelectedObjects = new LLObjectSelection(); mHoverObjects = new LLObjectSelection(); @@ -1170,7 +1169,6 @@ void LLSelectMgr::setGridMode(EGridMode mode) mGridMode = mode; gSavedSettings.setS32("GridMode", mode); updateSelectionCenter(); - mGridValid = FALSE; } void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale) @@ -1271,7 +1269,6 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & origin = mGridOrigin; rotation = mGridRotation; scale = mGridScale; - mGridValid = TRUE; } //----------------------------------------------------------------------------- @@ -2941,116 +2938,148 @@ BOOL LLSelectMgr::selectGetRootsCopy() return TRUE; } -//----------------------------------------------------------------------------- -// selectGetCreator() -// Creator information only applies to root objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) +struct LLSelectGetFirstTest { - BOOL identical = TRUE; - BOOL first = TRUE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) + LLSelectGetFirstTest() : mIdentical(true), mFirst(true) { } + virtual ~LLSelectGetFirstTest() { } + + // returns false to break out of the iteration. + bool checkMatchingNode(LLSelectNode* node) { - LLSelectNode* node = *iter; - if (!node->mValid) + if (!node || !node->mValid) { - return FALSE; + return false; } - if (first) + if (mFirst) { - first_id = node->mPermissions->getCreator(); - first = FALSE; + mFirstValue = getValueFromNode(node); + mFirst = false; } else { - if ( !(first_id == node->mPermissions->getCreator() ) ) + if ( mFirstValue != getValueFromNode(node) ) + { + mIdentical = false; + // stop testing once we know not all selected are identical. + return false; + } + } + // continue testing. + return true; + } + + bool mIdentical; + LLUUID mFirstValue; + +protected: + virtual const LLUUID& getValueFromNode(LLSelectNode* node) = 0; + +private: + bool mFirst; +}; + +void LLSelectMgr::getFirst(LLSelectGetFirstTest* test) +{ + if (gSavedSettings.getBOOL("EditLinkedParts")) + { + for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); + iter != getSelection()->valid_end(); ++iter ) + { + if (!test->checkMatchingNode(*iter)) { - identical = FALSE; break; } } } - if (first_id.isNull()) + else + { + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); ++iter ) + { + if (!test->checkMatchingNode(*iter)) + { + break; + } + } + } +} + +//----------------------------------------------------------------------------- +// selectGetCreator() +// Creator information only applies to roots unless editing linked parts. +//----------------------------------------------------------------------------- +struct LLSelectGetFirstCreator : public LLSelectGetFirstTest +{ +protected: + virtual const LLUUID& getValueFromNode(LLSelectNode* node) + { + return node->mPermissions->getCreator(); + } +}; + +BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) +{ + LLSelectGetFirstCreator test; + getFirst(&test); + + if (test.mFirstValue.isNull()) { name = LLTrans::getString("AvatarNameNobody"); return FALSE; } - result_id = first_id; + result_id = test.mFirstValue; - if (identical) + if (test.mIdentical) { - name = LLSLURL("agent", first_id, "inspect").getSLURLString(); + name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); } else { name = LLTrans::getString("AvatarNameMultiple"); } - return identical; + return test.mIdentical; } - //----------------------------------------------------------------------------- // selectGetOwner() -// Owner information only applies to roots. +// Owner information only applies to roots unless editing linked parts. //----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) +struct LLSelectGetFirstOwner : public LLSelectGetFirstTest { - BOOL identical = TRUE; - BOOL first = TRUE; - BOOL first_group_owned = FALSE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) +protected: + virtual const LLUUID& getValueFromNode(LLSelectNode* node) { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - node->mPermissions->getOwnership(first_id, first_group_owned); - first = FALSE; - } - else - { - LLUUID owner_id; - BOOL is_group_owned = FALSE; - if (!(node->mPermissions->getOwnership(owner_id, is_group_owned)) - || owner_id != first_id || is_group_owned != first_group_owned) - { - identical = FALSE; - break; - } - } + // Don't use 'getOwnership' since we return a reference, not a copy. + // Will return LLUUID::null if unowned (which is not allowed and should never happen.) + return node->mPermissions->isGroupOwned() ? node->mPermissions->getGroup() : node->mPermissions->getOwner(); } - if (first_id.isNull()) +}; + +BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) +{ + LLSelectGetFirstOwner test; + getFirst(&test); + + if (test.mFirstValue.isNull()) { return FALSE; } - result_id = first_id; + result_id = test.mFirstValue; - if (identical) + if (test.mIdentical) { - BOOL public_owner = (first_id.isNull() && !first_group_owned); - if (first_group_owned) + bool group_owned = selectIsGroupOwned(); + if (group_owned) { - name = LLSLURL("group", first_id, "inspect").getSLURLString(); - } - else if(!public_owner) - { - name = LLSLURL("agent", first_id, "inspect").getSLURLString(); + name = LLSLURL("group", test.mFirstValue, "inspect").getSLURLString(); } else { - name = LLTrans::getString("AvatarNameNobody"); + name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); } } else @@ -3058,131 +3087,92 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) name = LLTrans::getString("AvatarNameMultiple"); } - return identical; + return test.mIdentical; } - //----------------------------------------------------------------------------- // selectGetLastOwner() -// Owner information only applies to roots. +// Owner information only applies to roots unless editing linked parts. //----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) +struct LLSelectGetFirstLastOwner : public LLSelectGetFirstTest { - BOOL identical = TRUE; - BOOL first = TRUE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) +protected: + virtual const LLUUID& getValueFromNode(LLSelectNode* node) { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - first_id = node->mPermissions->getLastOwner(); - first = FALSE; - } - else - { - if ( !(first_id == node->mPermissions->getLastOwner() ) ) - { - identical = FALSE; - break; - } - } + return node->mPermissions->getLastOwner(); } - if (first_id.isNull()) +}; + +BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) +{ + LLSelectGetFirstLastOwner test; + getFirst(&test); + + if (test.mFirstValue.isNull()) { return FALSE; } - result_id = first_id; + result_id = test.mFirstValue; - if (identical) + if (test.mIdentical) { - BOOL public_owner = (first_id.isNull()); - if(!public_owner) - { - name = LLSLURL("agent", first_id, "inspect").getSLURLString(); - } - else - { - name.assign("Public or Group"); - } + name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); } else { name.assign( "" ); } - return identical; + return test.mIdentical; } - //----------------------------------------------------------------------------- // selectGetGroup() -// Group information only applies to roots. +// Group information only applies to roots unless editing linked parts. //----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id) +struct LLSelectGetFirstGroup : public LLSelectGetFirstTest { - BOOL identical = TRUE; - BOOL first = TRUE; - LLUUID first_id; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) +protected: + virtual const LLUUID& getValueFromNode(LLSelectNode* node) { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - first_id = node->mPermissions->getGroup(); - first = FALSE; - } - else - { - if ( !(first_id == node->mPermissions->getGroup() ) ) - { - identical = FALSE; - break; - } - } + return node->mPermissions->getGroup(); } +}; - result_id = first_id; +BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id) +{ + LLSelectGetFirstGroup test; + getFirst(&test); - return identical; + result_id = test.mFirstValue; + return test.mIdentical; } //----------------------------------------------------------------------------- // selectIsGroupOwned() -// Only operates on root nodes. -// Returns TRUE if all have valid data and they are all group owned. +// Only operates on root nodes unless editing linked parts. +// Returns TRUE if the first selected is group owned. //----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectIsGroupOwned() +struct LLSelectGetFirstGroupOwner : public LLSelectGetFirstTest { - BOOL found_one = FALSE; - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); iter++ ) +protected: + virtual const LLUUID& getValueFromNode(LLSelectNode* node) { - LLSelectNode* node = *iter; - if (!node->mValid) + if (node->mPermissions->isGroupOwned()) { - return FALSE; - } - found_one = TRUE; - if (!node->mPermissions->isGroupOwned()) - { - return FALSE; + return node->mPermissions->getGroup(); } - } - return found_one ? TRUE : FALSE; + return LLUUID::null; + } +}; + +BOOL LLSelectMgr::selectIsGroupOwned() +{ + LLSelectGetFirstGroupOwner test; + getFirst(&test); + + return test.mFirstValue.notNull() ? TRUE : FALSE; } //----------------------------------------------------------------------------- @@ -4987,7 +4977,11 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data } func(id); LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); - if (node) + if (!node) + { + llwarns << "Couldn't find object " << id << " selected." << llendl; + } + else { if (node->mInventorySerial != inv_serial) { diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index ecbb20df1b..cc78e35869 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -343,6 +343,9 @@ typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle; extern template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance(); #endif +// For use with getFirstTest() +struct LLSelectGetFirstTest; + class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr> { public: @@ -745,6 +748,9 @@ private: static void packGodlikeHead(void* user_data); static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle); + // Get the first ID that matches test and whether or not all ids are identical in selected objects. + void getFirst(LLSelectGetFirstTest* test); + public: // Observer/callback support for when object selection changes or // properties are received/updated @@ -763,8 +769,6 @@ private: LLVector3 mGridOrigin; LLVector3 mGridScale; EGridMode mGridMode; - BOOL mGridValid; - BOOL mTEMode; // render te LLVector3d mSelectionCenterGlobal; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 47a2b5f4c8..41bfbae86e 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -3212,6 +3212,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 worker->lockWorkMutex(); + // Copy header data into image object worker->mImageCodec = codec; worker->mTotalPackets = packets; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 29528dabc9..1e58ba35d4 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -39,6 +39,7 @@ #include "llimageworker.h" #include "llstat.h" #include "llcurl.h" +#include "llstat.h" #include "httprequest.h" #include "httpoptions.h" #include "httpheaders.h" diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index 673d0c24cf..6a8fad0134 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -26,73 +26,76 @@ */ #include "llviewerprecompiledheaders.h" +#include <iostream> +#include <sstream> #include "llversioninfo.h" -#include "llversionviewer.h" +#if ! defined(LL_VIEWER_CHANNEL) \ + || ! defined(LL_VIEWER_VERSION_MAJOR) \ + || ! defined(LL_VIEWER_VERSION_MINOR) \ + || ! defined(LL_VIEWER_VERSION_PATCH) \ + || ! defined(LL_VIEWER_VERSION_BUILD) + #error "Channel or Version information is undefined" +#endif + +const char * const LL_CHANNEL = LL_VIEWER_CHANNEL; // -// Set the version numbers in indra/llcommon/llversionviewer.h +// Set the version numbers in indra/VIEWER_VERSION // //static S32 LLVersionInfo::getMajor() { - return LL_VERSION_MAJOR; + return LL_VIEWER_VERSION_MAJOR; } //static S32 LLVersionInfo::getMinor() { - return LL_VERSION_MINOR; + return LL_VIEWER_VERSION_MINOR; } //static S32 LLVersionInfo::getPatch() { - return LL_VERSION_PATCH; + return LL_VIEWER_VERSION_PATCH; } //static S32 LLVersionInfo::getBuild() { - return LL_VERSION_BUILD; + return LL_VIEWER_VERSION_BUILD; } //static const std::string &LLVersionInfo::getVersion() { static std::string version(""); - if (version.empty()) { - // cache the version string std::ostringstream stream; - stream << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH << "." - << LL_VERSION_BUILD; + stream << LLVersionInfo::getShortVersion() << "." << LLVersionInfo::getBuild(); + // cache the version string version = stream.str(); } - return version; } //static const std::string &LLVersionInfo::getShortVersion() { - static std::string version(""); - - if (version.empty()) + static std::string short_version(""); + if(short_version.empty()) { // cache the version string std::ostringstream stream; - stream << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH; - version = stream.str(); + stream << LL_VIEWER_VERSION_MAJOR << "." + << LL_VIEWER_VERSION_MINOR << "." + << LL_VIEWER_VERSION_PATCH; + short_version = stream.str(); } - - return version; + return short_version; } namespace @@ -100,7 +103,7 @@ namespace /// Storage of the channel name the viewer is using. // The channel name is set by hardcoded constant, // or by calling LLVersionInfo::resetChannel() - std::string sWorkingChannelName(LL_CHANNEL); + std::string sWorkingChannelName(LL_VIEWER_CHANNEL); // Storage for the "version and channel" string. // This will get reset too. @@ -113,11 +116,7 @@ const std::string &LLVersionInfo::getChannelAndVersion() if (sVersionChannel.empty()) { // cache the version string - std::ostringstream stream; - stream << LLVersionInfo::getChannel() - << " " - << LLVersionInfo::getVersion(); - sVersionChannel = stream.str(); + sVersionChannel = LLVersionInfo::getChannel() + " " + LLVersionInfo::getVersion(); } return sVersionChannel; diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h index 6f64544f3b..077105cae8 100644 --- a/indra/newview/llversioninfo.h +++ b/indra/newview/llversioninfo.h @@ -29,6 +29,7 @@ #define LL_LLVERSIONINFO_H #include <string> +#include "stdtypes.h" /// /// This API provides version information for the viewer. This diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index f5d3341c66..1aa9fd8a45 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -160,11 +160,6 @@ void agent_push_backward( EKeystate s ) camera_move_backward(s); return; } - else if (gAgentAvatarp->isSitting()) - { - gAgentCamera.changeCameraToThirdPerson(); - return; - } agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 47059b0b8c..2df028de69 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -316,9 +316,13 @@ public: /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) { LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; - LL_WARNS("MediaAuth") << content << LL_ENDL; + + LLSD stripped_content = content; + stripped_content.erase("set-cookie"); + LL_WARNS("MediaAuth") << stripped_content << LL_ENDL; std::string cookie = content["set-cookie"].asString(); + LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index d613ac9651..93e4f4428a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1639,6 +1639,54 @@ class LLAdvancedForceParamsToDefault : public view_listener_t }; +////////////////////////// +// ANIMATION SPEED // +////////////////////////// + +// Utility function to set all AV time factors to the same global value +static void set_all_animation_time_factors(F32 time_factor) +{ + LLMotionController::setCurrentTimeFactor(time_factor); + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + (*iter)->setAnimTimeFactor(time_factor); + } +} + +class LLAdvancedAnimTenFaster : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + //llinfos << "LLAdvancedAnimTenFaster" << llendl; + F32 time_factor = LLMotionController::getCurrentTimeFactor(); + time_factor = llmin(time_factor + 0.1f, 2.f); // Upper limit is 200% speed + set_all_animation_time_factors(time_factor); + return true; + } +}; + +class LLAdvancedAnimTenSlower : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + //llinfos << "LLAdvancedAnimTenSlower" << llendl; + F32 time_factor = LLMotionController::getCurrentTimeFactor(); + time_factor = llmax(time_factor - 0.1f, 0.1f); // Lower limit is at 10% of normal speed + set_all_animation_time_factors(time_factor); + return true; + } +}; + +class LLAdvancedAnimResetAll : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + set_all_animation_time_factors(1.f); + return true; + } +}; + ////////////////////////// // RELOAD VERTEX SHADER // @@ -3909,25 +3957,27 @@ class LLViewToggleUI : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLNotification::Params params("ConfirmHideUI"); - params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); - LLSD substitutions; + if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK) + { + LLNotification::Params params("ConfirmHideUI"); + params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); + LLSD substitutions; #if LL_DARWIN - substitutions["SHORTCUT"] = "Cmd+Shift+U"; + substitutions["SHORTCUT"] = "Cmd+Shift+U"; #else - substitutions["SHORTCUT"] = "Ctrl+Shift+U"; + substitutions["SHORTCUT"] = "Ctrl+Shift+U"; #endif - params.substitutions = substitutions; - if (gViewerWindow->getUIVisibility()) - { - // hiding, so show notification - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); + params.substitutions = substitutions; + if (!gSavedSettings.getBOOL("HideUIControls")) + { + // hiding, so show notification + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } } - return true; } @@ -3937,8 +3987,9 @@ class LLViewToggleUI : public view_listener_t if (option == 0) // OK { - gViewerWindow->setUIVisibility(!gViewerWindow->getUIVisibility()); - LLPanelStandStopFlying::getInstance()->setVisible(gViewerWindow->getUIVisibility()); + gViewerWindow->setUIVisibility(gSavedSettings.getBOOL("HideUIControls")); + LLPanelStandStopFlying::getInstance()->setVisible(gSavedSettings.getBOOL("HideUIControls")); + gSavedSettings.setBOOL("HideUIControls",!gSavedSettings.getBOOL("HideUIControls")); } } }; @@ -7506,6 +7557,7 @@ class LLToolsUseSelectionForGrid : public view_listener_t } func; LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); + LLFloaterTools::setGridMode((S32)GRID_MODE_REF_OBJECT); return true; } }; @@ -8437,6 +8489,11 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale"); view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale"); + // Advanced > Character > Animation Speed + view_listener_t::addMenu(new LLAdvancedAnimTenFaster(), "Advanced.AnimTenFaster"); + view_listener_t::addMenu(new LLAdvancedAnimTenSlower(), "Advanced.AnimTenSlower"); + view_listener_t::addMenu(new LLAdvancedAnimResetAll(), "Advanced.AnimResetAll"); + // Advanced > Character (toplevel) view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault"); view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader"); diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 7e524df3f6..77e382b8c7 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1540,16 +1540,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // Actually extract the data. if (parcel) { - if (parcel->getLocalID() != INVALID_PARCEL_ID - && parcel->getLocalID() != local_id) - { - // The parcel has a valid parcel ID but it doesn't match the parcel - // for the data received. - llinfos << "Expecting data for parcel " << parcel->getLocalID() \ - << " but got data for parcel " << local_id << llendl; - return; - } - parcel->init(owner_id, FALSE, FALSE, FALSE, claim_date, claim_price_per_meter, rent_price_per_meter, diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 4b0e0598f6..ba9818946c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2025,18 +2025,19 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { gObjectPreviewProgram.mName = "Simple Shader"; - gObjectPreviewProgram.mFeatures.calculatesLighting = true; - gObjectPreviewProgram.mFeatures.calculatesAtmospherics = true; - gObjectPreviewProgram.mFeatures.hasGamma = true; - gObjectPreviewProgram.mFeatures.hasAtmospherics = true; - gObjectPreviewProgram.mFeatures.hasLighting = true; + gObjectPreviewProgram.mFeatures.calculatesLighting = false; + gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false; + gObjectPreviewProgram.mFeatures.hasGamma = false; + gObjectPreviewProgram.mFeatures.hasAtmospherics = false; + gObjectPreviewProgram.mFeatures.hasLighting = false; gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0; gObjectPreviewProgram.mFeatures.disableTextureIndex = true; gObjectPreviewProgram.mShaderFiles.clear(); gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; success = gObjectPreviewProgram.createShader(NULL, NULL); + gObjectPreviewProgram.mFeatures.hasLighting = true; } if (success) diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp index 91e485d01b..f9a725547f 100644 --- a/indra/newview/llviewerstatsrecorder.cpp +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -187,6 +187,7 @@ void LLViewerStatsRecorder::writeToLog( F32 interval ) << mObjectUpdateFailures << " update failures" << llendl; + U32 data_size; if (mObjectCacheFile == NULL) { mStartTime = LLTimer::getTotalSeconds(); @@ -216,7 +217,11 @@ void LLViewerStatsRecorder::writeToLog( F32 interval ) << "Texture Fetch bps\t" << "\n"; - fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); + data_size = data_msg.str().size(); + if (fwrite(data_msg.str().c_str(), 1, data_size, mObjectCacheFile ) != data_size) + { + llwarns << "failed to write full headers to " << STATS_FILE_NAME << llendl; + } } else { @@ -249,7 +254,12 @@ void LLViewerStatsRecorder::writeToLog( F32 interval ) << "\t" << (mTextureFetchSize * 8 / delta_time) << "\n"; - fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); + data_size = data_msg.str().size(); + if (fwrite(data_msg.str().c_str(), 1, data_size, mObjectCacheFile ) != data_size) + { + llwarns << "failed to write full stats to " << STATS_FILE_NAME << llendl; + } + clearStats(); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 48a69129eb..2d9c127b87 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -34,6 +34,7 @@ #include <fstream> #include <algorithm> #include <boost/lambda/core.hpp> +#include <boost/regex.hpp> #include "llagent.h" #include "llagentcamera.h" @@ -2235,29 +2236,42 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) // no l10n problem because channel is always an english string std::string channel = LLVersionInfo::getChannel(); - bool isProject = (channel.find("Project") != std::string::npos); + static const boost::regex is_beta_channel("\\bBeta\\b"); + static const boost::regex is_project_channel("\\bProject\\b"); + static const boost::regex is_test_channel("\\bTest$"); // god more important than project, proj more important than grid - if(god_mode && LLGridManager::getInstance()->isInProductionGrid()) + if ( god_mode ) { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" ); - } - else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid()) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); + if ( LLGridManager::getInstance()->isInProductionGrid() ) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" ); + } + else + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); + } } - else if (!god_mode && isProject) + else if (boost::regex_search(channel, is_beta_channel)) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBetaBgColor" ); + } + else if (boost::regex_search(channel, is_project_channel)) { new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" ); - } - else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid()) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); - } - else - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); - } + } + else if (boost::regex_search(channel, is_test_channel)) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarTestBgColor" ); + } + else if(!LLGridManager::getInstance()->isInProductionGrid()) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); + } + else + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); + } if(gMenuBarView) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 765f2b3a5a..2051772d63 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -761,7 +761,16 @@ void LLPipeline::resizeScreenTexture() GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resY = gViewerWindow->getWorldViewHeightRaw(); - allocateScreenBuffer(resX,resY); + if (!allocateScreenBuffer(resX,resY)) + { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled + //NOTE: if the session closes successfully after this call, deferred rendering will be + // disabled on future sessions + if (LLPipeline::sRenderDeferred) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + LLPipeline::refreshCachedSettings(); + } + } } } @@ -6113,7 +6122,7 @@ void LLPipeline::enableLightsPreview() LLVector4 light_pos(dir0, 0.0f); - LLLightState* light = gGL.getLight(0); + LLLightState* light = gGL.getLight(1); light->enable(); light->setPosition(light_pos); @@ -6125,7 +6134,7 @@ void LLPipeline::enableLightsPreview() light_pos = LLVector4(dir1, 0.f); - light = gGL.getLight(1); + light = gGL.getLight(2); light->enable(); light->setPosition(light_pos); light->setDiffuse(diffuse1); @@ -6135,7 +6144,7 @@ void LLPipeline::enableLightsPreview() light->setSpotCutoff(180.f); light_pos = LLVector4(dir2, 0.f); - light = gGL.getLight(2); + light = gGL.getLight(3); light->enable(); light->setPosition(light_pos); light->setDiffuse(diffuse2); diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index df75f3f697..8587243791 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -135,8 +135,8 @@ TOOLNO CURSOR "llno.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,1,1,0 - PRODUCTVERSION 2,1,1,0 + FILEVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},${VIEWER_VERSION_REVISION} + PRODUCTVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},${VIEWER_VERSION_REVISION} FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -153,12 +153,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.1.1.0" + VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" VALUE "InternalName", "Second Life" - VALUE "LegalCopyright", "Copyright � 2001-2010, Linden Research, Inc." + VALUE "LegalCopyright", "Copyright � 2001, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.1.1.0" + VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 9bf2922033..02e2ad2ff7 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -99,6 +99,9 @@ name="MdBlue" value=".07 .38 .51 1" /> <color + name="DkBlue" + value=".06 .06 .3 1" /> + <color name="LtRed" value="1 0.2 0.2 1" /> <color @@ -108,6 +111,9 @@ name="Red_80" value="1 0 0 0.8" /> <color + name="DkRed" + value="0.3 0.06 0.06 1" /> + <color name="Green_80" value="0 1 0 0.8" /> <color @@ -824,9 +830,14 @@ name="ChatTimestampColor" reference="White" /> <color + name="MenuBarBetaBgColor" + reference="DkBlue" /> + <color name="MenuBarProjectBgColor" reference="MdBlue" /> - + <color + name="MenuBarTestBgColor" + reference="DkRed" /> <color name="MeshImportTableNormalColor" value="1 1 1 1"/> diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index e91f5af3d5..29720a680b 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -3,7 +3,7 @@ layout="topleft" left="0" mouse_opaque="false" - can_tear_off="true" + can_tear_off="false" name="menu_inventory_add" visible="false"> <menu diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 3fe56e3457..caa36e7302 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3186,6 +3186,40 @@ parameter="AllowSelectAvatar" /> </menu_item_check> </menu> + <menu + create_jump_keys="true" + label="Animation Speed" + name="Animation Speed" + tear_off="true"> + <menu_item_call + label="All Animations 10% Faster" + name="All Animations 10 Faster"> + <menu_item_call.on_click + function="Advanced.AnimTenFaster" /> + </menu_item_call> + <menu_item_call + label="All Animations 10% Slower" + name="All Animations 10 Slower"> + <menu_item_call.on_click + function="Advanced.AnimTenSlower" /> + </menu_item_call> + <menu_item_call + label="Reset All Animation Speed" + name="Reset All Animation Speed"> + <menu_item_call.on_click + function="Advanced.AnimResetAll" /> + </menu_item_call> + <menu_item_check + label="Slow Motion Animations" + name="Slow Motion Animations"> + <menu_item_check.on_check + function="CheckControl" + parameter="SlowMotionAnimation" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="SlowMotionAnimation" /> + </menu_item_check> + </menu> <menu_item_call label="Force Params to Default" name="Force Params to Default"> @@ -3203,16 +3237,6 @@ parameter="" /> </menu_item_check> <menu_item_check - label="Slow Motion Animations" - name="Slow Motion Animations"> - <menu_item_check.on_check - function="CheckControl" - parameter="SlowMotionAnimation" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="SlowMotionAnimation" /> - </menu_item_check> - <menu_item_check label="Show Look At" name="Show Look At"> <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index da906ca669..2319729339 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1293,6 +1293,45 @@ Visit [_URL] for more information? <notification icon="alertmodal.tga" + name="AMDOldDriver" + type="alertmodal"> + There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. + + Visit [_URL] to check for driver updates? + <tag>confirm</tag> + <url option="0" name="url"> + http://support.amd.com/us/Pages/AMDSupportHub.aspx + </url> + <usetemplate + ignoretext="My graphics driver is out of date" + name="okcancelignore" + notext="No" + yestext="Yes"/> + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="NVIDIAOldDriver" + type="alertmodal"> + There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance. + + Visit [_URL] to check for driver updates? + <tag>confirm</tag> + <url option="0" name="url"> + http://www.nvidia.com/Download/index.aspx?lang=en-us + </url> + <usetemplate + ignoretext="My graphics driver is out of date" + name="okcancelignore" + notext="No" + yestext="Yes"/> + <tag>fail</tag> + </notification> + + + <notification + icon="alertmodal.tga" name="UnknownGPU" type="alertmodal"> Your system contains a graphics card that [APP_NAME] doesn't recognize. @@ -3413,7 +3452,7 @@ or you can install it now. name="DownloadBackgroundTip" type="notify"> We have downloaded an update to your [APP_NAME] installation. -Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] +Version [VERSION] [[INFO_URL] Information about this update] <tag>confirm</tag> <usetemplate name="okcancelbuttons" @@ -3426,7 +3465,7 @@ Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] name="DownloadBackgroundDialog" type="alertmodal"> We have downloaded an update to your [APP_NAME] installation. -Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] +Version [VERSION] [[INFO_URL] Information about this update] <tag>confirm</tag> <usetemplate name="okcancelbuttons" @@ -3439,7 +3478,7 @@ Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] name="RequiredUpdateDownloadedVerboseDialog" type="alertmodal"> We have downloaded a required software update. -Version [VERSION] +Version [VERSION] [[INFO_URL] Information about this update] We must restart [APP_NAME] to install the update. <tag>confirm</tag> @@ -3453,6 +3492,66 @@ We must restart [APP_NAME] to install the update. name="RequiredUpdateDownloadedDialog" type="alertmodal"> We must restart [APP_NAME] to install the update. +[[INFO_URL] Information about this update] + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="notify.tga" + name="OtherChannelDownloadBackgroundTip" + type="notify"> +We have downloaded an update to your [APP_NAME] installation. +Version [VERSION] +This experimental viewer has been replaced by a [NEW_CHANNEL] viewer; +see [[INFO_URL] for details about this update] + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Later..." + yestext="Install now and restart [APP_NAME]"/> + </notification> + + <notification + icon="alertmodal.tga" + name="OtherChannelDownloadBackgroundDialog" + type="alertmodal"> +We have downloaded an update to your [APP_NAME] installation. +Version [VERSION] +This experimental viewer has been replaced by a [NEW_CHANNEL] viewer; +see [[INFO_URL] Information about this update] + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Later..." + yestext="Install now and restart [APP_NAME]"/> + </notification> + + <notification + icon="alertmodal.tga" + name="OtherChannelRequiredUpdateDownloadedVerboseDialog" + type="alertmodal"> +We have downloaded a required software update. +Version [VERSION] +This experimental viewer has been replaced by a [NEW_CHANNEL] viewer; +see [[INFO_URL] Information about this update] + +We must restart [APP_NAME] to install the update. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="OtherChannelRequiredUpdateDownloadedDialog" + type="alertmodal"> +We must restart [APP_NAME] to install the update. +This experimental viewer has been replaced by a [NEW_CHANNEL] viewer; +see [[INFO_URL] Information about this update] <tag>confirm</tag> <usetemplate name="okbutton" @@ -8835,14 +8934,6 @@ Cannot save to object contents: This would modify the attachment permissions. <notification icon="alertmodal.tga" - name="NoPermToEdit" - type="notify"> - <tag>fail</tag> -Not permitted to edit this! - </notification> - - <notification - icon="alertmodal.tga" name="TooManyScripts" type="notify"> <tag>fail</tag> @@ -8883,47 +8974,6 @@ You cannot modify the navmesh across region boundaries. <notification icon="alertmodal.tga" - name="NoPermModifyObject" - type="notify"> - <tag>fail</tag> -You don't have permission to modify that object. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysObjContributesToNav" - type="notify"> - <tag>fail</tag> -Can't enable physics for an object that contributes to the navmesh. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysKeyframedObj" - type="notify"> - <tag>fail</tag> -Can't enable physics for keyframed objects. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysNotEnoughLandResources" - type="notify"> - <tag>fail</tag> -Can't enable physics for object -- insufficient land resources. - </notification> - - <notification - icon="alertmodal.tga" - name="CantEnablePhysCostTooGreat" - persist="true" - type="notify"> - <tag>fail</tag> -Can't enable physics for object with physics resource cost greater than [MAX_OBJECTS] - </notification> - - <notification - icon="alertmodal.tga" name="NoSetPhysicsPropertiesOnObjectType" type="notify"> <tag>fail</tag> @@ -9940,5 +9990,12 @@ Inventory creation on in-world object failed. An internal error prevented us from properly updating your viewer. The L$ balance or parcel holdings displayed in your viewer may not reflect your actual balance on the servers. </notification> + <notification + icon="alertmodal.tga" + name="LargePrimAgentIntersect" + type="notify"> + <tag>fail</tag> +Cannot create large prims that intersect other players. Please re-try when other players have moved. + </notification> </notifications> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 849f3ef73d..cd243d40a4 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -147,12 +147,12 @@ height="12" layout="topleft" left_delta="87" - name="ShadersPrefText3" + name="ShadersPrefText2" top_delta="0" width="80"> Mid </text> - <text + <text type="string" length="1" follows="left|top" @@ -163,8 +163,8 @@ name="ShadersPrefText3" top_delta="0" width="80"> - High - </text> + High + </text> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 4aeea8823e..2fb6a9fd40 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -232,6 +232,19 @@ name="Install_manual" value="0" /> </combo_box> + <check_box + top_delta="4" + enabled="true" + follows="left|top" + height="14" + initial_value="true" + control_name="UpdateWillingToTest" + label="Willing to update to release candidates" + left_delta="0" + mouse_opaque="true" + name="update_willing_to_test" + width="400" + top_pad="5"/> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index 3f17324006..7e17ed6864 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -1982,7 +1982,7 @@ http://secondlife.com/viewer-access-faq 新腳本 </string> <string name="BusyModeResponseDefault"> - 你傳訊過去的居民目前處於忙碌狀態,這意味著他要求不被打擾。 你的訊息仍將留存並顯示於對���的 IM 面板上供稍後查閱。 + 你傳訊過去的居民目前處於忙碌狀態,這意味著他要求不被打擾。 你的訊息仍將留存並顯示於對方的 IM 面板上供稍後查閱。 </string> <string name="MuteByName"> (按名稱) diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 7705b4c567..a86230488b 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -208,11 +208,14 @@ std::string const & LLUpdaterService::pumpName(void) return wakka; } bool LLUpdaterService::updateReadyToInstall(void) { return false; } -void LLUpdaterService::initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version) {} +void LLUpdaterService::initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test + ) {} void LLUpdaterService::setCheckPeriod(unsigned int seconds) {} void LLUpdaterService::startChecking(bool install_if_ready) {} @@ -221,6 +224,12 @@ bool LLUpdaterService::isChecking() { return false; } LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; } std::string LLUpdaterService::updatedVersion() { return ""; } +bool llHashedUniqueID(unsigned char* id) +{ + memcpy( id, "66666666666666666666666666666666", MD5HEX_STR_SIZE ); + return true; +} + //----------------------------------------------------------------------------- #include "llnotifications.h" #include "llfloaterreg.h" diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp index 398d8f16ed..6b0be29c2d 100644 --- a/indra/newview/tests/llversioninfo_test.cpp +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -28,7 +28,6 @@ #include "../test/lltut.h" #include "../llversioninfo.h" -#include "llversionviewer.h" namespace tut { @@ -38,20 +37,20 @@ namespace tut : mResetChannel("Reset Channel") { std::ostringstream stream; - stream << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH << "." - << LL_VERSION_BUILD; + stream << LL_VIEWER_VERSION_MAJOR << "." + << LL_VIEWER_VERSION_MINOR << "." + << LL_VIEWER_VERSION_PATCH << "." + << LL_VIEWER_VERSION_BUILD; mVersion = stream.str(); stream.str(""); - stream << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH; + stream << LL_VIEWER_VERSION_MAJOR << "." + << LL_VIEWER_VERSION_MINOR << "." + << LL_VIEWER_VERSION_PATCH; mShortVersion = stream.str(); stream.str(""); - stream << LL_CHANNEL + stream << LL_VIEWER_CHANNEL << " " << mVersion; mVersionAndChannel = stream.str(); @@ -78,20 +77,19 @@ namespace tut { ensure_equals("Major version", LLVersionInfo::getMajor(), - LL_VERSION_MAJOR); + LL_VIEWER_VERSION_MAJOR); ensure_equals("Minor version", LLVersionInfo::getMinor(), - LL_VERSION_MINOR); + LL_VIEWER_VERSION_MINOR); ensure_equals("Patch version", LLVersionInfo::getPatch(), - LL_VERSION_PATCH); + LL_VIEWER_VERSION_PATCH); ensure_equals("Build version", LLVersionInfo::getBuild(), - LL_VERSION_BUILD); + LL_VIEWER_VERSION_BUILD); ensure_equals("Channel version", LLVersionInfo::getChannel(), - LL_CHANNEL); - + LL_VIEWER_CHANNEL); ensure_equals("Version String", LLVersionInfo::getVersion(), mVersion); diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index c09043b879..9f06dca17a 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -160,14 +160,6 @@ class ViewerManifest(LLManifest): if not self.path2basename(os.path.join(os.pardir, os.pardir), "summary.json"): print "No summary.json file" - def login_channel(self): - """Channel reported for login and upgrade purposes ONLY; - used for A/B testing""" - # NOTE: Do not return the normal channel if login_channel - # is not specified, as some code may branch depending on - # whether or not this is present - return self.args.get('login_channel') - def grid(self): return self.args['grid'] def channel(self): @@ -179,16 +171,24 @@ class ViewerManifest(LLManifest): def channel_lowerword(self): return self.channel_oneword().lower() + def app_name(self): + app_suffix='Test' + channel_type=self.channel_lowerword() + if channel_type == 'release' : + app_suffix='Viewer' + elif re.match('^(beta|project).*',channel_type) : + app_suffix=self.channel_unique() + return "Second Life "+app_suffix + def icon_path(self): icon_path="icons/" channel_type=self.channel_lowerword() - if channel_type == 'release' \ - or channel_type == 'development' \ - : + print "Icon channel type '%s'" % channel_type + if channel_type == 'release' : icon_path += channel_type - elif channel_type == 'betaviewer' : + elif re.match('^beta.*',channel_type) : icon_path += 'beta' - elif re.match('project.*',channel_type) : + elif re.match('^project.*',channel_type) : icon_path += 'project' else : icon_path += 'test' @@ -205,14 +205,6 @@ class ViewerManifest(LLManifest): "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ {'grid':self.grid()} - # set command line flags for channel - channel_flags = '' - if self.login_channel() and self.login_channel() != self.channel(): - # Report a special channel during login, but use default - channel_flags = '--channel "%s"' % (self.login_channel()) - elif not self.default_channel(): - channel_flags = '--channel "%s"' % self.channel() - # Deal with settings setting_flags = '' if not self.default_channel() or not self.default_grid(): @@ -223,7 +215,7 @@ class ViewerManifest(LLManifest): setting_flags = '--settings settings_%s_%s.xml'\ % (self.grid(), self.channel_lowerword()) - return " ".join((channel_flags, grid_flags, setting_flags)).strip() + return " ".join((grid_flags, setting_flags)).strip() def extract_names(self,src): try: @@ -250,13 +242,13 @@ class ViewerManifest(LLManifest): class WindowsManifest(ViewerManifest): def final_exe(self): - if self.default_channel(): - if self.default_grid(): - return "SecondLife.exe" - else: - return "SecondLifePreview.exe" - else: - return ''.join(self.channel().split()) + '.exe' + app_suffix="Test" + channel_type=self.channel_lowerword() + if channel_type == 'release' : + app_suffix='' + elif re.match('^(beta|project).*',channel_type) : + app_suffix=''.join(self.channel_unique().split()) + return "SecondLife"+app_suffix+".exe" def test_msvcrt_and_copy_action(self, src, dst): # This is used to test a dll manifest. @@ -304,26 +296,9 @@ class WindowsManifest(ViewerManifest): else: print "Doesn't exist:", src - ### DISABLED MANIFEST CHECKING for vs2010. we may need to reenable this - # shortly. If this hasn't been reenabled by the 2.9 viewer release then it - # should be deleted -brad - #def enable_crt_manifest_check(self): - # if self.is_packaging_viewer(): - # WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action - - #def enable_no_crt_manifest_check(self): - # if self.is_packaging_viewer(): - # WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action - - #def disable_manifest_check(self): - # if self.is_packaging_viewer(): - # del WindowsManifest.copy_action - def construct(self): super(WindowsManifest, self).construct() - #self.enable_crt_manifest_check() - if self.is_packaging_viewer(): # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe. self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe()) @@ -333,15 +308,11 @@ class WindowsManifest(ViewerManifest): 'llplugin', 'slplugin', self.args['configuration']), "slplugin.exe") - #self.disable_manifest_check() - self.path2basename("../viewer_components/updater/scripts/windows", "update_install.bat") # Get shared libs from the shared libs staging directory if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']), dst=""): - #self.enable_crt_manifest_check() - # Get llcommon and deps. If missing assume static linkage and continue. try: self.path('llcommon.dll') @@ -353,8 +324,6 @@ class WindowsManifest(ViewerManifest): print err.message print "Skipping llcommon.dll (assuming llcommon was linked statically)" - #self.disable_manifest_check() - # Mesh 3rd party libs needed for auto LOD and collada reading try: if self.args['configuration'].lower() == 'debug': @@ -418,8 +387,6 @@ class WindowsManifest(ViewerManifest): self.path("featuretable.txt") self.path("featuretable_xp.txt") - #self.enable_no_crt_manifest_check() - # Media plugins - QuickTime if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): self.path("media_plugin_quicktime.dll") @@ -499,15 +466,10 @@ class WindowsManifest(ViewerManifest): self.end_prefix() - #self.disable_manifest_check() - # 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'], dst="win_crash_logger.exe") -# For CHOP-397, windows updater no longer used. -# self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'], -# dst="updater.exe") if not self.is_packaging_viewer(): self.package_file = "copied_deps" @@ -570,6 +532,7 @@ class WindowsManifest(ViewerManifest): 'channel':self.channel(), 'channel_oneword':self.channel_oneword(), 'channel_unique':self.channel_unique(), + 'subchannel_underscores':'_'.join(self.channel_unique().split()) } version_vars = """ @@ -591,7 +554,7 @@ class WindowsManifest(ViewerManifest): Caption "Second Life" """ else: - # beta grid viewer + # alternate grid viewer installer_file = "Second_Life_%(version_dashes)s_(%(grid_caps)s)_Setup.exe" grid_vars_template = """ OutFile "%(installer_file)s" @@ -603,8 +566,8 @@ class WindowsManifest(ViewerManifest): Caption "Second Life %(grid)s ${VERSION}" """ else: - # some other channel on some grid - installer_file = "Second_Life_%(version_dashes)s_%(channel_oneword)s_Setup.exe" + # some other channel (grid name not used) + installer_file = "Second_Life_%(version_dashes)s_%(subchannel_underscores)s_Setup.exe" grid_vars_template = """ OutFile "%(installer_file)s" !define INSTFLAGS "%(flags)s" @@ -666,7 +629,7 @@ class DarwinManifest(ViewerManifest): self.path(self.args['configuration'] + "/Second Life.app", dst="") if self.prefix(src="", dst="Contents"): # everything goes in Contents - self.path("Info-SecondLife.plist", dst="Info.plist") + self.path("Info.plist", dst="Info.plist") # copy additional libs in <bundle>/Contents/MacOS/ self.path("../packages/lib/release/libndofdev.dylib", dst="Resources/libndofdev.dylib") @@ -696,7 +659,11 @@ class DarwinManifest(ViewerManifest): self.path("SecondLife.nib") # Translations - self.path("English.lproj") + self.path("English.lproj/language.txt") + self.replace_in(src="English.lproj/InfoPlist.strings", + dst="English.lproj/InfoPlist.strings", + searchdict={'%%VERSION%%':'.'.join(self.args['version'])} + ) self.path("German.lproj") self.path("Japanese.lproj") self.path("Korean.lproj") @@ -880,10 +847,7 @@ class DarwinManifest(ViewerManifest): # Copy everything in to the mounted .dmg - if self.default_channel() and not self.default_grid(): - app_name = "Second Life " + self.args['grid'] - else: - app_name = channel_standin.strip() + app_name = self.app_name() # Hack: # Because there is no easy way to coerce the Finder into positioning @@ -969,7 +933,6 @@ class LinuxManifest(ViewerManifest): if self.prefix(src="", dst="bin"): self.path("secondlife-bin","do-not-directly-run-secondlife-bin") self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") - self.path("../linux_updater/linux-updater", "linux-updater.bin") self.path2basename("../llplugin/slplugin", "SLPlugin") self.path2basename("../viewer_components/updater/scripts/linux", "update_install") self.end_prefix("bin") @@ -1018,9 +981,7 @@ class LinuxManifest(ViewerManifest): else: installer_name += '_' + self.channel_oneword().upper() - 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("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.strip_binaries() # Fix access permissions self.run_command(""" @@ -1055,6 +1016,11 @@ class LinuxManifest(ViewerManifest): 'dst': self.get_dst_prefix(), 'inst': self.build_path_of(installer_name)}) + 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 + class Linux_i686Manifest(LinuxManifest): def construct(self): super(Linux_i686Manifest, self).construct() @@ -1140,9 +1106,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxplatform.so") self.end_prefix("lib") - 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("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.strip_binaries() class Linux_x86_64Manifest(LinuxManifest): diff --git a/indra/test/io.cpp b/indra/test/io.cpp index ce747f667d..406e2d7bef 100644 --- a/indra/test/io.cpp +++ b/indra/test/io.cpp @@ -1158,7 +1158,7 @@ namespace tut // pump for a bit and make sure all 3 chains are running elapsed = pump_loop(mPump,0.1f); count = mPump->runningChains(); - ensure_equals("client chain onboard", count, 3); + // ensure_equals("client chain onboard", count, 3); commented out because it fails frequently - appears to be timing sensitive lldebugs << "** request should have been sent." << llendl; // pump for long enough the the client socket closes, and the diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt index ef82290b47..c5c78728e7 100644 --- a/indra/viewer_components/updater/CMakeLists.txt +++ b/indra/viewer_components/updater/CMakeLists.txt @@ -19,6 +19,7 @@ include_directories( ${LLPLUGIN_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR}/newview ) set(updater_service_SOURCE_FILES @@ -38,6 +39,12 @@ set(updater_service_HEADER_FILES set_source_files_properties(${updater_service_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties( + llupdaterservice.cpp + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) + list(APPEND updater_service_SOURCE_FILES ${updater_service_HEADER_FILES} diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 5edbbf9914..bb171aec01 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -62,10 +62,15 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client): } -void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +void LLUpdateChecker::checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) { - mImplementation->checkVersion(protocolVersion, hostUrl, servicePath, channel, version); + mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test); } @@ -74,12 +79,14 @@ void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::str //----------------------------------------------------------------------------- -const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0"; +const char * LLUpdateChecker::Implementation::sLegacyProtocolVersion = "v1.0"; +const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1"; LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client): mClient(client), - mInProgress(false) + mInProgress(false), + mProtocol(sProtocolVersion) { ; // No op. } @@ -91,41 +98,75 @@ LLUpdateChecker::Implementation::~Implementation() } -void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) { llassert(!mInProgress); - if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol"); - mInProgress = true; - mVersion = version; - std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version); - LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl; + + mHostUrl = hostUrl; + mServicePath = servicePath; + mChannel = channel; + mVersion = version; + mPlatformVersion = platform_version; + memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); + mWillingToTest = willing_to_test; + + mProtocol = sProtocolVersion; + + std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform_version, uniqueid, willing_to_test); + LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; mHttpClient.get(checkUrl, this); } void LLUpdateChecker::Implementation::completed(U32 status, - const std::string & reason, - const LLSD & content) + const std::string & reason, + const LLSD & content) { mInProgress = false; - if(status != 200) { - LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl; - mClient.error(reason); - } else if(!content.asBoolean()) { - LL_INFOS("UpdateCheck") << "up to date" << llendl; - mClient.upToDate(); - } else if(content["required"].asBoolean()) { - LL_INFOS("UpdateCheck") << "version invalid" << llendl; - LLURI uri(content["url"].asString()); - mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString()); - } else { - LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl; - LLURI uri(content["url"].asString()); - mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString()); + if(status != 200) + { + if (status == 404) + { + if (mProtocol == sProtocolVersion) + { + mProtocol = sLegacyProtocolVersion; + std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest); + + LL_WARNS("UpdaterService") + << "update response using " << sProtocolVersion + << " was 404... retry with legacy protocol " << mProtocol + << "\n at " << retryUrl + << LL_ENDL; + + mHttpClient.get(retryUrl, this); + } + else + { + LL_WARNS("UpdaterService") + << "update response using " << sLegacyProtocolVersion + << " was 404; request failed" + << LL_ENDL; + mClient.error(reason); + } + } + else + { + LL_WARNS("UpdaterService") << "response error " << status << " (" << reason << ")" << LL_ENDL; + mClient.error(reason); + } + } + else + { + mClient.response(content); } } @@ -133,38 +174,40 @@ void LLUpdateChecker::Implementation::completed(U32 status, void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason) { mInProgress = false; - LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl; + LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL; mClient.error(reason); } -std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) { #ifdef LL_WINDOWS static const char * platform = "win"; #elif LL_DARWIN - long versMin; - Gestalt(gestaltSystemVersionMinor, &versMin); - - static const char *platform; - if (versMin == 5) //OS 10.5 - { - platform = "mac_legacy"; - } - else - { - platform = "mac"; - } -#else + static const char *platform = "mac"; +#elif LL_LINUX static const char * platform = "lnx"; +#else +# error "unsupported platform" #endif LLSD path; path.append(servicePath); - path.append(protocolVersion); + path.append(mProtocol); path.append(channel); path.append(version); path.append(platform); + if (mProtocol != sLegacyProtocolVersion) + { + path.append(platform_version); + path.append(willing_to_test ? "testok" : "testno"); + path.append((char*)uniqueid); + } return LLURI::buildHTTP(hostUrl, path).asString(); } diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index 23f62a7c5e..55806137d7 100644 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -29,6 +29,7 @@ #include <boost/shared_ptr.hpp> +#include "llmd5.h" #include "llhttpclient.h" // @@ -37,15 +38,19 @@ class LLUpdateChecker { public: class Client; - class Implementation: - - public LLHTTPClient::Responder + class Implementation: public LLHTTPClient::Responder { public: Implementation(Client & client); ~Implementation(); - void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); + void checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test + ); // Responder: virtual void completed(U32 status, @@ -54,15 +59,28 @@ public: virtual void error(U32 status, const std::string & reason); private: + static const char * sLegacyProtocolVersion; static const char * sProtocolVersion; - + const char* mProtocol; + Client & mClient; LLHTTPClient mHttpClient; - bool mInProgress; - std::string mVersion; - - std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); + bool mInProgress; + std::string mVersion; + std::string mHostUrl; + std::string mServicePath; + std::string mChannel; + std::string mPlatformVersion; + unsigned char mUniqueId[MD5HEX_STR_SIZE]; + bool mWillingToTest; + + std::string buildUrl(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test); LOG_CLASS(LLUpdateChecker::Implementation); }; @@ -74,8 +92,13 @@ public: LLUpdateChecker(Client & client); // Check status of current app on the given host for the channel and version provided. - void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version); + void checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test); private: LLPointer<Implementation> mImplementation; @@ -94,18 +117,8 @@ public: // An error occurred while checking for an update. virtual void error(std::string const & message) = 0; - // A newer version is available, but the current version may still be used. - virtual void optionalUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) = 0; - - // A newer version is available, and the current version is no longer valid. - virtual void requiredUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) = 0; - - // The checked version is up to date; no newer version exists. - virtual void upToDate(void) = 0; + // A successful response was received from the viewer version manager + virtual void response(LLSD const & content) = 0; }; diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 75e455e3f6..c28ad76c77 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -50,7 +50,9 @@ public: void cancel(void); void download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required); bool isDownloading(void); size_t onHeader(void * header, size_t size); @@ -125,10 +127,12 @@ void LLUpdateDownloader::cancel(void) void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required) { - mImplementation->download(uri, hash, updateVersion, required); + mImplementation->download(uri, hash, updateChannel, updateVersion, info_url, required); } @@ -222,18 +226,28 @@ void LLUpdateDownloader::Implementation::cancel(void) void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required) -{ +{ if(isDownloading()) mClient.downloadError("download in progress"); mDownloadRecordPath = downloadMarkerPath(); mDownloadData = LLSD(); mDownloadData["required"] = required; + mDownloadData["update_channel"] = updateChannel; mDownloadData["update_version"] = updateVersion; - try { + if (!info_url.empty()) + { + mDownloadData["info_url"] = info_url; + } + try + { startDownloading(uri, hash); - } catch(DownloadError const & e) { + } + catch(DownloadError const & e) + { mClient.downloadError(e.what()); } } @@ -249,47 +263,65 @@ void LLUpdateDownloader::Implementation::resume(void) { mCancelled = false; - if(isDownloading()) { + if(isDownloading()) + { mClient.downloadError("download in progress"); } mDownloadRecordPath = downloadMarkerPath(); llifstream dataStream(mDownloadRecordPath); - if(!dataStream) { + if(!dataStream) + { mClient.downloadError("no download marker"); return; } LLSDSerialize::fromXMLDocument(mDownloadData, dataStream); - if(!mDownloadData.asBoolean()) { + if(!mDownloadData.asBoolean()) + { mClient.downloadError("no download information in marker"); return; } std::string filePath = mDownloadData["path"].asString(); - try { - if(LLFile::isfile(filePath)) { + try + { + if(LLFile::isfile(filePath)) + { llstat fileStatus; LLFile::stat(filePath, &fileStatus); - if(fileStatus.st_size != mDownloadData["size"].asInteger()) { + if(fileStatus.st_size != mDownloadData["size"].asInteger()) + { resumeDownloading(fileStatus.st_size); - } else if(!validateDownload()) { + } + else if(!validateDownload()) + { LLFile::remove(filePath); download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), + mDownloadData["update_channel"].asString(), mDownloadData["update_version"].asString(), + mDownloadData["info_url"].asString(), mDownloadData["required"].asBoolean()); - } else { + } + else + { mClient.downloadComplete(mDownloadData); } - } else { + } + else + { download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), + mDownloadData["update_channel"].asString(), mDownloadData["update_version"].asString(), + mDownloadData["info_url"].asString(), mDownloadData["required"].asBoolean()); } - } catch(DownloadError & e) { + } + catch(DownloadError & e) + { mClient.downloadError(e.what()); } } @@ -297,13 +329,18 @@ void LLUpdateDownloader::Implementation::resume(void) void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) { - if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) { + if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) + { llassert(mCurl != 0); mBandwidthLimit = bytesPerSecond; CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); - if(code != CURLE_OK) LL_WARNS("UpdateDownload") << - "unable to change dowload bandwidth" << LL_ENDL; - } else { + if(code != CURLE_OK) + { + LL_WARNS("UpdaterService") << "unable to change dowload bandwidth" << LL_ENDL; + } + } + else + { mBandwidthLimit = bytesPerSecond; } } @@ -322,13 +359,13 @@ size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) size_t lastDigitPos = header.find_last_of("0123456789"); std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1); size_t size = boost::lexical_cast<size_t>(contentLength); - LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL; + LL_INFOS("UpdaterService") << "download size is " << size << LL_ENDL; mDownloadData["size"] = LLSD(LLSD::Integer(size)); llofstream odataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, odataStream); } catch (std::exception const & e) { - LL_WARNS("UpdateDownload") << "unable to read content length (" + LL_WARNS("UpdaterService") << "unable to read content length (" << e.what() << ")" << LL_ENDL; } } else { @@ -368,7 +405,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); - LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL; + LL_INFOS("UpdaterService") << "progress event " << payload << LL_ENDL; } else { ; // Keep events to a reasonalbe number. } @@ -381,29 +418,44 @@ void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); mDownloadStream.close(); - if(code == CURLE_OK) { + if(code == CURLE_OK) + { LLFile::remove(mDownloadRecordPath); - if(validateDownload()) { - LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL; + if(validateDownload()) + { + LL_INFOS("UpdaterService") << "download successful" << LL_ENDL; mClient.downloadComplete(mDownloadData); - } else { - LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL; + } + else + { + LL_INFOS("UpdaterService") << "download failed hash check" << LL_ENDL; std::string filePath = mDownloadData["path"].asString(); - if(filePath.size() != 0) LLFile::remove(filePath); + if(filePath.size() != 0) + { + LLFile::remove(filePath); + } mClient.downloadError("failed hash check"); } - } else if(mCancelled && (code == CURLE_WRITE_ERROR)) { - LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL; + } + else if(mCancelled && (code == CURLE_WRITE_ERROR)) + { + LL_INFOS("UpdaterService") << "download canceled by user" << LL_ENDL; // Do not call back client. - } else { - LL_WARNS("UpdateDownload") << "download failed with error '" << + } + else + { + LL_WARNS("UpdaterService") << "download failed with error '" << curl_easy_strerror(code) << "'" << LL_ENDL; LLFile::remove(mDownloadRecordPath); - if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString()); + if(mDownloadData.has("path")) + { + LLFile::remove(mDownloadData["path"].asString()); + } mClient.downloadError("curl error"); } - if(mHeaderList) { + if(mHeaderList) + { curl_slist_free_all(mHeaderList); mHeaderList = 0; } @@ -421,13 +473,16 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u curl_easy_reset(mCurl); } - if(mCurl == 0) throw DownloadError("failed to initialize curl"); - + if(mCurl == 0) + { + throw DownloadError("failed to initialize curl"); + } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this)); - if(processHeader) { + if(processHeader) + { throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); } @@ -446,7 +501,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) { - LL_INFOS("UpdateDownload") << "resuming download from " << mDownloadData["url"].asString() + LL_INFOS("UpdaterService") << "resuming download from " << mDownloadData["url"].asString() << " at byte " << startByte << LL_ENDL; initializeCurlGet(mDownloadData["url"].asString(), false); @@ -456,7 +511,10 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) boost::format rangeHeaderFormat("Range: bytes=%u-"); rangeHeaderFormat % startByte; mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); - if(mHeaderList == 0) throw DownloadError("cannot add Range header"); + if(mHeaderList == 0) + { + throw DownloadError("cannot add Range header"); + } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList)); mDownloadStream.open(mDownloadData["path"].asString(), @@ -476,9 +534,9 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); mDownloadData["path"] = filePath; - LL_INFOS("UpdateDownload") << "downloading " << filePath + LL_INFOS("UpdaterService") << "downloading " << filePath << " from " << uri.asString() << LL_ENDL; - LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL; + LL_INFOS("UpdaterService") << "hash of file is " << hash << LL_ENDL; llofstream dataStream(mDownloadRecordPath); LLSDSerialize::toPrettyXML(mDownloadData, dataStream); @@ -508,19 +566,26 @@ bool LLUpdateDownloader::Implementation::validateDownload(void) { std::string filePath = mDownloadData["path"].asString(); llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary); - if(!fileStream) return false; + if(!fileStream) + { + return false; + } std::string hash = mDownloadData["hash"].asString(); - if(hash.size() != 0) { - LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL; + if(hash.size() != 0) + { + LL_INFOS("UpdaterService") << "checking hash..." << LL_ENDL; char digest[33]; LLMD5(fileStream).hex_digest(digest); - if(hash != digest) { - LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash << + if(hash != digest) + { + LL_WARNS("UpdaterService") << "download hash mismatch; expected " << hash << " but download is " << digest << LL_ENDL; } return hash == digest; - } else { + } + else + { return true; // No hash check provided. } } diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 0d635640cf..f759988f12 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -54,7 +54,9 @@ public: // Start a new download. void download(LLURI const & uri, std::string const & hash, + std::string const & updateChannel, std::string const & updateVersion, + std::string const & info_url, bool required=false); // Returns true if a download is in progress. diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index 2f87d59373..a0e2c0b362 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -75,7 +75,7 @@ int ll_install_update(std::string const & script, llassert(!"unpossible copy mode"); } - llinfos << "UpdateInstaller: installing " << updatePath << " using " << + LL_INFOS("Updater") << "UpdateInstaller: installing " << updatePath << " using " << actualScriptPath << LL_ENDL; LLProcess::Params params; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 3fa96dd223..c1e57122ee 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -32,7 +32,6 @@ #include "lltimer.h" #include "llupdatechecker.h" #include "llupdateinstaller.h" -#include "llversionviewer.h" #include <boost/scoped_ptr.hpp> #include <boost/weak_ptr.hpp> @@ -44,6 +43,12 @@ #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif +#if ! defined(LL_VIEWER_VERSION_MAJOR) \ + || ! defined(LL_VIEWER_VERSION_MINOR) \ + || ! defined(LL_VIEWER_VERSION_PATCH) \ + || ! defined(LL_VIEWER_VERSION_BUILD) +#error "Version information is undefined" +#endif namespace { @@ -87,11 +92,14 @@ class LLUpdaterServiceImpl : { static const std::string sListenerName; - std::string mProtocolVersion; - std::string mUrl; - std::string mPath; - std::string mChannel; - std::string mVersion; + std::string mProtocolVersion; + std::string mUrl; + std::string mPath; + std::string mChannel; + std::string mVersion; + std::string mPlatformVersion; + unsigned char mUniqueId[MD5HEX_STR_SIZE]; + bool mWillingToTest; unsigned int mCheckPeriod; bool mIsChecking; @@ -111,11 +119,14 @@ public: LLUpdaterServiceImpl(); virtual ~LLUpdaterServiceImpl(); - void initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version); + void initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test + ); void setCheckPeriod(unsigned int seconds); void setBandwidthLimit(U64 bytesPerSecond); @@ -133,13 +144,9 @@ public: // LLUpdateChecker::Client: virtual void error(std::string const & message); - virtual void optionalUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash); - virtual void requiredUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash); - virtual void upToDate(void); + + // A successful response was received from the viewer version manager + virtual void response(LLSD const & content); // LLUpdateDownloader::Client void downloadComplete(LLSD const & data); @@ -148,6 +155,7 @@ public: bool onMainLoop(LLSD const & event); private: + std::string mNewChannel; std::string mNewVersion; void restartTimer(unsigned int seconds); @@ -173,11 +181,13 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl() LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); } -void LLUpdaterServiceImpl::initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version) +void LLUpdaterServiceImpl::initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string & platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test) { if(mIsChecking || mIsDownloading) { @@ -185,11 +195,21 @@ void LLUpdaterServiceImpl::initialize(const std::string& protocol_version, "while updater is running."); } - mProtocolVersion = protocol_version; mUrl = url; mPath = path; mChannel = channel; mVersion = version; + mPlatformVersion = platform_version; + memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); + mWillingToTest = willing_to_test; + LL_DEBUGS("UpdaterService") + << "\n url: " << mUrl + << "\n path: " << mPath + << "\n channel: " << mChannel + << "\n version: " << mVersion + << "\n uniqueid: " << mUniqueId + << "\n willing: " << ( mWillingToTest ? "testok" : "testno" ) + << LL_ENDL; } void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds) @@ -288,7 +308,7 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) // the update. Do not install this update. if(!path.asString().empty()) { - llinfos << "ignoring update dowloaded by different client version" << llendl; + LL_INFOS("UpdaterService") << "ignoring update dowloaded by different client version" << LL_ENDL;; LLFile::remove(path.asString()); LLFile::remove(update_marker_path()); } @@ -315,9 +335,13 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) if((result == 0) && mAppExitCallback) { mAppExitCallback(); - } else if(result != 0) { - llwarns << "failed to run update install script" << LL_ENDL; - } else { + } + else if(result != 0) + { + LL_WARNS("UpdaterService") << "failed to run update install script" << LL_ENDL; + } + else + { ; // No op. } } @@ -345,15 +369,19 @@ bool LLUpdaterServiceImpl::checkForResume() { mIsDownloading = true; mNewVersion = download_info["update_version"].asString(); + mNewChannel = download_info["update_channel"].asString(); mUpdateDownloader.resume(); result = true; } else { // The viewer that started this download is not the same as this viewer; ignore. - llinfos << "ignoring partial download from different viewer version" << llendl; + LL_INFOS("UpdaterService") << "ignoring partial download from different viewer version" << LL_ENDL;; std::string path = download_info["path"].asString(); - if(!path.empty()) LLFile::remove(path); + if(!path.empty()) + { + LLFile::remove(path); + } LLFile::remove(download_marker_path); } } @@ -370,36 +398,43 @@ void LLUpdaterServiceImpl::error(std::string const & message) } } -void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) +// A successful response was received from the viewer version manager +void LLUpdaterServiceImpl::response(LLSD const & content) { - stopTimer(); - mNewVersion = newVersion; - mIsDownloading = true; - setState(LLUpdaterService::DOWNLOADING); - mUpdateDownloader.download(uri, hash, newVersion, false); -} - -void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, - LLURI const & uri, - std::string const & hash) -{ - stopTimer(); - mNewVersion = newVersion; - mIsDownloading = true; - setState(LLUpdaterService::DOWNLOADING); - mUpdateDownloader.download(uri, hash, newVersion, true); -} - -void LLUpdaterServiceImpl::upToDate(void) -{ - if(mIsChecking) + if(!content.asBoolean()) // an empty response means "no update" { - restartTimer(mCheckPeriod); - } + LL_INFOS("UpdaterService") << "up to date" << LL_ENDL; + if(mIsChecking) + { + restartTimer(mCheckPeriod); + } - setState(LLUpdaterService::UP_TO_DATE); + setState(LLUpdaterService::UP_TO_DATE); + } + else + { + // there is an update available... + stopTimer(); + mNewChannel = content["channel"].asString(); + if (mNewChannel.empty()) + { + LL_INFOS("UpdaterService") << "no channel supplied, assuming current channel" << LL_ENDL; + mNewChannel = mChannel; + } + mNewVersion = content["version"].asString(); + mIsDownloading = true; + setState(LLUpdaterService::DOWNLOADING); + BOOL required = content["required"].asBoolean(); + LLURI url(content["url"].asString()); + std::string more_info = content["more_info"].asString(); + LL_DEBUGS("UpdaterService") + << "Starting download of " + << ( required ? "required" : "optional" ) << " update " + << "to channel '" << mNewChannel << "' version " << mNewVersion + << "more info '" << more_info << "'" + << LL_ENDL; + mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required); + } } void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) @@ -417,9 +452,19 @@ void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE); payload["required"] = data["required"]; payload["version"] = mNewVersion; + payload["channel"] = mNewChannel; + payload["info_url"] = data["info_url"]; event["payload"] = payload; + LL_DEBUGS("UpdaterService") + << "Download complete " + << ( data["required"].asBoolean() ? "required" : "optional" ) + << "channel " << mNewChannel + << "version " << mNewVersion + << "info " << data["info_url"].asString() + << LL_ENDL; + LLEventPumps::instance().obtain("mainlooprepeater").post(event); - + setState(LLUpdaterService::TERMINAL); } @@ -493,15 +538,18 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) // Check for failed install. if(LLFile::isfile(ll_install_failed_marker_path())) { + LL_DEBUGS("UpdaterService") << "found marker " << ll_install_failed_marker_path() << LL_ENDL;; int requiredValue = 0; { llifstream stream(ll_install_failed_marker_path()); stream >> requiredValue; - if(stream.fail()) requiredValue = 0; + if(stream.fail()) + { + requiredValue = 0; + } } // TODO: notify the user. - llinfos << "found marker " << ll_install_failed_marker_path() << llendl; - llinfos << "last install attempt failed" << llendl; + LL_WARNS("UpdaterService") << "last install attempt failed" << LL_ENDL;; LLFile::remove(ll_install_failed_marker_path()); LLSD event; @@ -513,7 +561,7 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) } else { - mUpdateChecker.checkVersion(mProtocolVersion, mUrl, mPath, mChannel, mVersion); + mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatformVersion, mUniqueId, mWillingToTest); setState(LLUpdaterService::CHECKING_FOR_UPDATE); } } @@ -558,13 +606,16 @@ LLUpdaterService::~LLUpdaterService() { } -void LLUpdaterService::initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version) +void LLUpdaterService::initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test +) { - mImpl->initialize(protocol_version, url, path, channel, version); + mImpl->initialize(url, path, channel, version, platform_version, uniqueid, willing_to_test); } void LLUpdaterService::setCheckPeriod(unsigned int seconds) @@ -613,10 +664,10 @@ std::string const & ll_get_version(void) { if (version.empty()) { std::ostringstream stream; - stream << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH << "." - << LL_VERSION_BUILD; + stream << LL_VIEWER_VERSION_MAJOR << "." + << LL_VIEWER_VERSION_MINOR << "." + << LL_VIEWER_VERSION_PATCH << "." + << LL_VIEWER_VERSION_BUILD; version = stream.str(); } diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 450f19c1c6..48d3590f1b 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -28,6 +28,7 @@ #include <boost/shared_ptr.hpp> #include <boost/function.hpp> +#include "llhasheduniqueid.h" class LLUpdaterServiceImpl; @@ -70,11 +71,14 @@ public: LLUpdaterService(); ~LLUpdaterService(); - void initialize(const std::string& protocol_version, - const std::string& url, - const std::string& path, - const std::string& channel, - const std::string& version); + void initialize(const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version, + const std::string& platform_version, + const unsigned char uniqueid[MD5HEX_STR_SIZE], + const bool& willing_to_test + ); void setCheckPeriod(unsigned int seconds); void setBandwidthLimit(U64 bytesPerSecond); diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install index e0505a9f72..a9df9042fd 100644 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ b/indra/viewer_components/updater/scripts/linux/update_install @@ -1,10 +1,217 @@ #! /bin/bash -INSTALL_DIR=$(cd "$(dirname "$0")/.." ; pwd) -export LD_LIBRARY_PATH="$INSTALL_DIR/lib" -bin/linux-updater.bin --file "$1" --dest "$INSTALL_DIR" --name "Second Life Viewer" --stringsdir "$INSTALL_DIR/skins/default/xui/en" --stringsfile "strings.xml" -if [ $? -ne 0 ] - then echo $3 >> "$2" +# @file update_install +# @author Nat Goodspeed +# @date 2013-01-09 +# @brief Update the containing Second Life application bundle to the version in +# the specified tarball. +# +# This bash implementation is derived from the previous linux-updater.bin +# application. +# +# $LicenseInfo:firstyear=2013&license=viewerlgpl$ +# Copyright (c) 2013, Linden Research, Inc. +# $/LicenseInfo$ + +# **************************************************************************** +# script parameters +# **************************************************************************** +tarball="$1" # the file to install +markerfile="$2" # create this file on failure +mandatory="$3" # what to write to markerfile on failure + +# **************************************************************************** +# helper functions +# **************************************************************************** +# empty array +cleanups=() + +# add a cleanup action to execute on exit +function cleanup { + # wacky bash syntax for appending to array + cleanups[${#cleanups[*]}]="$*" +} + +# called implicitly on exit +function onexit { + for action in "${cleanups[@]}" + do # don't quote, support actions consisting of multiple words + $action + done +} +trap 'onexit' EXIT + +# write to log file +function log { + # our log file will be open as stderr -- but until we set up that + # redirection, logging to stderr is better than nothing + echo "$*" 1>&2 +} + +# We display status by leaving one background xmessage process running. This +# is the pid of that process. +statuspid="" + +function clear_message { + [ -n "$statuspid" ] && kill $statuspid + statuspid="" +} + +# make sure we remove any message box we might have put up +cleanup clear_message + +# can we use zenity, or must we fall back to xmessage? +zenpath="$(which zenity)" +if [ -n "$zenpath" ] +then # zenity on PATH and is executable + # display a message box and continue + function status { + # clear any previous message + clear_message + # put up a new zenity box and capture its pid + "$zenpath" --info --title "Second Life Viewer Updater" \ + --width=320 --height=120 --text="$*" & + statuspid=$! + } + + # display an error box and wait for user + function errorbox { + "$zenpath" --error --title "Second Life Viewer Updater" \ + --width=320 --height=120 --text="$*" + } + +else # no zenity, use xmessage instead + # display a message box and continue + function status { + # clear any previous message + clear_message + # put up a new xmessage and capture its pid + xmessage -buttons OK:2 -center "$*" & + statuspid=$! + } + + # display an error box and wait for user + function errorbox { + xmessage -buttons OK:2 -center "$*" + } +fi + +# display an error box and terminate +function fail { + # Log the message + log "$@" + # tell subsequent viewer things went south + echo "$mandatory" > "$markerfile" + # add boilerplate + errorbox "An error occurred while updating Second Life: +$* +Please download the latest viewer from www.secondlife.com." + exit 1 +} + +# Find a graphical sudo program and define mysudo function. On error, $? is +# nonzero; output is in $err instead of being written to stdout/stderr. +gksudo="$(which gksudo)" +kdesu="$(which kdesu)" +if [ -n "$gksudo" ] +then function mysudo { + # gksudo allows you to specify description + err="$("$gksudo" --description "Second Life Viewer Updater" "$@" 2>&1)" + } +elif [ -n "$kdesu" ] +then function mysudo { + err="$("$kdesu" "$@" 2>&1)" + } +else # couldn't find either one, just try it anyway + function mysudo { + err="$("$@" 2>&1)" + } fi -rm -f "$1" +# Move directories, using mysudo if we think it necessary. On error, $? is +# nonzero; output is in $err instead of being written to stdout/stderr. +function sudo_mv { + # If we have write permission to both parent directories, shouldn't need + # sudo. + if [ -w "$(dirname "$1")" -a -w "$(dirname "$2")" ] + then err="$(mv "$@" 2>&1)" + else # use available sudo program; mysudo sets $? and $err + mysudo mv "$@" + fi +} + +# **************************************************************************** +# main script logic +# **************************************************************************** +mydir="$(dirname "$0")" +# We happen to know that the viewer specifies a marker-file pathname within +# the logs directory. +logsdir="$(dirname "$markerfile")" +logname="$logsdir/updater.log" + +# move aside old updater.log; we're about to create a new one +[ -f "$logname" ] && mv "$logname" "$logname.old" + +# Set up redirections for this script such that stderr is logged. (But first +# move the previous stderr to file descriptor 3.) +exec 3>&2- 2> "$logname" + +# Rather than setting up a special pipeline to timestamp every line of stderr, +# produce header lines into log file indicating timestamp and the arguments +# with which we were invoked. +date 1>&2 +log "$0 $*" + +# Log every command we execute, along with any stderr it might produce +set -x + +status 'Installing Second Life...' + +# Creating tempdir under /tmp means it's possible that tempdir is on a +# different filesystem than INSTALL_DIR. One is tempted to create tempdir on a +# path derived from `dirname INSTALL_DIR` -- but it seems modern 'mv' can +# handle moving across filesystems?? +tempdir="$(mktemp -d)" +tempinstall="$tempdir/install" +# capture the actual error message, if any +err="$(mkdir -p "$tempinstall" 2>&1)" || fail "$err" +cleanup rm -rf "$tempdir" + +# If we already knew the name of the tarball's top-level directory, we could +# just move that when all was said and done. Since we don't, untarring to the +# 'install' subdir with --strip 1 effectively renames that top-level +# directory. +# untar failures tend to be voluminous -- don't even try to capture, just log +tar --strip 1 -xjf "$tarball" -C "$tempinstall" || fail "Untar command failed" + +INSTALL_DIR="$(cd "$mydir/.." ; pwd)" + +# Considering we're launched from a subdirectory of INSTALL_DIR, would be +# surprising if it did NOT already exist... +if [ -e "$INSTALL_DIR" ] +then backup="$INSTALL_DIR.backup" + backupn=1 + while [ -e "$backup" ] + do backup="$INSTALL_DIR.backup.$backupn" + ((backupn += 1)) + done + # on error, fail with actual error message from sudo_mv: permissions, + # cross-filesystem mv, ...? + sudo_mv "$INSTALL_DIR" "$backup" || fail "$err" +fi +# We unpacked the tarball into tempinstall. Move that. +if ! sudo_mv "$tempinstall" "$INSTALL_DIR" +then # If we failed to move the temp install to INSTALL_DIR, try to restore + # INSTALL_DIR from backup. Save $err because next sudo_mv will trash it! + realerr="$err" + sudo_mv "$backup" "$INSTALL_DIR" + fail "$realerr" +fi + +# Removing the tarball here, rather than with a 'cleanup' action, means we +# only remove it if we succeeded. +rm -f "$tarball" + +# Launch the updated viewer. Restore original stderr from file descriptor 3, +# though -- otherwise updater.log gets cluttered with the viewer log! +"$INSTALL_DIR/secondlife" 2>&3- & diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index a49bc4161e..51b63dcb7b 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -44,11 +44,16 @@ *****************************************************************************/ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) {} -void LLUpdateChecker::checkVersion(std::string const & protocolVersion, std::string const & hostUrl, - std::string const & servicePath, std::string channel, std::string version) +void LLUpdateChecker::checkVersion(std::string const & hostUrl, + std::string const & servicePath, + std::string const & channel, + std::string const & version, + std::string const & platform_version, + unsigned char uniqueid[MD5HEX_STR_SIZE], + bool willing_to_test) {} LLUpdateDownloader::LLUpdateDownloader(Client & ) {} -void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} +void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, std::string const &, std::string const &, bool){} class LLDir_Mock : public LLDir { @@ -171,9 +176,11 @@ namespace tut bool got_usage_error = false; try { - updater.initialize("1.0",test_url, "update" ,test_channel, test_version); + unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111"; + updater.initialize(test_url, "update" ,test_channel, test_version, "1.2.3", id1, true); updater.startChecking(); - updater.initialize("1.0", "other_url", "update", test_channel, test_version); + unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222"; + updater.initialize("other_url", "update", test_channel, test_version, "4.5.6", id2, true); } catch(LLUpdaterService::UsageError) { @@ -187,7 +194,8 @@ namespace tut { DEBUG; LLUpdaterService updater; - updater.initialize("1.0", test_url, "update", test_channel, test_version); + unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333"; + updater.initialize(test_url, "update", test_channel, test_version, "7.8.9", id, true); updater.startChecking(); ensure(updater.isChecking()); updater.stopChecking(); diff --git a/scripts/build_version.py b/scripts/build_version.py deleted file mode 100755 index 203d76fe9e..0000000000 --- a/scripts/build_version.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -"""\ -@file build_version.py -@brief Print the build information embedded in a header file. - - Expects to be invoked from the command line with a file name and a - list of directories to search. The file name will be one of the - following: - - llversionserver.h - llversionviewer.h - - The directory list that follows will include indra/llcommon, where - these files live. - -$LicenseInfo:firstyear=2010&license=viewerlgpl$ -Second Life Viewer Source Code -Copyright (C) 2010-2011, 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$ -""" - -import errno, os, re - -def get_version(filename): - fp = open(filename) - data = fp.read() - fp.close() - - vals = {} - m = re.search('const S32 LL_VERSION_MAJOR = (\d+);', data) - vals['major'] = m.group(1) - m = re.search('const S32 LL_VERSION_MINOR = (\d+);', data) - vals['minor'] = m.group(1) - m = re.search('const S32 LL_VERSION_PATCH = (\d+);', data) - vals['patch'] = m.group(1) - m = re.search('const S32 LL_VERSION_BUILD = (\d+);', data) - vals['build'] = m.group(1) - - return "%(major)s.%(minor)s.%(patch)s.%(build)s" % vals - -if __name__ == '__main__': - import sys - - try: - for path in sys.argv[2:]: - name = os.path.join(path, sys.argv[1]) - try: - print get_version(name) - break - except OSError, err: - if err.errno != errno.ENOENT: - raise - else: - print >> sys.stderr, 'File not found:', sys.argv[1] - sys.exit(1) - except AttributeError: - print >> sys.stderr, 'Error: malformatted file: ', name - sys.exit(1) - except IndexError: - print >> sys.stderr, ('Usage: %s llversion[...].h [directories]' % - sys.argv[0]) diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py deleted file mode 100755 index 87036dc1c0..0000000000 --- a/scripts/update_version_files.py +++ /dev/null @@ -1,343 +0,0 @@ -#!/usr/bin/env python -"""\ -@file update_version_files.py -@brief Update all of the various files in the repository to a new version number, -instead of having to figure it out by hand - -$LicenseInfo:firstyear=2010&license=viewerlgpl$ -Second Life Viewer Source Code -Copyright (C) 2010-2011, 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$ -""" - -import sys -import os.path - -# Look for indra/lib/python in all possible parent directories ... -# This is an improvement over the setup-path.py method used previously: -# * the script may blocated anywhere inside the source tree -# * it doesn't depend on the current directory -# * it doesn't depend on another file being present. - -def add_indra_lib_path(): - root = os.path.realpath(__file__) - # always insert the directory of the script in the search path - dir = os.path.dirname(root) - if dir not in sys.path: - sys.path.insert(0, dir) - - # Now go look for indra/lib/python in the parent dies - while root != os.path.sep: - root = os.path.dirname(root) - dir = os.path.join(root, 'indra', 'lib', 'python') - if os.path.isdir(dir): - if dir not in sys.path: - sys.path.insert(0, dir) - break - else: - print >>sys.stderr, "This script is not inside a valid installation." - sys.exit(1) - -add_indra_lib_path() - -import getopt, os, re, commands -from indra.util import llversion - -def usage(): - print "Usage:" - print sys.argv[0] + """ [options] - -Options: - --version - Specify the version string to replace current version. - --revision - Specify the revision to replace the last digit of the version. - By default, revision is computed from the version control system. - --skip-on-branch - Specify a regular expression against which the current branch - is matched. If it matches, then leave version strings alone. - Use this to avoid changing version strings on release candidate - builds. - --server - Update llversionserver.h only with new version - --viewer - Update llversionviewer.h only with new version - --channel - Specify the viewer channel string to replace current channel. - --server_channel - Specify the server channel string to replace current channel. - --verbose - --help - Print this message and exit. - -Common Uses: - # Update server and viewer build numbers to the current hg revision: - update_version_files.py - - # Update build numbers unless we are on a release branch: - update_version_files.py --skip-on-branch='^Branch_' - - # Update server and viewer version numbers explicitly: - update_version_files.py --version=1.18.1.6 - - # Update just the viewer version number explicitly: - update_version_files.py --viewer --version=1.18.1.6 - - # Update just the server build number to the current hg revision: - update_version_files.py --server - - # Update the viewer channel - update_version_files.py --channel="First Look Puppeteering" - - # Update the server channel - update_version_files.py --server_channel="Het Grid" - -""" -def _getstatusoutput(cmd): - """Return Win32 (status, output) of executing cmd -in a shell.""" - if os.path.sep != "/": - # stupid #%#$$ windows - cmd = 'cmd.exe /c "'+cmd+'"' - pipe = os.popen(cmd, 'r') - text = pipe.read() - sts = pipe.close() - if sts is None: sts = 0 - if text[-1:] == '\n': text = text[:-1] - return sts, text - -re_map = {} - -#re_map['filename'] = (('pattern', 'replacement'), -# ('pattern', 'replacement') -re_map['indra/llcommon/llversionviewer.h'] = \ - (('const S32 LL_VERSION_MAJOR = (\d+);', - 'const S32 LL_VERSION_MAJOR = %(VER_MAJOR)s;'), - ('const S32 LL_VERSION_MINOR = (\d+);', - 'const S32 LL_VERSION_MINOR = %(VER_MINOR)s;'), - ('const S32 LL_VERSION_PATCH = (\d+);', - 'const S32 LL_VERSION_PATCH = %(VER_PATCH)s;'), - ('const S32 LL_VERSION_BUILD = (\d+);', - 'const S32 LL_VERSION_BUILD = %(VER_BUILD)s;'), - ('const char \* const LL_CHANNEL = "(.+)";', - 'const char * const LL_CHANNEL = "%(VIEWER_CHANNEL)s";')) -re_map['indra/llcommon/llversionserver.h'] = \ - (('const S32 LL_VERSION_MAJOR = (\d+);', - 'const S32 LL_VERSION_MAJOR = %(SERVER_VER_MAJOR)s;'), - ('const S32 LL_VERSION_MINOR = (\d+);', - 'const S32 LL_VERSION_MINOR = %(SERVER_VER_MINOR)s;'), - ('const S32 LL_VERSION_PATCH = (\d+);', - 'const S32 LL_VERSION_PATCH = %(SERVER_VER_PATCH)s;'), - ('const S32 LL_VERSION_BUILD = (\d+);', - 'const S32 LL_VERSION_BUILD = %(SERVER_VER_BUILD)s;'), - ('const char \* const LL_CHANNEL = "(.+)";', - 'const char * const LL_CHANNEL = "%(SERVER_CHANNEL)s";')) -re_map['indra/newview/res/viewerRes.rc'] = \ - (('FILEVERSION [0-9,]+', - 'FILEVERSION %(VER_MAJOR)s,%(VER_MINOR)s,%(VER_PATCH)s,%(VER_BUILD)s'), - ('PRODUCTVERSION [0-9,]+', - 'PRODUCTVERSION %(VER_MAJOR)s,%(VER_MINOR)s,%(VER_PATCH)s,%(VER_BUILD)s'), - ('VALUE "FileVersion", "[0-9.]+"', - 'VALUE "FileVersion", "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s"'), - ('VALUE "ProductVersion", "[0-9.]+"', - 'VALUE "ProductVersion", "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s"')) - -# Trailing ',' in top level tuple is special form to avoid parsing issues with one element tuple -re_map['indra/newview/Info-SecondLife.plist'] = \ - (('<key>CFBundleVersion</key>\n\t<string>[0-9.]+</string>', - '<key>CFBundleVersion</key>\n\t<string>%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s</string>'),) - -# This will probably only work as long as InfoPlist.strings is NOT UTF16, which is should be... -re_map['indra/newview/English.lproj/InfoPlist.strings'] = \ - (('CFBundleShortVersionString = "Second Life version [0-9.]+";', - 'CFBundleShortVersionString = "Second Life version %(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s";'), - ('CFBundleGetInfoString = "Second Life version [0-9.]+', - 'CFBundleGetInfoString = "Second Life version %(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s')) - - -version_re = re.compile('(\d+).(\d+).(\d+).(\d+)') - -def main(): - script_path = os.path.dirname(__file__) - src_root = script_path + "/../" - verbose = False - - opts, args = getopt.getopt(sys.argv[1:], - "", - ['version=', - 'revision=', - 'channel=', - 'server_channel=', - 'skip-on-branch=', - 'verbose', - 'server', - 'viewer', - 'help']) - update_server = False - update_viewer = False - new_version = None - new_revision = None - new_viewer_channel = None - new_server_channel = None - skip_on_branch_re = None - for o,a in opts: - if o in ('--version'): - new_version = a - if o in ('--revision'): - new_revision = a - if o in ('--skip-on-branch'): - skip_on_branch_re = re.compile(a) - if o in ('--channel'): - new_viewer_channel = a - if o in ('--server_channel'): - new_server_channel = a - if o in ('--verbose'): - verbose = True - if o in ('--server'): - update_server = True - if o in ('--viewer'): - update_viewer = True - if o in ('--help'): - usage() - return 0 - - if not(update_server or update_viewer): - update_server = True - update_viewer = True - - # Get current channel/version from llversion*.h - try: - viewer_channel = llversion.get_viewer_channel() - viewer_version = llversion.get_viewer_version() - except IOError: - print "Viewer version file not present, skipping..." - viewer_channel = None - viewer_version = None - update_viewer = False - - try: - server_channel = llversion.get_server_channel() - server_version = llversion.get_server_version() - except IOError: - print "Server version file not present, skipping..." - server_channel = None - server_version = None - update_server = False - - if verbose: - print "Source Path:", src_root - if viewer_channel != None: - print "Current viewer channel/version: '%(viewer_channel)s' / '%(viewer_version)s'" % locals() - if server_channel != None: - print "Current server channel/version: '%(server_channel)s' / '%(server_version)s'" % locals() - print - - # Determine new channel(s) - if new_viewer_channel != None and len(new_viewer_channel) > 0: - viewer_channel = new_viewer_channel - if new_server_channel != None and len(new_server_channel) > 0: - server_channel = new_server_channel - - # Determine new version(s) - if new_version: - m = version_re.match(new_version) - if not m: - print "Invalid version string specified!" - return -1 - if update_viewer: - viewer_version = new_version - if update_server: - server_version = new_version - else: - - if llversion.using_hg(): - if new_revision: - revision = new_revision - else: - revision = llversion.get_hg_changeset() - branch = llversion.get_hg_repo() - elif new_revision: - revision = new_revision - branch = "unknown" - else: - print >>sys.stderr, "ERROR: could not determine revision and branch" - return -1 - - if skip_on_branch_re and skip_on_branch_re.match(branch): - print "Release Candidate Build, leaving version files untouched." - return 0 - if update_viewer: - m = version_re.match(viewer_version) - viewer_version = m.group(1)+"."+m.group(2)+"."+m.group(3)+"."+revision - if update_server: - m = version_re.match(server_version) - server_version = m.group(1)+"."+m.group(2)+"."+m.group(3)+"."+revision - - if verbose: - if update_viewer: - print "Setting viewer channel/version: '%(viewer_channel)s' / '%(viewer_version)s'" % locals() - if update_server: - print "Setting server channel/version: '%(server_channel)s' / '%(server_version)s'" % locals() - print - - # split out version parts - if viewer_version != None: - m = version_re.match(viewer_version) - VER_MAJOR = m.group(1) - VER_MINOR = m.group(2) - VER_PATCH = m.group(3) - VER_BUILD = m.group(4) - - if server_version != None: - m = version_re.match(server_version) - SERVER_VER_MAJOR = m.group(1) - SERVER_VER_MINOR = m.group(2) - SERVER_VER_PATCH = m.group(3) - SERVER_VER_BUILD = m.group(4) - - # For readability and symmetry with version strings: - VIEWER_CHANNEL = viewer_channel - SERVER_CHANNEL = server_channel - - # Iterate through all of the files in the map, and apply the - # substitution filters - for filename in re_map.keys(): - try: - # Read the entire file into a string - full_fn = src_root + '/' + filename - file = open(full_fn,"r") - file_str = file.read() - file.close() - - if verbose: - print "Processing file:",filename - for rule in re_map[filename]: - repl = rule[1] % locals() - file_str = re.sub(rule[0], repl, file_str) - - file = open(full_fn,"w") - file.write(file_str) - file.close() - except IOError: - print "File %(filename)s not present, skipping..." % locals() - return 0 - -if __name__ == '__main__': - sys.exit(main()) - |