diff options
author | Steve Bennetts <steve@lindenlab.com> | 2009-10-26 09:59:39 -0700 |
---|---|---|
committer | Steve Bennetts <steve@lindenlab.com> | 2009-10-26 09:59:39 -0700 |
commit | d6e8f32b8073d85db59f2a45a10d622b71c859ae (patch) | |
tree | 953c5efd60338604c229824467270cd8d5a458ce /indra/newview | |
parent | add9298c1e4d74bdb5503722a6c795ea6f30fa11 (diff) | |
parent | 53c972a521cbb92c6c9390c41b250a41dc22cd5a (diff) |
merge
Diffstat (limited to 'indra/newview')
209 files changed, 7643 insertions, 3451 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 26170d1713..dd3937a6ef 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -36,10 +36,8 @@ include(UI) include(UnixInstall) include(LLKDU) include(ViewerMiscLibs) - -if (WINDOWS) - include(CopyWinLibs) -endif (WINDOWS) +include(LLLogin) +include(CMakeCopyIfDifferent) include_directories( ${DBUSGLIB_INCLUDE_DIRS} @@ -61,12 +59,14 @@ include_directories( ${LLXUIXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile + ${LLLOGIN_INCLUDE_DIRS} ) set(viewer_SOURCE_FILES llaccordionctrltab.cpp llaccordionctrl.cpp llagent.cpp + llagentlistener.cpp llagentaccess.cpp llagentdata.cpp llagentlanguage.cpp @@ -77,6 +77,7 @@ set(viewer_SOURCE_FILES llanimstatelabels.cpp llappearancemgr.cpp llappviewer.cpp + llappviewerlistener.cpp llassetuploadresponders.cpp llassetuploadqueue.cpp llaudiosourcevo.cpp @@ -262,6 +263,7 @@ set(viewer_SOURCE_FILES llurllineeditorctrl.cpp lllogchat.cpp llloginhandler.cpp + lllogininstance.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp @@ -333,6 +335,7 @@ set(viewer_SOURCE_FILES llpanelpicks.cpp llpanelplace.cpp llpanelplaceinfo.cpp + llpanelshower.cpp llpanelplaces.cpp llpanelplacestab.cpp llpanelprofile.cpp @@ -370,7 +373,6 @@ set(viewer_SOURCE_FILES llspatialpartition.cpp llsplitbutton.cpp llsprite.cpp - llsrv.cpp llstartup.cpp llstatusbar.cpp llstylemap.cpp @@ -417,19 +419,20 @@ set(viewer_SOURCE_FILES lltracker.cpp lltransientdockablefloater.cpp lltransientfloatermgr.cpp + lluilistener.cpp lluploaddialog.cpp llurl.cpp llurldispatcher.cpp llurlhistory.cpp llurlsimstring.cpp llurlwhitelist.cpp - lluserauth.cpp llvectorperfoptions.cpp llviewchildren.cpp llviewerassetstorage.cpp llvieweraudio.cpp llviewercamera.cpp llviewercontrol.cpp + llviewercontrollistener.cpp llviewerdisplay.cpp llviewerfloaterreg.cpp llviewergenericmessage.cpp @@ -471,6 +474,7 @@ set(viewer_SOURCE_FILES llviewerthrottle.cpp llviewervisualparam.cpp llviewerwindow.cpp + llviewerwindowlistener.cpp llvlcomposition.cpp llvlmanager.cpp llvoavatar.cpp @@ -508,6 +512,7 @@ set(viewer_SOURCE_FILES llworld.cpp llworldmap.cpp llworldmapview.cpp + llxmlrpclistener.cpp llxmlrpctransaction.cpp noise.cpp pipeline.cpp @@ -536,6 +541,7 @@ set(viewer_HEADER_FILES llaccordionctrltab.h llaccordionctrl.h llagent.h + llagentlistener.h llagentaccess.h llagentdata.h llagentlanguage.h @@ -546,6 +552,7 @@ set(viewer_HEADER_FILES llanimstatelabels.h llappearance.h llappviewer.h + llappviewerlistener.h llassetuploadresponders.h llassetuploadqueue.h llaudiosourcevo.h @@ -734,6 +741,7 @@ set(viewer_HEADER_FILES llurllineeditorctrl.h lllogchat.h llloginhandler.h + lllogininstance.h llmanip.h llmaniprotate.h llmanipscale.h @@ -801,6 +809,7 @@ set(viewer_HEADER_FILES llpanelpicks.h llpanelplace.h llpanelplaceinfo.h + llpanelshower.h llpanelplaces.h llpanelplacestab.h llpanelprofile.h @@ -840,7 +849,6 @@ set(viewer_HEADER_FILES llspatialpartition.h llsplitbutton.h llsprite.h - llsrv.h llstartup.h llstatusbar.h llstylemap.h @@ -889,13 +897,13 @@ set(viewer_HEADER_FILES lltransientdockablefloater.h lltransientfloatermgr.h lluiconstants.h + lluilistener.h lluploaddialog.h llurl.h llurldispatcher.h llurlhistory.h llurlsimstring.h llurlwhitelist.h - lluserauth.h llvectorperfoptions.h llviewchildren.h llviewerassetstorage.h @@ -903,6 +911,7 @@ set(viewer_HEADER_FILES llviewerbuild.h llviewercamera.h llviewercontrol.h + llviewercontrollistener.h llviewerdisplay.h llviewerfloaterreg.h llviewergenericmessage.h @@ -941,6 +950,7 @@ set(viewer_HEADER_FILES llviewerthrottle.h llviewervisualparam.h llviewerwindow.h + llviewerwindowlistener.h llvlcomposition.h llvlmanager.h llvoavatar.h @@ -981,6 +991,7 @@ set(viewer_HEADER_FILES llworld.h llworldmap.h llworldmapview.h + llxmlrpclistener.h llxmlrpctransaction.h macmain.h noise.h @@ -1137,7 +1148,6 @@ if (WINDOWS) comdlg32 ${DINPUT_LIBRARY} ${DXGUID_LIBRARY} - fmodvc kernel32 odbc32 odbccp32 @@ -1181,6 +1191,15 @@ file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml) list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST}) +file(GLOB SILVER_XUI_FILE_GLOB_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/*.xml) +list(APPEND viewer_XUI_FILES ${SILVER_XUI_FILE_GLOB_LIST}) + +# Cannot append empty lists in CMake, wait until we have files here. +#file(GLOB SILVER_WIDGET_FILE_GLOB_LIST +# ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/widgets/*.xml) +#list(APPEND viewer_XUI_FILES ${SILVER_WIDGET_FILE_GLOB_LIST}) + list(SORT viewer_XUI_FILES) source_group("XUI Files" FILES ${viewer_XUI_FILES}) @@ -1255,23 +1274,23 @@ endif (OPENAL) if (FMOD) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") - if (NOT WINDOWS) + if (DARWIN) set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) - set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY}) - if (DARWIN) - list(APPEND fmodwrapper_needed_LIBRARIES ${CARBON_LIBRARY}) - set_target_properties( - fmodwrapper - PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Resources" - LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" - ) - endif (DARWIN) + set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) + set_target_properties( + fmodwrapper + PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Resources" + LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" + ) set(FMODWRAPPER_LIBRARY fmodwrapper) target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) - endif (NOT WINDOWS) + else (DARWIN) + # fmodwrapper unnecessary on linux or windows + set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) + endif (DARWIN) endif (FMOD) set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") @@ -1292,6 +1311,11 @@ if (LLKDU_LIBRARY) add_dependencies(${VIEWER_BINARY_NAME} ${LLKDU_LIBRARY}) endif (LLKDU_LIBRARY) +# add package files +file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) +list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST}) + set(PACKAGE OFF CACHE BOOL "Add a package target that builds an installer package.") @@ -1348,7 +1372,28 @@ if (WINDOWS) COMMENT "Copying message.xml to the runtime folder." ) - add_dependencies(${VIEWER_BINARY_NAME} copy_win_libs) + if(WINDOWS) + # Copy Win Libs... + # This happens at build time, not config time. We can't glob files in this cmake. + # *FIX:Mani Write a sub script to glob the files... + # *FIX:Mani Use actually dependencies rather than bulk copy. + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} PRE_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_directory + ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMENT "Copying staged dlls." + ) + + add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon) + if(LLKDU_LIBRARY) + # kdu may not exist! + add_dependencies(${VIEWER_BINARY_NAME} llkdu) + endif(LLKDU_LIBRARY) + endif(WINDOWS) if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts) @@ -1374,8 +1419,29 @@ if (WINDOWS) add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) if (PACKAGE) - add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2 + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CFG_INTDIR} + + DEPENDS + lleventhost + ${EVENT_HOST_SCRIPTS} + ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py) + + add_custom_target(package ALL + DEPENDS + ${CMAKE_CFG_INTDIR}/touched.bat) + # temporarily disable packaging of event_host until hg subrepos get + # sorted out on the parabuild cluster... + #${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2) add_dependencies(package windows-updater windows-crash-logger) + + endif (PACKAGE) endif (WINDOWS) @@ -1412,6 +1478,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${WINDOWS_LIBRARIES} ${XMLRPCEPI_LIBRARIES} ${ELFIO_LIBRARIES} + ${LLLOGIN_LIBRARIES} ${GOOGLE_PERFTOOLS_LIBRARIES} ) @@ -1545,7 +1612,9 @@ include(LLAddBuildTest) SET(viewer_TEST_SOURCE_FILES llagentaccess.cpp lldateutil.cpp + llmediadataclient.cpp llviewerhelputil.cpp + lllogininstance.cpp ) set_source_files_properties( ${viewer_TEST_SOURCE_FILES} @@ -1562,6 +1631,7 @@ set(test_libs ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} + ${GOOGLEMOCK_LIBRARIES} ) LL_ADD_INTEGRATION_TEST(llcapabilitylistener @@ -1576,6 +1646,16 @@ LL_ADD_INTEGRATION_TEST(llcapabilitylistener # Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py if (WINDOWS) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + make_directory + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Creating llplugin dir." + ) + get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD @@ -1611,5 +1691,72 @@ if (WINDOWS) ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin COMMENT "Copying Quicktime Plugin to the runtime folder." ) + + #******************************* + # Copy media plugin support dlls + # Debug config runtime files required for the plugins + set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") + set(plugins_debug_files + libeay32.dll + qtcored4.dll + qtguid4.dll + qtnetworkd4.dll + qtopengld4.dll + qtwebkitd4.dll + ssleay32.dll + ) + copy_if_different( + ${plugins_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin" + out_targets + ${plugins_debug_files} + ) + set(media_plugin_targets ${media_plugin_targets} ${out_targets}) + + # Release & ReleaseDebInfo config runtime files required for the plugins + set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") + set(plugins_release_files + libeay32.dll + qtcore4.dll + qtgui4.dll + qtnetwork4.dll + qtopengl4.dll + qtwebkit4.dll + ssleay32.dll + ) + copy_if_different( + ${plugins_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin" + out_targets + ${plugins_release_files} + ) + set(media_plugin_targets ${media_plugin_targets} ${out_targets}) + + copy_if_different( + ${plugins_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin" + out_targets + ${plugins_release_files} + ) + set(media_plugin_targets ${media_plugin_targets} ${out_targets}) + + add_custom_target(copy_media_plugin_libs ALL + DEPENDS + ${media_plugin_targets} + ) + + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_directory + ${CMAKE_BINARY_DIR}/test_apps/llplugintest/${CMAKE_CFG_INTDIR}/imageformats + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/imageformats + COMMENT "Copying llpluging imageformat libs." + ) + + add_dependencies(${VIEWER_BINARY_NAME} llmediaplugintest copy_media_plugin_libs) + endif (WINDOWS) diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 735424c647..dceaba9a43 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.0.0.0"; -CFBundleGetInfoString = "Second Life version 2.0.0.0, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.0.0.3256"; +CFBundleGetInfoString = "Second Life version 2.0.0.3256, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 7264044d37..7aec8a343d 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.0.0.0</string> + <string>2.0.0.3256</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7e368b0c9c..eb045349c2 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -375,6 +375,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>AutoPlayMedia</key> + <map> + <key>Comment</key> + <string>Allow media objects to automatically play or navigate?</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>AutoSnapshot</key> <map> <key>Comment</key> @@ -5316,6 +5327,17 @@ <key>Value</key> <integer>13</integer> </map> + <key>PrimMediaMaxRetries</key> + <map> + <key>Comment</key> + <string>Maximum number of retries for media queries.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>4</integer> + </map> <key>PrimMediaRequestQueueDelay</key> <map> <key>Comment</key> @@ -5404,6 +5426,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>QAModeEventHostPort</key> + <map> + <key>Comment</key> + <string>Enable Testing Features.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>-1</integer> + </map> <key>QuietSnapshotsToDisk</key> <map> <key>Comment</key> @@ -10014,7 +10047,7 @@ <key>Comment</key> <string>Versioning Channel Name.</string> <key>Persist</key> - <integer>1</integer> + <integer>0</integer> <key>Type</key> <string>String</string> <key>Value</key> diff --git a/indra/newview/build_win32_appConfig.py b/indra/newview/build_win32_appConfig.py index fb6a0258bc..8eadf0068f 100644 --- a/indra/newview/build_win32_appConfig.py +++ b/indra/newview/build_win32_appConfig.py @@ -31,11 +31,7 @@ import sys, os, re from xml.dom.minidom import parse -def main(): - src_manifest_name = sys.argv[1] - src_config_name = sys.argv[2] - dst_config_name = sys.argv[3] - +def munge_binding_redirect_version(src_manifest_name, src_config_name, dst_config_name): manifest_dom = parse(src_manifest_name) node = manifest_dom.getElementsByTagName('assemblyIdentity')[0] manifest_assm_ver = node.getAttribute('version') @@ -47,11 +43,31 @@ def main(): node.setAttribute('oldVersion', src_old_ver + manifest_assm_ver) comment = config_dom.createComment("This file is automatically generated by the build. see indra/newview/build_win32_appConfig.py") config_dom.insertBefore(comment, config_dom.childNodes[0]) - + + print "Writing: " + dst_config_name f = open(dst_config_name, 'w') config_dom.writexml(f) f.close() + + + +def main(): + config = sys.argv[1] + src_dir = sys.argv[2] + dst_dir = sys.argv[3] + dst_name = sys.argv[4] + + if config.lower() == 'debug': + src_manifest_name = dst_dir + '/Microsoft.VC80.DebugCRT.manifest' + src_config_name = src_dir + '/SecondLifeDebug.exe.config' + else: + src_manifest_name = dst_dir + '/Microsoft.VC80.CRT.manifest' + src_config_name = src_dir + '/SecondLife.exe.config' + + dst_config_name = dst_dir + '/' + dst_name + munge_binding_redirect_version(src_manifest_name, src_config_name, dst_config_name) + return 0 if __name__ == "__main__": diff --git a/indra/newview/character/avatar_eye.llm b/indra/newview/character/avatar_eye.llm Binary files differnew file mode 100644 index 0000000000..8c6e74e1de --- /dev/null +++ b/indra/newview/character/avatar_eye.llm diff --git a/indra/newview/character/avatar_eye_1.llm b/indra/newview/character/avatar_eye_1.llm Binary files differnew file mode 100644 index 0000000000..7a3b0d6f28 --- /dev/null +++ b/indra/newview/character/avatar_eye_1.llm diff --git a/indra/newview/character/avatar_eyelashes.llm b/indra/newview/character/avatar_eyelashes.llm Binary files differnew file mode 100644 index 0000000000..99995b5758 --- /dev/null +++ b/indra/newview/character/avatar_eyelashes.llm diff --git a/indra/newview/character/avatar_hair.llm b/indra/newview/character/avatar_hair.llm Binary files differnew file mode 100644 index 0000000000..df99de8db7 --- /dev/null +++ b/indra/newview/character/avatar_hair.llm diff --git a/indra/newview/character/avatar_hair_1.llm b/indra/newview/character/avatar_hair_1.llm Binary files differnew file mode 100644 index 0000000000..6de31fdc23 --- /dev/null +++ b/indra/newview/character/avatar_hair_1.llm diff --git a/indra/newview/character/avatar_hair_2.llm b/indra/newview/character/avatar_hair_2.llm Binary files differnew file mode 100644 index 0000000000..47d02ba9ce --- /dev/null +++ b/indra/newview/character/avatar_hair_2.llm diff --git a/indra/newview/character/avatar_hair_3.llm b/indra/newview/character/avatar_hair_3.llm Binary files differnew file mode 100644 index 0000000000..107f9e2a53 --- /dev/null +++ b/indra/newview/character/avatar_hair_3.llm diff --git a/indra/newview/character/avatar_hair_4.llm b/indra/newview/character/avatar_hair_4.llm Binary files differnew file mode 100644 index 0000000000..1b9a12a0ca --- /dev/null +++ b/indra/newview/character/avatar_hair_4.llm diff --git a/indra/newview/character/avatar_hair_5.llm b/indra/newview/character/avatar_hair_5.llm Binary files differnew file mode 100644 index 0000000000..1b9a12a0ca --- /dev/null +++ b/indra/newview/character/avatar_hair_5.llm diff --git a/indra/newview/character/avatar_head.llm b/indra/newview/character/avatar_head.llm Binary files differnew file mode 100644 index 0000000000..8d8b5e0442 --- /dev/null +++ b/indra/newview/character/avatar_head.llm diff --git a/indra/newview/character/avatar_head_1.llm b/indra/newview/character/avatar_head_1.llm Binary files differnew file mode 100644 index 0000000000..26291e6584 --- /dev/null +++ b/indra/newview/character/avatar_head_1.llm diff --git a/indra/newview/character/avatar_head_2.llm b/indra/newview/character/avatar_head_2.llm Binary files differnew file mode 100644 index 0000000000..c2b808b1a6 --- /dev/null +++ b/indra/newview/character/avatar_head_2.llm diff --git a/indra/newview/character/avatar_head_3.llm b/indra/newview/character/avatar_head_3.llm Binary files differnew file mode 100644 index 0000000000..a0676b1f1c --- /dev/null +++ b/indra/newview/character/avatar_head_3.llm diff --git a/indra/newview/character/avatar_head_4.llm b/indra/newview/character/avatar_head_4.llm Binary files differnew file mode 100644 index 0000000000..5035585770 --- /dev/null +++ b/indra/newview/character/avatar_head_4.llm diff --git a/indra/newview/character/avatar_lower_body.llm b/indra/newview/character/avatar_lower_body.llm Binary files differnew file mode 100644 index 0000000000..0420899739 --- /dev/null +++ b/indra/newview/character/avatar_lower_body.llm diff --git a/indra/newview/character/avatar_lower_body_1.llm b/indra/newview/character/avatar_lower_body_1.llm Binary files differnew file mode 100644 index 0000000000..1394eb848b --- /dev/null +++ b/indra/newview/character/avatar_lower_body_1.llm diff --git a/indra/newview/character/avatar_lower_body_2.llm b/indra/newview/character/avatar_lower_body_2.llm Binary files differnew file mode 100644 index 0000000000..0da9c1249e --- /dev/null +++ b/indra/newview/character/avatar_lower_body_2.llm diff --git a/indra/newview/character/avatar_lower_body_3.llm b/indra/newview/character/avatar_lower_body_3.llm Binary files differnew file mode 100644 index 0000000000..f3c49a1568 --- /dev/null +++ b/indra/newview/character/avatar_lower_body_3.llm diff --git a/indra/newview/character/avatar_lower_body_4.llm b/indra/newview/character/avatar_lower_body_4.llm Binary files differnew file mode 100644 index 0000000000..e71721063e --- /dev/null +++ b/indra/newview/character/avatar_lower_body_4.llm diff --git a/indra/newview/character/avatar_skirt.llm b/indra/newview/character/avatar_skirt.llm Binary files differnew file mode 100644 index 0000000000..08ce3d1700 --- /dev/null +++ b/indra/newview/character/avatar_skirt.llm diff --git a/indra/newview/character/avatar_skirt_1.llm b/indra/newview/character/avatar_skirt_1.llm Binary files differnew file mode 100644 index 0000000000..88076c321f --- /dev/null +++ b/indra/newview/character/avatar_skirt_1.llm diff --git a/indra/newview/character/avatar_skirt_2.llm b/indra/newview/character/avatar_skirt_2.llm Binary files differnew file mode 100644 index 0000000000..73b3effbc6 --- /dev/null +++ b/indra/newview/character/avatar_skirt_2.llm diff --git a/indra/newview/character/avatar_skirt_3.llm b/indra/newview/character/avatar_skirt_3.llm Binary files differnew file mode 100644 index 0000000000..ded546fdea --- /dev/null +++ b/indra/newview/character/avatar_skirt_3.llm diff --git a/indra/newview/character/avatar_skirt_4.llm b/indra/newview/character/avatar_skirt_4.llm Binary files differnew file mode 100644 index 0000000000..b9d5cb945e --- /dev/null +++ b/indra/newview/character/avatar_skirt_4.llm diff --git a/indra/newview/character/avatar_upper_body.llm b/indra/newview/character/avatar_upper_body.llm Binary files differnew file mode 100644 index 0000000000..da7d990540 --- /dev/null +++ b/indra/newview/character/avatar_upper_body.llm diff --git a/indra/newview/character/avatar_upper_body_1.llm b/indra/newview/character/avatar_upper_body_1.llm Binary files differnew file mode 100644 index 0000000000..31e104cc20 --- /dev/null +++ b/indra/newview/character/avatar_upper_body_1.llm diff --git a/indra/newview/character/avatar_upper_body_2.llm b/indra/newview/character/avatar_upper_body_2.llm Binary files differnew file mode 100644 index 0000000000..c1f4199b9c --- /dev/null +++ b/indra/newview/character/avatar_upper_body_2.llm diff --git a/indra/newview/character/avatar_upper_body_3.llm b/indra/newview/character/avatar_upper_body_3.llm Binary files differnew file mode 100644 index 0000000000..9e89ed8b3e --- /dev/null +++ b/indra/newview/character/avatar_upper_body_3.llm diff --git a/indra/newview/character/avatar_upper_body_4.llm b/indra/newview/character/avatar_upper_body_4.llm Binary files differnew file mode 100644 index 0000000000..ec836d1dc3 --- /dev/null +++ b/indra/newview/character/avatar_upper_body_4.llm diff --git a/indra/newview/character/blush_alpha.tga b/indra/newview/character/blush_alpha.tga Binary files differnew file mode 100644 index 0000000000..05be7e7e3d --- /dev/null +++ b/indra/newview/character/blush_alpha.tga diff --git a/indra/newview/character/body_skingrain.tga b/indra/newview/character/body_skingrain.tga Binary files differnew file mode 100644 index 0000000000..7264baac14 --- /dev/null +++ b/indra/newview/character/body_skingrain.tga diff --git a/indra/newview/character/bodyfreckles_alpha.tga b/indra/newview/character/bodyfreckles_alpha.tga Binary files differnew file mode 100644 index 0000000000..d30ab3d122 --- /dev/null +++ b/indra/newview/character/bodyfreckles_alpha.tga diff --git a/indra/newview/character/bump_face_wrinkles.tga b/indra/newview/character/bump_face_wrinkles.tga Binary files differnew file mode 100644 index 0000000000..54bf7a55be --- /dev/null +++ b/indra/newview/character/bump_face_wrinkles.tga diff --git a/indra/newview/character/bump_head_base.tga b/indra/newview/character/bump_head_base.tga Binary files differnew file mode 100644 index 0000000000..fa3568573a --- /dev/null +++ b/indra/newview/character/bump_head_base.tga diff --git a/indra/newview/character/bump_lowerbody_base.tga b/indra/newview/character/bump_lowerbody_base.tga Binary files differnew file mode 100644 index 0000000000..498ea3c721 --- /dev/null +++ b/indra/newview/character/bump_lowerbody_base.tga diff --git a/indra/newview/character/bump_pants_wrinkles.tga b/indra/newview/character/bump_pants_wrinkles.tga Binary files differnew file mode 100644 index 0000000000..cca72415e8 --- /dev/null +++ b/indra/newview/character/bump_pants_wrinkles.tga diff --git a/indra/newview/character/bump_shirt_wrinkles.tga b/indra/newview/character/bump_shirt_wrinkles.tga Binary files differnew file mode 100644 index 0000000000..9e0d757a48 --- /dev/null +++ b/indra/newview/character/bump_shirt_wrinkles.tga diff --git a/indra/newview/character/bump_upperbody_base.tga b/indra/newview/character/bump_upperbody_base.tga Binary files differnew file mode 100644 index 0000000000..e57d6352e6 --- /dev/null +++ b/indra/newview/character/bump_upperbody_base.tga diff --git a/indra/newview/character/eyebrows_alpha.tga b/indra/newview/character/eyebrows_alpha.tga Binary files differnew file mode 100644 index 0000000000..c363e482e1 --- /dev/null +++ b/indra/newview/character/eyebrows_alpha.tga diff --git a/indra/newview/character/eyeliner_alpha.tga b/indra/newview/character/eyeliner_alpha.tga Binary files differnew file mode 100644 index 0000000000..1611eb3355 --- /dev/null +++ b/indra/newview/character/eyeliner_alpha.tga diff --git a/indra/newview/character/eyeshadow_inner_alpha.tga b/indra/newview/character/eyeshadow_inner_alpha.tga Binary files differnew file mode 100644 index 0000000000..37d7919395 --- /dev/null +++ b/indra/newview/character/eyeshadow_inner_alpha.tga diff --git a/indra/newview/character/eyeshadow_outer_alpha.tga b/indra/newview/character/eyeshadow_outer_alpha.tga Binary files differnew file mode 100644 index 0000000000..00eef9d9f7 --- /dev/null +++ b/indra/newview/character/eyeshadow_outer_alpha.tga diff --git a/indra/newview/character/eyewhite.tga b/indra/newview/character/eyewhite.tga Binary files differnew file mode 100644 index 0000000000..a720496988 --- /dev/null +++ b/indra/newview/character/eyewhite.tga diff --git a/indra/newview/character/facehair_chincurtains_alpha.tga b/indra/newview/character/facehair_chincurtains_alpha.tga Binary files differnew file mode 100644 index 0000000000..b10397063c --- /dev/null +++ b/indra/newview/character/facehair_chincurtains_alpha.tga diff --git a/indra/newview/character/facehair_moustache_alpha.tga b/indra/newview/character/facehair_moustache_alpha.tga Binary files differnew file mode 100644 index 0000000000..4068c4f2b1 --- /dev/null +++ b/indra/newview/character/facehair_moustache_alpha.tga diff --git a/indra/newview/character/facehair_sideburns_alpha.tga b/indra/newview/character/facehair_sideburns_alpha.tga Binary files differnew file mode 100644 index 0000000000..acddc2d9bd --- /dev/null +++ b/indra/newview/character/facehair_sideburns_alpha.tga diff --git a/indra/newview/character/facehair_soulpatch_alpha.tga b/indra/newview/character/facehair_soulpatch_alpha.tga Binary files differnew file mode 100644 index 0000000000..687091a29f --- /dev/null +++ b/indra/newview/character/facehair_soulpatch_alpha.tga diff --git a/indra/newview/character/freckles_alpha.tga b/indra/newview/character/freckles_alpha.tga Binary files differnew file mode 100644 index 0000000000..a9a4ec0735 --- /dev/null +++ b/indra/newview/character/freckles_alpha.tga diff --git a/indra/newview/character/glove_length_alpha.tga b/indra/newview/character/glove_length_alpha.tga Binary files differnew file mode 100644 index 0000000000..db89ad57e7 --- /dev/null +++ b/indra/newview/character/glove_length_alpha.tga diff --git a/indra/newview/character/gloves_fingers_alpha.tga b/indra/newview/character/gloves_fingers_alpha.tga Binary files differnew file mode 100644 index 0000000000..dba2eec277 --- /dev/null +++ b/indra/newview/character/gloves_fingers_alpha.tga diff --git a/indra/newview/character/head_alpha.tga b/indra/newview/character/head_alpha.tga Binary files differnew file mode 100644 index 0000000000..8164525353 --- /dev/null +++ b/indra/newview/character/head_alpha.tga diff --git a/indra/newview/character/head_color.tga b/indra/newview/character/head_color.tga Binary files differnew file mode 100644 index 0000000000..74b1b3078b --- /dev/null +++ b/indra/newview/character/head_color.tga diff --git a/indra/newview/character/head_hair.tga b/indra/newview/character/head_hair.tga Binary files differnew file mode 100644 index 0000000000..5321f35204 --- /dev/null +++ b/indra/newview/character/head_hair.tga diff --git a/indra/newview/character/head_highlights_alpha.tga b/indra/newview/character/head_highlights_alpha.tga Binary files differnew file mode 100644 index 0000000000..8dc5239f97 --- /dev/null +++ b/indra/newview/character/head_highlights_alpha.tga diff --git a/indra/newview/character/head_shading_alpha.tga b/indra/newview/character/head_shading_alpha.tga Binary files differnew file mode 100644 index 0000000000..e8ea490109 --- /dev/null +++ b/indra/newview/character/head_shading_alpha.tga diff --git a/indra/newview/character/head_skingrain.tga b/indra/newview/character/head_skingrain.tga Binary files differnew file mode 100644 index 0000000000..b42dee0809 --- /dev/null +++ b/indra/newview/character/head_skingrain.tga diff --git a/indra/newview/character/jacket_length_lower_alpha.tga b/indra/newview/character/jacket_length_lower_alpha.tga Binary files differnew file mode 100644 index 0000000000..722bc192a8 --- /dev/null +++ b/indra/newview/character/jacket_length_lower_alpha.tga diff --git a/indra/newview/character/jacket_length_upper_alpha.tga b/indra/newview/character/jacket_length_upper_alpha.tga Binary files differnew file mode 100644 index 0000000000..e9db7e7b1f --- /dev/null +++ b/indra/newview/character/jacket_length_upper_alpha.tga diff --git a/indra/newview/character/jacket_open_lower_alpha.tga b/indra/newview/character/jacket_open_lower_alpha.tga Binary files differnew file mode 100644 index 0000000000..db0c2fb0e3 --- /dev/null +++ b/indra/newview/character/jacket_open_lower_alpha.tga diff --git a/indra/newview/character/jacket_open_upper_alpha.tga b/indra/newview/character/jacket_open_upper_alpha.tga Binary files differnew file mode 100644 index 0000000000..71b8a0b805 --- /dev/null +++ b/indra/newview/character/jacket_open_upper_alpha.tga diff --git a/indra/newview/character/lipgloss_alpha.tga b/indra/newview/character/lipgloss_alpha.tga Binary files differnew file mode 100644 index 0000000000..78ceecaf85 --- /dev/null +++ b/indra/newview/character/lipgloss_alpha.tga diff --git a/indra/newview/character/lips_mask.tga b/indra/newview/character/lips_mask.tga Binary files differnew file mode 100644 index 0000000000..ae1401c006 --- /dev/null +++ b/indra/newview/character/lips_mask.tga diff --git a/indra/newview/character/lipstick_alpha.tga b/indra/newview/character/lipstick_alpha.tga Binary files differnew file mode 100644 index 0000000000..2795f1bd40 --- /dev/null +++ b/indra/newview/character/lipstick_alpha.tga diff --git a/indra/newview/character/lowerbody_color.tga b/indra/newview/character/lowerbody_color.tga Binary files differnew file mode 100644 index 0000000000..a63aa12fca --- /dev/null +++ b/indra/newview/character/lowerbody_color.tga diff --git a/indra/newview/character/lowerbody_highlights_alpha.tga b/indra/newview/character/lowerbody_highlights_alpha.tga Binary files differnew file mode 100644 index 0000000000..ae3413ac8b --- /dev/null +++ b/indra/newview/character/lowerbody_highlights_alpha.tga diff --git a/indra/newview/character/lowerbody_shading_alpha.tga b/indra/newview/character/lowerbody_shading_alpha.tga Binary files differnew file mode 100644 index 0000000000..0242663a7d --- /dev/null +++ b/indra/newview/character/lowerbody_shading_alpha.tga diff --git a/indra/newview/character/nailpolish_alpha.tga b/indra/newview/character/nailpolish_alpha.tga Binary files differnew file mode 100644 index 0000000000..91af762902 --- /dev/null +++ b/indra/newview/character/nailpolish_alpha.tga diff --git a/indra/newview/character/pants_length_alpha.tga b/indra/newview/character/pants_length_alpha.tga Binary files differnew file mode 100644 index 0000000000..3c4f21c0f2 --- /dev/null +++ b/indra/newview/character/pants_length_alpha.tga diff --git a/indra/newview/character/pants_waist_alpha.tga b/indra/newview/character/pants_waist_alpha.tga Binary files differnew file mode 100644 index 0000000000..35658c0896 --- /dev/null +++ b/indra/newview/character/pants_waist_alpha.tga diff --git a/indra/newview/character/rosyface_alpha.tga b/indra/newview/character/rosyface_alpha.tga Binary files differnew file mode 100644 index 0000000000..a0c8513da2 --- /dev/null +++ b/indra/newview/character/rosyface_alpha.tga diff --git a/indra/newview/character/rouge_alpha.tga b/indra/newview/character/rouge_alpha.tga Binary files differnew file mode 100644 index 0000000000..a0c8513da2 --- /dev/null +++ b/indra/newview/character/rouge_alpha.tga diff --git a/indra/newview/character/shirt_bottom_alpha.tga b/indra/newview/character/shirt_bottom_alpha.tga Binary files differnew file mode 100644 index 0000000000..7cce03dbe0 --- /dev/null +++ b/indra/newview/character/shirt_bottom_alpha.tga diff --git a/indra/newview/character/shirt_collar_alpha.tga b/indra/newview/character/shirt_collar_alpha.tga Binary files differnew file mode 100644 index 0000000000..f55f635473 --- /dev/null +++ b/indra/newview/character/shirt_collar_alpha.tga diff --git a/indra/newview/character/shirt_collar_back_alpha.tga b/indra/newview/character/shirt_collar_back_alpha.tga Binary files differnew file mode 100644 index 0000000000..43a6453107 --- /dev/null +++ b/indra/newview/character/shirt_collar_back_alpha.tga diff --git a/indra/newview/character/shirt_sleeve_alpha.tga b/indra/newview/character/shirt_sleeve_alpha.tga Binary files differnew file mode 100644 index 0000000000..e3b18f4fc6 --- /dev/null +++ b/indra/newview/character/shirt_sleeve_alpha.tga diff --git a/indra/newview/character/shoe_height_alpha.tga b/indra/newview/character/shoe_height_alpha.tga Binary files differnew file mode 100644 index 0000000000..d08dd750f3 --- /dev/null +++ b/indra/newview/character/shoe_height_alpha.tga diff --git a/indra/newview/character/skirt_length_alpha.tga b/indra/newview/character/skirt_length_alpha.tga Binary files differnew file mode 100644 index 0000000000..c86799469d --- /dev/null +++ b/indra/newview/character/skirt_length_alpha.tga diff --git a/indra/newview/character/skirt_slit_back_alpha.tga b/indra/newview/character/skirt_slit_back_alpha.tga Binary files differnew file mode 100644 index 0000000000..0e49688b14 --- /dev/null +++ b/indra/newview/character/skirt_slit_back_alpha.tga diff --git a/indra/newview/character/skirt_slit_front_alpha.tga b/indra/newview/character/skirt_slit_front_alpha.tga Binary files differnew file mode 100644 index 0000000000..888bbf71a1 --- /dev/null +++ b/indra/newview/character/skirt_slit_front_alpha.tga diff --git a/indra/newview/character/skirt_slit_left_alpha.tga b/indra/newview/character/skirt_slit_left_alpha.tga Binary files differnew file mode 100644 index 0000000000..210feac1ea --- /dev/null +++ b/indra/newview/character/skirt_slit_left_alpha.tga diff --git a/indra/newview/character/skirt_slit_right_alpha.tga b/indra/newview/character/skirt_slit_right_alpha.tga Binary files differnew file mode 100644 index 0000000000..ce11c64bf6 --- /dev/null +++ b/indra/newview/character/skirt_slit_right_alpha.tga diff --git a/indra/newview/character/underpants_trial_female.tga b/indra/newview/character/underpants_trial_female.tga Binary files differnew file mode 100644 index 0000000000..96bf732351 --- /dev/null +++ b/indra/newview/character/underpants_trial_female.tga diff --git a/indra/newview/character/underpants_trial_male.tga b/indra/newview/character/underpants_trial_male.tga Binary files differnew file mode 100644 index 0000000000..095695ca1c --- /dev/null +++ b/indra/newview/character/underpants_trial_male.tga diff --git a/indra/newview/character/undershirt_trial_female.tga b/indra/newview/character/undershirt_trial_female.tga Binary files differnew file mode 100644 index 0000000000..e17a309531 --- /dev/null +++ b/indra/newview/character/undershirt_trial_female.tga diff --git a/indra/newview/character/upperbody_color.tga b/indra/newview/character/upperbody_color.tga Binary files differnew file mode 100644 index 0000000000..85fcc41142 --- /dev/null +++ b/indra/newview/character/upperbody_color.tga diff --git a/indra/newview/character/upperbody_highlights_alpha.tga b/indra/newview/character/upperbody_highlights_alpha.tga Binary files differnew file mode 100644 index 0000000000..2d8102b583 --- /dev/null +++ b/indra/newview/character/upperbody_highlights_alpha.tga diff --git a/indra/newview/character/upperbody_shading_alpha.tga b/indra/newview/character/upperbody_shading_alpha.tga Binary files differnew file mode 100644 index 0000000000..b420506b3e --- /dev/null +++ b/indra/newview/character/upperbody_shading_alpha.tga diff --git a/indra/newview/character/upperbodyfreckles_alpha.tga b/indra/newview/character/upperbodyfreckles_alpha.tga Binary files differnew file mode 100644 index 0000000000..76c7ce8849 --- /dev/null +++ b/indra/newview/character/upperbodyfreckles_alpha.tga diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt index d488c7487e..1324fa1a86 100644 --- a/indra/newview/licenses-mac.txt +++ b/indra/newview/licenses-mac.txt @@ -315,6 +315,515 @@ This product includes cryptographic software written by Eric Young Hudson (tjh@cryptsoft.com). +=========== +Pth License +=========== + ____ _ _ + | _ \| |_| |__ ``Ian Fleming was a UNIX fan! + | |_) | __| '_ \ How do I know? Well, James Bond + | __/| |_| | | | had the (license to kill) number 007, + |_| \__|_| |_| i.e., he could execute anyone!'' + + GNU Pth - The GNU Portable Threads + + LICENSE + ======= + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + For some people, it is not clear, what is the real intention of the + author by using the GNU Lesser General Public License (LGPL) as the + distribution license for GNU Pth. This is, because the LGPL and the + GPL can be (and are often) interpreted very differently and some + interpretations seem to be not compatible with others. So an explicit + clarification for the use of the LGPL for GNU Pth from the authors + point of view might be useful. + + The author places this library under the LGPL to make sure that it + can be used both commercially and non-commercially provided that + modifications to the code base are always donated back to the official + code base under the same license conditions. Please keep in mind that + especially using this library in code not staying under the GPL or + the LGPL _is_ allowed and that any taint or license creap into code + that uses the library is not the authors intention. It is just the + case that _including_ this library into the source tree of other + applications is a little bit more inconvinient because of the LGPL. + But it has to be this way for good reasons. And keep in mind that + inconvinient doesn't mean not allowed or even impossible. + + Even if you want to use this library in some BSD-style licensed + packages, this _is_ possible as long as you are a little bit + carefully. Usually this means you have to make sure that the code is + still clearly separated into the source tree and that modifications to + this source area are done under the conditions of the LGPL. Read below + for more details on the conditions. Contact the author if you have + more questions. + + The license text of the GNU Lesser General Public License follows: + __________________________________________________________________________ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + ======================= Original SSLeay License diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 0fa3b1f04d..f62606cc50 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "llagentwearables.h" +#include "llagentlistener.h" #include "llanimationstates.h" #include "llcallingcard.h" #include "llconsole.h" @@ -255,6 +256,7 @@ LLAgent::LLAgent() : mHUDTargetZoom(1.f), mHUDCurZoom(1.f), mInitialized(FALSE), + mListener(), mForceMouselook(FALSE), mDoubleTapRunTimer(), @@ -383,6 +385,8 @@ LLAgent::LLAgent() : } mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); + + mListener.reset(new LLAgentListener(*this)); } // Requires gSavedSettings to be initialized. @@ -5971,7 +5975,7 @@ bool LLAgent::teleportCore(bool is_local) LLFloaterReg::hideInstance("about_land"); LLViewerParcelMgr::getInstance()->deselectLand(); - LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL); + LLViewerMediaFocus::getInstance()->clearFocus(); // Close all pie menus, deselect land, etc. // Don't change the camera until we know teleport succeeded. JC diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index b334874e6e..99a9bdd8e6 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -105,6 +105,8 @@ struct LLGroupData std::string mName; }; +class LLAgentListener; + //------------------------------------------------------------------------ // LLAgent //------------------------------------------------------------------------ @@ -142,6 +144,8 @@ public: BOOL mInitialized; BOOL mFirstLogin; std::string mMOTD; // Message of the day +private: + boost::shared_ptr<LLAgentListener> mListener; //-------------------------------------------------------------------- // Session diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp new file mode 100644 index 0000000000..0f00078b33 --- /dev/null +++ b/indra/newview/llagentlistener.cpp @@ -0,0 +1,78 @@ +/** + * @file llagentlistener.cpp + * @author Brad Kittenbrink + * @date 2009-07-10 + * @brief Implementation for llagentlistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagentlistener.h" + +#include "llagent.h" +#include "llcommandhandler.h" +#include "llslurl.h" +#include "llurldispatcher.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" + +LLAgentListener::LLAgentListener(LLAgent &agent) + : LLDispatchListener("LLAgent", "op"), + mAgent(agent) +{ + add("requestTeleport", &LLAgentListener::requestTeleport); + add("requestSit", &LLAgentListener::requestSit); + add("requestStand", &LLAgentListener::requestStand); +} + +void LLAgentListener::requestTeleport(LLSD const & event_data) const +{ + if(event_data["skip_confirmation"].asBoolean()) + { + LLSD params(LLSD::emptyArray()); + params.append(event_data["regionname"]); + params.append(event_data["x"]); + params.append(event_data["y"]); + params.append(event_data["z"]); + LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true); + // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "objectim", "parcel", "login", login_refresh", "balance", "chat" + // should we just compose LLCommandHandler and LLDispatchListener? + } + else + { + std::string url = LLSLURL::buildSLURL(event_data["regionname"], event_data["x"], event_data["y"], event_data["z"]); + LLURLDispatcher::dispatch(url, NULL, false); + } +} + +void LLAgentListener::requestSit(LLSD const & event_data) const +{ + //mAgent.getAvatarObject()->sitOnObject(); + // shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand() + // *TODO - find a permanent place to share this code properly. + LLViewerObject *object = gObjectList.findObject(event_data["obj_uuid"]); + + if (object && object->getPCode() == LL_PCODE_VOLUME) + { + gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, mAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, mAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_TargetObject); + gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID); + gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3(0,0,0)); + + object->getRegion()->sendReliableMessage(); + } +} + +void LLAgentListener::requestStand(LLSD const & event_data) const +{ + mAgent.setControlFlags(AGENT_CONTROL_STAND_UP); +} + diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h new file mode 100644 index 0000000000..6f0b5a54c5 --- /dev/null +++ b/indra/newview/llagentlistener.h @@ -0,0 +1,36 @@ +/** + * @file llagentlistener.h + * @author Brad Kittenbrink + * @date 2009-07-09 + * @brief Event API for subset of LLViewerControl methods + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + + +#ifndef LL_LLAGENTLISTENER_H +#define LL_LLAGENTLISTENER_H + +#include "lleventdispatcher.h" + +class LLAgent; +class LLSD; + +class LLAgentListener : public LLDispatchListener +{ +public: + LLAgentListener(LLAgent &agent); + +private: + void requestTeleport(LLSD const & event_data) const; + void requestSit(LLSD const & event_data) const; + void requestStand(LLSD const & event_data) const; + +private: + LLAgent & mAgent; +}; + +#endif // LL_LLAGENTLISTENER_H + diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c673db2034..923a66ee8e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -73,6 +73,7 @@ #include "llurlhistory.h" #include "llfirstuse.h" #include "llrender.h" +#include "llteleporthistory.h" #include "lllocationhistory.h" #include "llfasttimerview.h" @@ -91,14 +92,15 @@ #if LL_WINDOWS #include "llwindebug.h" -#endif - -#if LL_WINDOWS # include <share.h> // For _SH_DENYWR in initMarkerFile #else # include <sys/file.h> // For initMarkerFile support #endif +#include "llapr.h" +#include "apr_dso.h" +#include <boost/lexical_cast.hpp> + #include "llnotify.h" #include "llviewerkeyboard.h" #include "lllfsthread.h" @@ -154,7 +156,6 @@ #include "llfolderview.h" #include "lltoolbar.h" #include "llagentpilot.h" -#include "llsrv.h" #include "llvovolume.h" #include "llflexibleobject.h" #include "llvosurfacepatch.h" @@ -192,7 +193,19 @@ //---------------------------------------------------------------------------- // llviewernetwork.h #include "llviewernetwork.h" +// define a self-registering event API object +#include "llappviewerlistener.h" + +#if (LL_LINUX || LL_SOLARIS) && LL_GTK +#include "glib.h" +#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +static LLAppViewerListener sAppViewerListener("LLAppViewer", LLAppViewer::instance); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // @@ -218,9 +231,6 @@ BOOL gAllowTapTapHoldRun = TRUE; BOOL gShowObjectUpdates = FALSE; BOOL gUseQuickTime = TRUE; -BOOL gAcceptTOS = FALSE; -BOOL gAcceptCriticalMessage = FALSE; - eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL; LLSD gDebugInfo; @@ -565,9 +575,9 @@ LLAppViewer::LLAppViewer() : mYieldTime(-1), mMainloopTimeout(NULL), mAgentRegionLastAlive(false), - mFastTimerLogThread(NULL), mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)), - mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)) + mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)), + mFastTimerLogThread(NULL) { if(NULL != sInstance) { @@ -877,6 +887,11 @@ bool LLAppViewer::init() LLViewerJoystick::getInstance()->init(false); gGLActive = FALSE; + if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) + { + loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort")); + } + return true; } @@ -1191,6 +1206,21 @@ bool LLAppViewer::mainLoop() bool LLAppViewer::cleanup() { + // workaround for DEV-35406 crash on shutdown + LLEventPumps::instance().reset(); + + // *TODO - generalize this and move DSO wrangling to a helper class -brad + std::set<struct apr_dso_handle_t *>::const_iterator i; + for(i = mPlugins.begin(); i != mPlugins.end(); ++i) + { + int (*ll_plugin_stop_func)(void) = NULL; + apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop"); + ll_plugin_stop_func(); + + rv = apr_dso_unload(*i); + } + mPlugins.clear(); + //---------------------------------------------- //this test code will be removed after the test //test manual call stack tracer @@ -1498,7 +1528,6 @@ bool LLAppViewer::cleanup() //Note: //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao - LLViewerMediaFocus::cleanupClass(); LLViewerMedia::cleanupClass(); LLViewerParcelMedia::cleanupClass(); gTextureList.shutdown(); // shutdown again in case a callback added something @@ -3694,6 +3723,17 @@ void LLAppViewer::idleShutdown() { return; } + + // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup() + // *TODO: ugly + static bool saved_teleport_history = false; + if (!saved_teleport_history) + { + saved_teleport_history = true; + LLTeleportHistory::getInstance()->dump(); + LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this + return; + } static bool saved_snapshot = false; if (!saved_snapshot) @@ -3988,7 +4028,7 @@ void LLAppViewer::forceErrorBadMemoryAccess() return; } -void LLAppViewer::forceErrorInifiniteLoop() +void LLAppViewer::forceErrorInfiniteLoop() { while(true) { @@ -4109,3 +4149,198 @@ void LLAppViewer::handleLoginComplete() writeDebugInfo(); } + +// *TODO - generalize this and move DSO wrangling to a helper class -brad +void LLAppViewer::loadEventHostModule(S32 listen_port) +{ + std::string dso_name = +#if LL_WINDOWS + "lleventhost.dll"; +#elif LL_DARWIN + "liblleventhost.dylib"; +#else + "liblleventhost.so"; +#endif + + std::string dso_path = gDirUtilp->findFile(dso_name, + gDirUtilp->getAppRODataDir(), + gDirUtilp->getExecutableDir()); + + if(dso_path == "") + { + llwarns << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl; + return; + } + + apr_dso_handle_t * eventhost_dso_handle = NULL; + apr_pool_t * eventhost_dso_memory_pool = NULL; + + //attempt to load the shared library + apr_pool_create(&eventhost_dso_memory_pool, NULL); + apr_status_t rv = apr_dso_load(&eventhost_dso_handle, + dso_path.c_str(), + eventhost_dso_memory_pool); + ll_apr_assert_status(rv); + llassert_always(eventhost_dso_handle != NULL); + + int (*ll_plugin_start_func)(LLSD const &) = NULL; + rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start"); + + ll_apr_assert_status(rv); + llassert_always(ll_plugin_start_func != NULL); + + LLSD args; + args["listen_port"] = listen_port; + + int status = ll_plugin_start_func(args); + + if(status != 0) + { + llwarns << "problem loading eventhost plugin, status: " << status << llendl; + } + + mPlugins.insert(eventhost_dso_handle); +} + +void LLAppViewer::launchUpdater() +{ + LLSD query_map = LLSD::emptyMap(); + // *TODO place os string in a global constant +#if LL_WINDOWS + query_map["os"] = "win"; +#elif LL_DARWIN + query_map["os"] = "mac"; +#elif LL_LINUX + query_map["os"] = "lnx"; +#elif LL_SOLARIS + query_map["os"] = "sol"; +#endif + // *TODO change userserver to be grid on both viewer and sim, since + // userserver no longer exists. + query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); + query_map["channel"] = gSavedSettings.getString("VersionChannelName"); + // *TODO constantize this guy + // *NOTE: This URL is also used in win_setup/lldownloader.cpp + LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); + + if(LLAppViewer::sUpdaterInfo) + { + delete LLAppViewer::sUpdaterInfo; + } + LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; + + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLURLSimString::sInstance.mSimString.length() ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString ); + }; + +#if LL_WINDOWS + LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); + if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + // We're hosed, bail + LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; + return; + } + + LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; + + std::string updater_source = gDirUtilp->getAppRODataDir(); + updater_source += gDirUtilp->getDirDelimiter(); + updater_source += "updater.exe"; + + LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source + << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath + << LL_ENDL; + + + if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; + + return; + } + + LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; + + //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. + LLAppViewer::instance()->removeMarkerFile(); // In case updater fails + + // *NOTE:Mani The updater is spawned as the last thing before the WinMain exit. + // see LLAppViewerWin32.cpp + +#elif LL_DARWIN + LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; + LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; + + // Run the auto-updater. + system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ + +#elif (LL_LINUX || LL_SOLARIS) && LL_GTK + // we tell the updater where to find the xml containing string + // translations which it can use for its own UI + std::string xml_strings_file = "strings.xml"; + std::vector<std::string> xui_path_vec = LLUI::getXUIPaths(); + std::string xml_search_paths; + std::vector<std::string>::const_iterator iter; + // build comma-delimited list of xml paths to pass to updater + for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) + { + std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() + + gDirUtilp->getDirDelimiter() + + (*iter); + llinfos << "Got a XUI path: " << this_skin_dir << llendl; + xml_search_paths.append(this_skin_dir); + ++iter; + if (iter != xui_path_vec.end()) + xml_search_paths.append(","); // comma-delimit + } + // build the overall command-line to run the updater correctly + LLAppViewer::sUpdaterInfo->mUpdateExePath = + gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + + " --url \"" + update_url.asString() + "\"" + + " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" + + " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" + + " --stringsdir \"" + xml_search_paths + "\"" + + " --stringsfile \"" + xml_strings_file + "\""; + + LL_INFOS("AppInit") << "Calling updater: " + << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; + + // *TODO: we could use the gdk equivalent to ensure the updater + // gets started on the same screen. + GError *error = NULL; + if (!g_spawn_command_line_async(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), &error)) + { + llerrs << "Failed to launch updater: " + << error->message + << llendl; + } + if (error) { + g_error_free(error); + } +#else + OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); +#endif + + // *REMOVE:Mani - Saving for reference... + // LLAppViewer::instance()->forceQuit(); +} + diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 646b677264..f95d7cb412 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -47,6 +47,8 @@ class LLVFS; class LLWatchdogTimeout; class LLWorkerThread; +struct apr_dso_handle_t; + class LLAppViewer : public LLApp { @@ -124,7 +126,7 @@ public: virtual void forceErrorLLError(); virtual void forceErrorBreakpoint(); virtual void forceErrorBadMemoryAccess(); - virtual void forceErrorInifiniteLoop(); + virtual void forceErrorInfiniteLoop(); virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); @@ -210,6 +212,8 @@ private: void sendLogoutRequest(); void disconnectViewer(); + void loadEventHostModule(S32 listen_port); + // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. static LLAppViewer* sInstance; @@ -255,6 +259,8 @@ private: LLAllocator mAlloc; + std::set<struct apr_dso_handle_t*> mPlugins; + public: //some information for updater typedef struct @@ -263,6 +269,8 @@ public: std::ostringstream mParams; }LLUpdaterInfo ; static LLUpdaterInfo *sUpdaterInfo ; + + void launchUpdater(); }; // consts from viewer.h @@ -278,10 +286,6 @@ extern LLSD gDebugInfo; extern BOOL gAllowTapTapHoldRun; extern BOOL gShowObjectUpdates; -extern BOOL gAcceptTOS; -extern BOOL gAcceptCriticalMessage; - - typedef enum { LAST_EXEC_NORMAL = 0, diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp new file mode 100644 index 0000000000..3259309eee --- /dev/null +++ b/indra/newview/llappviewerlistener.cpp @@ -0,0 +1,40 @@ +/** + * @file llappviewerlistener.cpp + * @author Nat Goodspeed + * @date 2009-06-23 + * @brief Implementation for llappviewerlistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llappviewerlistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llappviewer.h" + +LLAppViewerListener::LLAppViewerListener(const std::string& pumpname, + const LLAppViewerGetter& getter): + LLDispatchListener(pumpname, "op"), + mAppViewerGetter(getter) +{ + // add() every method we want to be able to invoke via this event API. + add("requestQuit", &LLAppViewerListener::requestQuit); + add("forceQuit", &LLAppViewerListener::forceQuit); +} + +void LLAppViewerListener::requestQuit(const LLSD& event) +{ + mAppViewerGetter()->requestQuit(); +} + +void LLAppViewerListener::forceQuit(const LLSD& event) +{ + mAppViewerGetter()->forceQuit(); +} diff --git a/indra/newview/llappviewerlistener.h b/indra/newview/llappviewerlistener.h new file mode 100644 index 0000000000..73227cb95a --- /dev/null +++ b/indra/newview/llappviewerlistener.h @@ -0,0 +1,37 @@ +/** + * @file llappviewerlistener.h + * @author Nat Goodspeed + * @date 2009-06-18 + * @brief Wrap subset of LLAppViewer API in event API + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLAPPVIEWERLISTENER_H) +#define LL_LLAPPVIEWERLISTENER_H + +#include "lleventdispatcher.h" +#include <boost/function.hpp> + +class LLAppViewer; +class LLSD; + +/// Listen on an LLEventPump with specified name for LLAppViewer request events. +class LLAppViewerListener: public LLDispatchListener +{ +public: + typedef boost::function<LLAppViewer*(void)> LLAppViewerGetter; + /// Specify the pump name on which to listen, and bind the LLAppViewer + /// instance to use (e.g. LLAppViewer::instance()). + LLAppViewerListener(const std::string& pumpname, const LLAppViewerGetter& getter); + +private: + void requestQuit(const LLSD& event); + void forceQuit(const LLSD& event); + + LLAppViewerGetter mAppViewerGetter; +}; + +#endif /* ! defined(LL_LLAPPVIEWERLISTENER_H) */ diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 7ae1b5cd4a..ebcda13dd4 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -152,6 +152,8 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) : LLIconCtrl(p), mDrawTooltip(p.draw_tooltip) { + mPriority = LLViewerFetchedTexture::BOOST_ICON; + LLRect rect = p.rect; static LLUICachedControl<S32> llavatariconctrl_symbol_hpad("UIAvatariconctrlSymbolHPad", 2); diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp index 4a3e9aec9c..ed9613c1bc 100644 --- a/indra/newview/llcapabilitylistener.cpp +++ b/indra/newview/llcapabilitylistener.cpp @@ -114,6 +114,7 @@ bool LLCapabilityListener::capListener(const LLSD& request) // This capability is supported by the region to which we're talking. LLHTTPClient::post(url, payload, new LLSDMessage::EventResponder(LLEventPumps::instance(), + request, mProvider.getDescription(), cap, reply, error), LLSD(), // headers diff --git a/indra/newview/llclassifiedinfo.cpp b/indra/newview/llclassifiedinfo.cpp index 5cf1579d0e..5fcafbeca6 100644 --- a/indra/newview/llclassifiedinfo.cpp +++ b/indra/newview/llclassifiedinfo.cpp @@ -38,35 +38,19 @@ LLClassifiedInfo::cat_map LLClassifiedInfo::sCategories; // static -void LLClassifiedInfo::loadCategories(LLUserAuth::options_t classified_options) +void LLClassifiedInfo::loadCategories(const LLSD& options) { - LLUserAuth::options_t::iterator resp_it; - for (resp_it = classified_options.begin(); - resp_it != classified_options.end(); - ++resp_it) + for(LLSD::array_const_iterator resp_it = options.beginArray(), + end = options.endArray(); resp_it != end; ++resp_it) { - const LLUserAuth::response_t& response = *resp_it; - - LLUserAuth::response_t::const_iterator option_it; - - S32 cat_id = 0; - option_it = response.find("category_id"); - if (option_it != response.end()) + LLSD name = (*resp_it)["category_name"]; + if(name.isDefined()) { - cat_id = atoi(option_it->second.c_str()); + LLSD id = (*resp_it)["category_id"]; + if(id.isDefined()) + { + LLClassifiedInfo::sCategories[id.asInteger()] = name.asString(); + } } - else - { - continue; - } - - // Add the category id/name pair - option_it = response.find("category_name"); - if (option_it != response.end()) - { - LLClassifiedInfo::sCategories[cat_id] = option_it->second; - } - } - } diff --git a/indra/newview/llclassifiedinfo.h b/indra/newview/llclassifiedinfo.h index cc5a6bf28f..37134c7e5b 100644 --- a/indra/newview/llclassifiedinfo.h +++ b/indra/newview/llclassifiedinfo.h @@ -37,7 +37,6 @@ #include "v3dmath.h" #include "lluuid.h" -#include "lluserauth.h" class LLMessageSystem; @@ -46,7 +45,7 @@ class LLClassifiedInfo public: LLClassifiedInfo() {} - static void loadCategories(LLUserAuth::options_t event_options); + static void loadCategories(const LLSD& options); typedef std::map<U32, std::string> cat_map; static cat_map sCategories; diff --git a/indra/newview/lleventinfo.cpp b/indra/newview/lleventinfo.cpp index d4175b6c84..9be45d18fb 100644 --- a/indra/newview/lleventinfo.cpp +++ b/indra/newview/lleventinfo.cpp @@ -87,35 +87,19 @@ void LLEventInfo::unpack(LLMessageSystem *msg) } // static -void LLEventInfo::loadCategories(LLUserAuth::options_t event_options) +void LLEventInfo::loadCategories(const LLSD& options) { - LLUserAuth::options_t::iterator resp_it; - for (resp_it = event_options.begin(); - resp_it != event_options.end(); - ++resp_it) + for(LLSD::array_const_iterator resp_it = options.beginArray(), + end = options.endArray(); resp_it != end; ++resp_it) { - const LLUserAuth::response_t& response = *resp_it; - - LLUserAuth::response_t::const_iterator option_it; - - S32 cat_id = 0; - option_it = response.find("category_id"); - if (option_it != response.end()) + LLSD name = (*resp_it)["category_name"]; + if(name.isDefined()) { - cat_id = atoi(option_it->second.c_str()); + LLSD id = (*resp_it)["category_id"]; + if(id.isDefined()) + { + LLEventInfo::sCategories[id.asInteger()] = name.asString(); + } } - else - { - continue; - } - - // Add the category id/name pair - option_it = response.find("category_name"); - if (option_it != response.end()) - { - LLEventInfo::sCategories[cat_id] = option_it->second; - } - } - } diff --git a/indra/newview/lleventinfo.h b/indra/newview/lleventinfo.h index 880517a9f4..493c659983 100644 --- a/indra/newview/lleventinfo.h +++ b/indra/newview/lleventinfo.h @@ -37,7 +37,6 @@ #include "v3dmath.h" #include "lluuid.h" -#include "lluserauth.h" class LLMessageSystem; @@ -48,7 +47,7 @@ public: void unpack(LLMessageSystem *msg); - static void loadCategories(LLUserAuth::options_t event_options); + static void loadCategories(const LLSD& options); public: std::string mName; diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 867fb0255a..da20766e7e 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -94,18 +94,16 @@ void LLEventNotifier::update() } } -void LLEventNotifier::load(const LLUserAuth::options_t& event_options) +void LLEventNotifier::load(const LLSD& event_options) { - LLUserAuth::options_t::const_iterator resp_it; - for (resp_it = event_options.begin(); - resp_it != event_options.end(); - ++resp_it) + for(LLSD::array_const_iterator resp_it = event_options.beginArray(), + end = event_options.endArray(); resp_it != end; ++resp_it) { - const LLUserAuth::response_t& response = *resp_it; + LLSD response = *resp_it; LLEventNotification *new_enp = new LLEventNotification(); - if (!new_enp->load(response)) + if(!new_enp->load(response)) { delete new_enp; continue; @@ -208,49 +206,46 @@ bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& r return false; } -BOOL LLEventNotification::load(const LLUserAuth::response_t &response) +BOOL LLEventNotification::load(const LLSD& response) { - - LLUserAuth::response_t::const_iterator option_it; BOOL event_ok = TRUE; - option_it = response.find("event_id"); - if (option_it != response.end()) + LLSD option = response.get("event_id"); + if (option.isDefined()) { - mEventID = atoi(option_it->second.c_str()); + mEventID = option.asInteger(); } else { event_ok = FALSE; } - option_it = response.find("event_name"); - if (option_it != response.end()) + option = response.get("event_name"); + if (option.isDefined()) { - llinfos << "Event: " << option_it->second << llendl; - mEventName = option_it->second; + llinfos << "Event: " << option.asString() << llendl; + mEventName = option.asString(); } else { event_ok = FALSE; } - - option_it = response.find("event_date"); - if (option_it != response.end()) + option = response.get("event_date"); + if (option.isDefined()) { - llinfos << "EventDate: " << option_it->second << llendl; - mEventDateStr = option_it->second; + llinfos << "EventDate: " << option.asString() << llendl; + mEventDateStr = option.asString(); } else { event_ok = FALSE; } - option_it = response.find("event_date_ut"); - if (option_it != response.end()) + option = response.get("event_date_ut"); + if (option.isDefined()) { - llinfos << "EventDate: " << option_it->second << llendl; - mEventDate = strtoul(option_it->second.c_str(), NULL, 10); + llinfos << "EventDate: " << option.asString() << llendl; + mEventDate = strtoul(option.asString().c_str(), NULL, 10); } else { @@ -262,44 +257,44 @@ BOOL LLEventNotification::load(const LLUserAuth::response_t &response) S32 x_region = 0; S32 y_region = 0; - option_it = response.find("grid_x"); - if (option_it != response.end()) + option = response.get("grid_x"); + if (option.isDefined()) { - llinfos << "GridX: " << option_it->second << llendl; - grid_x= atoi(option_it->second.c_str()); + llinfos << "GridX: " << option.asInteger() << llendl; + grid_x= option.asInteger(); } else { event_ok = FALSE; } - option_it = response.find("grid_y"); - if (option_it != response.end()) + option = response.get("grid_y"); + if (option.isDefined()) { - llinfos << "GridY: " << option_it->second << llendl; - grid_y = atoi(option_it->second.c_str()); + llinfos << "GridY: " << option.asInteger() << llendl; + grid_y = option.asInteger(); } else { event_ok = FALSE; } - option_it = response.find("x_region"); - if (option_it != response.end()) + option = response.get("x_region"); + if (option.isDefined()) { - llinfos << "RegionX: " << option_it->second << llendl; - x_region = atoi(option_it->second.c_str()); + llinfos << "RegionX: " << option.asInteger() << llendl; + x_region = option.asInteger(); } else { event_ok = FALSE; } - option_it = response.find("y_region"); - if (option_it != response.end()) + option = response.get("y_region"); + if (option.isDefined()) { - llinfos << "RegionY: " << option_it->second << llendl; - y_region = atoi(option_it->second.c_str()); + llinfos << "RegionY: " << option.asInteger() << llendl; + y_region = option.asInteger(); } else { diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h index feb734948c..6fdde87646 100644 --- a/indra/newview/lleventnotifier.h +++ b/indra/newview/lleventnotifier.h @@ -34,7 +34,6 @@ #define LL_LLEVENTNOTIFIER_H #include "llframetimer.h" -#include "lluserauth.h" #include "v3dmath.h" class LLEventInfo; @@ -49,7 +48,7 @@ public: void update(); // Notify the user of the event if it's coming up - void load(const LLUserAuth::options_t& event_options); // In the format that it comes in from LLUserAuth + void load(const LLSD& event_options); // In the format that it comes in from login void add(LLEventInfo &event_info); // Add a new notification for an event void remove(U32 event_id); @@ -69,7 +68,7 @@ public: LLEventNotification(); virtual ~LLEventNotification(); - BOOL load(const LLUserAuth::response_t &en); // In the format it comes in from LLUserAuth + BOOL load(const LLSD& en); // In the format it comes in from login BOOL load(const LLEventInfo &event_info); // From existing event_info on the viewer. //void setEventID(const U32 event_id); //void setEventName(std::string &event_name); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index f44cdc1a98..2ab17d6220 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -996,8 +996,12 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is) std::string label = iter->first; F64 time = iter->second["Time"].asReal(); - - total_time += time; + + // Skip the total figure + if(label.compare("Total") != 0) + { + total_time += time; + } if (time > 0.0) { diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 2a8365b3f0..fb724f30e0 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -44,6 +44,7 @@ #include "llgl.h" #include "llsecondlifeurls.h" +#include "llappviewer.h" #include "llviewercontrol.h" #include "llworld.h" #include "lldrawpoolterrain.h" @@ -58,11 +59,6 @@ #include "lldxhardware.h" #endif -// -// externs -// -extern LLMemoryInfo gSysMemory; -extern LLCPUInfo gSysCPU; #if LL_DARWIN const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt"; diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index a4c38d03aa..92ad28a105 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -1,293 +1,292 @@ -/** - * @file llfloaterabout.cpp - * @author James Cook - * @brief The about box from Help->About - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterabout.h" - -// Viewer includes -#include "llagent.h" -#include "llappviewer.h" -#include "llsecondlifeurls.h" -#include "lluictrlfactory.h" -#include "llviewertexteditor.h" -#include "llviewercontrol.h" -#include "llviewerstats.h" -#include "llviewerregion.h" -#include "llversionviewer.h" -#include "llviewerbuild.h" -#include "llweb.h" - -// Linden library includes -#include "llaudioengine.h" -#include "llbutton.h" -#include "llcurl.h" -#include "llglheaders.h" -#include "llfloater.h" -#include "llfloaterreg.h" -#include "llimagej2c.h" -#include "llsys.h" -#include "lltrans.h" -#include "lluri.h" -#include "v3dmath.h" -#include "llwindow.h" - -#if LL_WINDOWS -#include "lldxhardware.h" -#endif - -extern LLCPUInfo gSysCPU; -extern LLMemoryInfo gSysMemory; -extern U32 gPacketsIn; - -static std::string get_viewer_release_notes_url(); - - -///---------------------------------------------------------------------------- -/// Class LLFloaterAbout -///---------------------------------------------------------------------------- -class LLFloaterAbout - : public LLFloater -{ - friend class LLFloaterReg; -private: - LLFloaterAbout(const LLSD& key); - virtual ~LLFloaterAbout(); - -public: - /*virtual*/ BOOL postBuild(); - void onClickCopyToClipboard(); -}; - - -// Default constructor -LLFloaterAbout::LLFloaterAbout(const LLSD& key) -: LLFloater(key) -{ - //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml"); - -} - -// Destroys the object -LLFloaterAbout::~LLFloaterAbout() -{ -} - -BOOL LLFloaterAbout::postBuild() -{ - center(); - LLViewerTextEditor *support_widget = - getChild<LLViewerTextEditor>("support_editor", true); - - LLViewerTextEditor *credits_widget = - getChild<LLViewerTextEditor>("credits_editor", true); - - getChild<LLUICtrl>("copy_btn")->setCommitCallback( - boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this)); - - // Version string - std::string version = LLTrans::getString("APP_NAME") - + llformat(" %d.%d.%d (%d) %s %s (%s)\n", - LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD, - __DATE__, __TIME__, - gSavedSettings.getString("VersionChannelName").c_str()); - - std::string support; - support.append(version); - support.append("[" + get_viewer_release_notes_url() + " " + - LLTrans::getString("ReleaseNotes") + "]"); - support.append("\n\n"); - -#if LL_MSVC - support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER)); -#endif - -#if LL_GNUC - support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION)); -#endif - - // Position - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - const LLVector3d &pos = gAgent.getPositionGlobal(); - LLUIString pos_text = getString("you_are_at"); - pos_text.setArg("[POSITION]", - llformat("%.1f, %.1f, %.1f ", pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ])); - support.append(pos_text); - - LLUIString region_text = getString ("in_region") + " "; - region_text.setArg("[REGION]", llformat ("%s", gAgent.getRegion()->getName().c_str())); - support.append(region_text); - - std::string buffer; - buffer = gAgent.getRegion()->getHost().getHostName(); - support.append(buffer); - support.append(" ("); - buffer = gAgent.getRegion()->getHost().getString(); - support.append(buffer); - support.append(")\n"); - support.append(gLastVersionChannel); - support.append("\n"); - support.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) + - " " + LLTrans::getString("ReleaseNotes") + "]"); - support.append("\n\n"); - } - - // *NOTE: Do not translate text like GPU, Graphics Card, etc - - // Most PC users that know what these mean will be used to the english versions, - // and this info sometimes gets sent to support - - // CPU - support.append(getString("CPU") + " "); - support.append( gSysCPU.getCPUString() ); - support.append("\n"); - - U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024; - // Moved hack adjustment to Windows memory size into llsys.cpp - - LLStringUtil::format_map_t args; - args["[MEM]"] = llformat ("%u", memory); - support.append(getString("Memory", args) + "\n"); - - support.append(getString("OSVersion") + " "); - support.append( LLAppViewer::instance()->getOSInfo().getOSString() ); - support.append("\n"); - - support.append(getString("GraphicsCardVendor") + " "); - support.append( (const char*) glGetString(GL_VENDOR) ); - support.append("\n"); - - support.append(getString("GraphicsCard") + " "); - support.append( (const char*) glGetString(GL_RENDERER) ); - support.append("\n"); - -#if LL_WINDOWS - getWindow()->incBusyCount(); - getWindow()->setCursor(UI_CURSOR_ARROW); - support.append("Windows Graphics Driver Version: "); - LLSD driver_info = gDXHardware.getDisplayInfo(); - if (driver_info.has("DriverVersion")) - { - support.append(driver_info["DriverVersion"]); - } - support.append("\n"); - getWindow()->decBusyCount(); - getWindow()->setCursor(UI_CURSOR_ARROW); -#endif - - support.append(getString("OpenGLVersion") + " "); - support.append( (const char*) glGetString(GL_VERSION) ); - support.append("\n"); - - support.append("\n"); - - support.append(getString("LibCurlVersion") + " "); - support.append( LLCurl::getVersionString() ); - support.append("\n"); - - support.append(getString("J2CDecoderVersion") + " "); - support.append( LLImageJ2C::getEngineInfo() ); - support.append("\n"); - - support.append(getString("AudioDriverVersion") + " "); - bool want_fullname = true; - support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : getString("none") ); - support.append("\n"); - - // TODO: Implement media plugin version query - - support.append(getString("LLQtWebkitVersion") + " "); - support.append("\n"); - - if (gPacketsIn > 0) - { - args["[LOST]"] = llformat ("%.0f", LLViewerStats::getInstance()->mPacketsLostStat.getCurrent()); - args["[IN]"] = llformat ("%.0f", F32(gPacketsIn)); - args["[PCT]"] = llformat ("%.1f", 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) ); - support.append(getString ("PacketsLost", args) + "\n"); - } - - support_widget->appendText(support, - FALSE, - LLStyle::Params() - .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor"))); - support_widget->blockUndo(); - - // Fix views - support_widget->setCursorPos(0); - support_widget->setEnabled(FALSE); - - credits_widget->setCursorPos(0); - credits_widget->setEnabled(FALSE); - - return TRUE; -} - - -static std::string get_viewer_release_notes_url() -{ - std::ostringstream version; - version << LL_VERSION_MAJOR << "." - << LL_VERSION_MINOR << "." - << LL_VERSION_PATCH << "." - << LL_VERSION_BUILD; - - LLSD query; - query["channel"] = gSavedSettings.getString("VersionChannelName"); - query["version"] = version.str(); - - std::ostringstream url; - url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query); - - return LLWeb::escapeURL(url.str()); -} - -void LLFloaterAbout::onClickCopyToClipboard() -{ - LLViewerTextEditor *support_widget = - getChild<LLViewerTextEditor>("support_editor", true); - support_widget->selectAll(); - support_widget->copy(); - support_widget->deselect(); -} - -///---------------------------------------------------------------------------- -/// LLFloaterAboutUtil -///---------------------------------------------------------------------------- -void LLFloaterAboutUtil::registerFloater() -{ - LLFloaterReg::add("sl_about", "floater_about.xml", - &LLFloaterReg::build<LLFloaterAbout>); - -} +/**
+ * @file llfloaterabout.cpp
+ * @author James Cook
+ * @brief The about box from Help->About
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterabout.h"
+
+// Viewer includes
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llsecondlifeurls.h"
+#include "lluictrlfactory.h"
+#include "llviewertexteditor.h"
+#include "llviewercontrol.h"
+#include "llviewerstats.h"
+#include "llviewerregion.h"
+#include "llversionviewer.h"
+#include "llviewerbuild.h"
+#include "llweb.h"
+
+// Linden library includes
+#include "llaudioengine.h"
+#include "llbutton.h"
+#include "llcurl.h"
+#include "llglheaders.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llimagej2c.h"
+#include "llsys.h"
+#include "lltrans.h"
+#include "lluri.h"
+#include "v3dmath.h"
+#include "llwindow.h"
+
+#if LL_WINDOWS
+#include "lldxhardware.h"
+#endif
+
+extern LLMemoryInfo gSysMemory;
+extern U32 gPacketsIn;
+
+static std::string get_viewer_release_notes_url();
+
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterAbout
+///----------------------------------------------------------------------------
+class LLFloaterAbout
+ : public LLFloater
+{
+ friend class LLFloaterReg;
+private:
+ LLFloaterAbout(const LLSD& key);
+ virtual ~LLFloaterAbout();
+
+public:
+ /*virtual*/ BOOL postBuild();
+ void onClickCopyToClipboard();
+};
+
+
+// Default constructor
+LLFloaterAbout::LLFloaterAbout(const LLSD& key)
+: LLFloater(key)
+{
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
+
+}
+
+// Destroys the object
+LLFloaterAbout::~LLFloaterAbout()
+{
+}
+
+BOOL LLFloaterAbout::postBuild()
+{
+ center();
+ LLViewerTextEditor *support_widget =
+ getChild<LLViewerTextEditor>("support_editor", true);
+
+ LLViewerTextEditor *credits_widget =
+ getChild<LLViewerTextEditor>("credits_editor", true);
+
+ getChild<LLUICtrl>("copy_btn")->setCommitCallback(
+ boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
+
+ // Version string
+ std::string version = LLTrans::getString("APP_NAME")
+ + llformat(" %d.%d.%d (%d) %s %s (%s)\n",
+ LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD,
+ __DATE__, __TIME__,
+ gSavedSettings.getString("VersionChannelName").c_str());
+
+ std::string support;
+ support.append(version);
+ support.append("[" + get_viewer_release_notes_url() + " " +
+ LLTrans::getString("ReleaseNotes") + "]");
+ support.append("\n\n");
+
+#if LL_MSVC
+ support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER));
+#endif
+
+#if LL_GNUC
+ support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION));
+#endif
+
+ // Position
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ const LLVector3d &pos = gAgent.getPositionGlobal();
+ LLUIString pos_text = getString("you_are_at");
+ pos_text.setArg("[POSITION]",
+ llformat("%.1f, %.1f, %.1f ", pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ]));
+ support.append(pos_text);
+
+ LLUIString region_text = getString ("in_region") + " ";
+ region_text.setArg("[REGION]", llformat ("%s", gAgent.getRegion()->getName().c_str()));
+ support.append(region_text);
+
+ std::string buffer;
+ buffer = gAgent.getRegion()->getHost().getHostName();
+ support.append(buffer);
+ support.append(" (");
+ buffer = gAgent.getRegion()->getHost().getString();
+ support.append(buffer);
+ support.append(")\n");
+ support.append(gLastVersionChannel);
+ support.append("\n");
+ support.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) +
+ " " + LLTrans::getString("ReleaseNotes") + "]");
+ support.append("\n\n");
+ }
+
+ // *NOTE: Do not translate text like GPU, Graphics Card, etc -
+ // Most PC users that know what these mean will be used to the english versions,
+ // and this info sometimes gets sent to support
+
+ // CPU
+ support.append(getString("CPU") + " ");
+ support.append( gSysCPU.getCPUString() );
+ support.append("\n");
+
+ U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
+ // Moved hack adjustment to Windows memory size into llsys.cpp
+
+ LLStringUtil::format_map_t args;
+ args["[MEM]"] = llformat ("%u", memory);
+ support.append(getString("Memory", args) + "\n");
+
+ support.append(getString("OSVersion") + " ");
+ support.append( LLAppViewer::instance()->getOSInfo().getOSString() );
+ support.append("\n");
+
+ support.append(getString("GraphicsCardVendor") + " ");
+ support.append( (const char*) glGetString(GL_VENDOR) );
+ support.append("\n");
+
+ support.append(getString("GraphicsCard") + " ");
+ support.append( (const char*) glGetString(GL_RENDERER) );
+ support.append("\n");
+
+#if LL_WINDOWS
+ getWindow()->incBusyCount();
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ support.append("Windows Graphics Driver Version: ");
+ LLSD driver_info = gDXHardware.getDisplayInfo();
+ if (driver_info.has("DriverVersion"))
+ {
+ support.append(driver_info["DriverVersion"]);
+ }
+ support.append("\n");
+ getWindow()->decBusyCount();
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+
+ support.append(getString("OpenGLVersion") + " ");
+ support.append( (const char*) glGetString(GL_VERSION) );
+ support.append("\n");
+
+ support.append("\n");
+
+ support.append(getString("LibCurlVersion") + " ");
+ support.append( LLCurl::getVersionString() );
+ support.append("\n");
+
+ support.append(getString("J2CDecoderVersion") + " ");
+ support.append( LLImageJ2C::getEngineInfo() );
+ support.append("\n");
+
+ support.append(getString("AudioDriverVersion") + " ");
+ bool want_fullname = true;
+ support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : getString("none") );
+ support.append("\n");
+
+ // TODO: Implement media plugin version query
+
+ support.append(getString("LLQtWebkitVersion") + " ");
+ support.append("\n");
+
+ if (gPacketsIn > 0)
+ {
+ args["[LOST]"] = llformat ("%.0f", LLViewerStats::getInstance()->mPacketsLostStat.getCurrent());
+ args["[IN]"] = llformat ("%.0f", F32(gPacketsIn));
+ args["[PCT]"] = llformat ("%.1f", 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) );
+ support.append(getString ("PacketsLost", args) + "\n");
+ }
+
+ support_widget->appendText(support,
+ FALSE,
+ LLStyle::Params()
+ .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+ support_widget->blockUndo();
+
+ // Fix views
+ support_widget->setCursorPos(0);
+ support_widget->setEnabled(FALSE);
+
+ credits_widget->setCursorPos(0);
+ credits_widget->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+
+static std::string get_viewer_release_notes_url()
+{
+ std::ostringstream version;
+ version << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH << "."
+ << LL_VERSION_BUILD;
+
+ LLSD query;
+ query["channel"] = gSavedSettings.getString("VersionChannelName");
+ query["version"] = version.str();
+
+ std::ostringstream url;
+ url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
+
+ return LLWeb::escapeURL(url.str());
+}
+
+void LLFloaterAbout::onClickCopyToClipboard()
+{
+ LLViewerTextEditor *support_widget =
+ getChild<LLViewerTextEditor>("support_editor", true);
+ support_widget->selectAll();
+ support_widget->copy();
+ support_widget->deselect();
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterAboutUtil
+///----------------------------------------------------------------------------
+void LLFloaterAboutUtil::registerFloater()
+{
+ LLFloaterReg::add("sl_about", "floater_about.xml",
+ &LLFloaterReg::build<LLFloaterAbout>);
+
+}
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index cb0d304aa0..262dc1804d 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -58,6 +58,7 @@ #include "llui.h" #include "llrender.h" #include "llsdutil.h" +#include "llsdutil_math.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 2c2a5107f5..36f0315790 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -81,6 +81,8 @@ public: LLFloaterBuyLandUI(const LLSD& key); virtual ~LLFloaterBuyLandUI(); + /*virtual*/ void onClose(bool app_quitting); + private: class SelectionObserver : public LLParcelObserver { @@ -300,11 +302,21 @@ LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key) LLFloaterBuyLandUI::~LLFloaterBuyLandUI() { LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver); - LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo); + LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo); delete mTransaction; } +// virtual +void LLFloaterBuyLandUI::onClose(bool app_quitting) +{ + // This object holds onto observer, transactions, and parcel state. + // Despite being single_instance, destroy it to call destructors and clean + // everything up. + setVisible(FALSE); + destroy(); +} + void LLFloaterBuyLandUI::SelectionObserver::changed() { if (LLViewerParcelMgr::getInstance()->selectionEmpty()) @@ -756,7 +768,7 @@ void LLFloaterBuyLandUI::sendBuyLand() if (mParcelBuyInfo) { LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo); - LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo); + LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo); mBought = true; } } diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index 9242f00c91..9c6660c0dc 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -74,6 +74,9 @@ public: virtual BOOL postBuild(); + // *HACK Made public to remove friends from LLAvatarIconCtrl context menu + static bool handleRemove(const LLSD& notification, const LLSD& response); + private: enum FRIENDS_COLUMN_ORDER diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 488d71aa70..bdf9842b01 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1054,9 +1054,9 @@ BOOL LLPanelLandObjects::postBuild() mBtnReturnOwnerList = getChild<LLButton>("Return objects..."); mBtnReturnOwnerList->setClickedCallback(onClickReturnOwnerList, this); - mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga"); - mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga"); - mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga"); + mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga", 0); + mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga", 0); + mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga", 0); mOwnerList = getChild<LLNameListCtrl>("owner list"); mOwnerList->sortByColumnIndex(3, FALSE); diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index aa457de2d8..d941f24f49 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -118,6 +118,7 @@ BOOL LLFloaterMediaSettings::postBuild() mTabContainer->addTabPanel( LLTabContainer::TabPanelParams(). panel(mPanelMediaSettingsSecurity)); + mPanelMediaSettingsSecurity->setParent( this ); // restore the last tab viewed from persistance variable storage if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab"))) @@ -248,3 +249,28 @@ void LLFloaterMediaSettings::enableOkApplyBtns( bool enable ) childSetEnabled( "OK", enable ); childSetEnabled( "Apply", enable ); } + +//////////////////////////////////////////////////////////////////////////////// +// +const std::string LLFloaterMediaSettings::getHomeUrl() +{ + if ( mPanelMediaSettingsGeneral ) + return mPanelMediaSettingsGeneral->getHomeUrl(); + else + return std::string( "" ); +} + + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLFloaterMediaSettings::passesWhiteList( const std::string& test_url ) +{ + // sanity check - don't think this can happen + if ( mPanelMediaSettingsSecurity ) + // version in security dialog code is specialized so we pass in + // empty string for first parameter since it's not used + return mPanelMediaSettingsSecurity->passesWhiteList( "", test_url ); + else + // this is all we can do + return false; +} diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h index e2683039cc..17a47cb0f5 100644 --- a/indra/newview/llfloatermediasettings.h +++ b/indra/newview/llfloatermediasettings.h @@ -56,6 +56,8 @@ public: static void clearValues( bool editable); void enableOkApplyBtns( bool enable ); LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;}; + const std::string getHomeUrl(); + bool passesWhiteList( const std::string& test_url ); bool mIdenticalHasMediaInfo; bool mMultipleMedia; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index e15fdd3e35..11544f5b7b 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -442,52 +442,43 @@ LLPanelRegionInfo::LLPanelRegionInfo() { } -// static -void LLPanelRegionInfo::onBtnSet(void* user_data) +void LLPanelRegionInfo::onBtnSet() { - LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data; - if(!panel) return; - if (panel->sendUpdate()) + if (sendUpdate()) { - panel->disableButton("apply_btn"); + disableButton("apply_btn"); } } -//static -void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl, void* user_data) +void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl) { - if (ctrl) - { - LLPanelRegionInfo* panel = (LLPanelRegionInfo*) ctrl->getParent(); - panel->updateChild(ctrl); - } + updateChild(ctrl); // virtual function } -// static // Enables the "set" button if it is not already enabled -void LLPanelRegionInfo::onChangeAnything(LLUICtrl* ctrl, void* user_data) +void LLPanelRegionInfo::onChangeAnything() { - LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data; - if(panel) - { - panel->enableButton("apply_btn"); - panel->refresh(); - } + enableButton("apply_btn"); + refresh(); } // static // Enables set button on change to line editor void LLPanelRegionInfo::onChangeText(LLLineEditor* caller, void* user_data) { - // reuse the previous method - onChangeAnything(0, user_data); + LLPanelRegionInfo* panel = dynamic_cast<LLPanelRegionInfo*>(caller->getParent()); + if(panel) + { + panel->enableButton("apply_btn"); + panel->refresh(); + } } // virtual BOOL LLPanelRegionInfo::postBuild() { - childSetAction("apply_btn", onBtnSet, this); + getChild<LLUICtrl>("apply_btn")->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this)); childDisable("apply_btn"); refresh(); return TRUE; @@ -550,19 +541,17 @@ void LLPanelRegionInfo::disableButton(const std::string& btn_name) void LLPanelRegionInfo::initCtrl(const std::string& name) { - childSetCommitCallback(name, onChangeAnything, this); + getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this)); } void LLPanelRegionInfo::initHelpBtn(const std::string& name, const std::string& xml_alert) { - childSetAction(name, onClickHelp, new std::string(xml_alert)); + getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onClickHelp, this, xml_alert)); } -// static -void LLPanelRegionInfo::onClickHelp(void* data) +void LLPanelRegionInfo::onClickHelp(std::string xml_alert) { - std::string* xml_alert = (std::string*)data; - LLNotifications::instance().add(*xml_alert); + LLNotifications::instance().add(xml_alert); } ///////////////////////////////////////////////////////////////////////////// @@ -1207,9 +1196,9 @@ BOOL LLPanelRegionTerrainInfo::postBuild() initCtrl("terrain_lower_spin"); initCtrl("fixed_sun_check"); - childSetCommitCallback("fixed_sun_check", onChangeFixedSun, this); - childSetCommitCallback("use_estate_sun_check", onChangeUseEstateTime, this); - childSetCommitCallback("sun_hour_slider", onChangeSunHour, this); + getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeFixedSun, this)); + getChild<LLUICtrl>("use_estate_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeUseEstateTime, this)); + getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeSunHour, this)); childSetAction("download_raw_btn", onClickDownloadRaw, this); childSetAction("upload_raw_btn", onClickUploadRaw, this); @@ -1292,39 +1281,29 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() return TRUE; } -// static -void LLPanelRegionTerrainInfo::onChangeUseEstateTime(LLUICtrl* ctrl, void* user_data) +void LLPanelRegionTerrainInfo::onChangeUseEstateTime() { - LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) user_data; - if (!panel) return; - BOOL use_estate_sun = panel->childGetValue("use_estate_sun_check").asBoolean(); - panel->childSetEnabled("fixed_sun_check", !use_estate_sun); - panel->childSetEnabled("sun_hour_slider", !use_estate_sun); + BOOL use_estate_sun = childGetValue("use_estate_sun_check").asBoolean(); + childSetEnabled("fixed_sun_check", !use_estate_sun); + childSetEnabled("sun_hour_slider", !use_estate_sun); if (use_estate_sun) { - panel->childSetValue("fixed_sun_check", LLSD(FALSE)); - panel->childSetValue("sun_hour_slider", LLSD(0.f)); + childSetValue("fixed_sun_check", LLSD(FALSE)); + childSetValue("sun_hour_slider", LLSD(0.f)); } - panel->childEnable("apply_btn"); + childEnable("apply_btn"); } -// static -void LLPanelRegionTerrainInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data) +void LLPanelRegionTerrainInfo::onChangeFixedSun() { - LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) user_data; - if (!panel) return; // Just enable the apply button. We let the sun-hour slider be enabled // for both fixed-sun and non-fixed-sun. JC - panel->childEnable("apply_btn"); + childEnable("apply_btn"); } -// static -void LLPanelRegionTerrainInfo::onChangeSunHour(LLUICtrl* ctrl, void*) +void LLPanelRegionTerrainInfo::onChangeSunHour() { - // can't use userdata to get panel, slider uses it internally - LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) ctrl->getParent(); - if (!panel) return; - panel->childEnable("apply_btn"); + childEnable("apply_btn"); } // static @@ -1420,32 +1399,23 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch) estate_dispatch_initialized = true; } -// static // Disables the sun-hour slider and the use fixed time check if the use global time is check -void LLPanelEstateInfo::onChangeUseGlobalTime(LLUICtrl* ctrl, void* user_data) +void LLPanelEstateInfo::onChangeUseGlobalTime() { - LLPanelEstateInfo* panel = (LLPanelEstateInfo*) user_data; - if (panel) - { - bool enabled = !panel->childGetValue("use_global_time_check").asBoolean(); - panel->childSetEnabled("sun_hour_slider", enabled); - panel->childSetEnabled("fixed_sun_check", enabled); - panel->childSetValue("fixed_sun_check", LLSD(FALSE)); - panel->enableButton("apply_btn"); - } + bool enabled = !childGetValue("use_global_time_check").asBoolean(); + childSetEnabled("sun_hour_slider", enabled); + childSetEnabled("fixed_sun_check", enabled); + childSetValue("fixed_sun_check", LLSD(FALSE)); + enableButton("apply_btn"); } // Enables the sun-hour slider if the fixed-sun checkbox is set -void LLPanelEstateInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data) +void LLPanelEstateInfo::onChangeFixedSun() { - LLPanelEstateInfo* panel = (LLPanelEstateInfo*) user_data; - if (panel) - { - bool enabled = !panel->childGetValue("fixed_sun_check").asBoolean(); - panel->childSetEnabled("use_global_time_check", enabled); - panel->childSetValue("use_global_time_check", LLSD(FALSE)); - panel->enableButton("apply_btn"); - } + bool enabled = !childGetValue("fixed_sun_check").asBoolean(); + childSetEnabled("use_global_time_check", enabled); + childSetValue("use_global_time_check", LLSD(FALSE)); + enableButton("apply_btn"); } @@ -2130,7 +2100,7 @@ BOOL LLPanelEstateInfo::postBuild() initCtrl("limit_payment"); initCtrl("limit_age_verified"); initCtrl("voice_chat_check"); - childSetCommitCallback("abuse_email_address", onChangeAnything, this); + getChild<LLUICtrl>("abuse_email_address")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAnything, this)); getChild<LLLineEditor>("abuse_email_address")->setKeystrokeCallback(onChangeText, this); initHelpBtn("estate_manager_help", "HelpEstateEstateManager"); @@ -2144,15 +2114,15 @@ BOOL LLPanelEstateInfo::postBuild() initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); initHelpBtn("allow_group_help", "HelpEstateAllowGroup"); initHelpBtn("ban_resident_help", "HelpEstateBanResident"); - initHelpBtn("abuse_email_address_help", "HelpEstateAbuseEmailAddress"); - initHelpBtn("voice_chat_help", "HelpEstateVoiceChat"); + initHelpBtn("abuse_email_address_help", "HelpEstateAbuseEmailAddress"); + initHelpBtn("voice_chat_help", "HelpEstateVoiceChat"); // set up the use global time checkbox - childSetCommitCallback("use_global_time_check", onChangeUseGlobalTime, this); - childSetCommitCallback("fixed_sun_check", onChangeFixedSun, this); - childSetCommitCallback("sun_hour_slider", onChangeChildCtrl, this); - - childSetCommitCallback("allowed_avatar_name_list", onChangeChildCtrl, this); + getChild<LLUICtrl>("use_global_time_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeUseGlobalTime, this)); + getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeFixedSun, this)); + getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + + getChild<LLUICtrl>("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); LLNameListCtrl *avatar_name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list"); if (avatar_name_list) { @@ -2163,7 +2133,7 @@ BOOL LLPanelEstateInfo::postBuild() childSetAction("add_allowed_avatar_btn", onClickAddAllowedAgent, this); childSetAction("remove_allowed_avatar_btn", onClickRemoveAllowedAgent, this); - childSetCommitCallback("allowed_group_name_list", onChangeChildCtrl, this); + getChild<LLUICtrl>("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); LLNameListCtrl* group_name_list = getChild<LLNameListCtrl>("allowed_group_name_list"); if (group_name_list) { @@ -2174,7 +2144,7 @@ BOOL LLPanelEstateInfo::postBuild() getChild<LLUICtrl>("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onClickAddAllowedGroup, this)); childSetAction("remove_allowed_group_btn", onClickRemoveAllowedGroup, this); - childSetCommitCallback("banned_avatar_name_list", onChangeChildCtrl, this); + getChild<LLUICtrl>("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); LLNameListCtrl* banned_name_list = getChild<LLNameListCtrl>("banned_avatar_name_list"); if (banned_name_list) { @@ -2185,7 +2155,7 @@ BOOL LLPanelEstateInfo::postBuild() childSetAction("add_banned_avatar_btn", onClickAddBannedAgent, this); childSetAction("remove_banned_avatar_btn", onClickRemoveBannedAgent, this); - childSetCommitCallback("estate_manager_name_list", onChangeChildCtrl, this); + getChild<LLUICtrl>("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); LLNameListCtrl* manager_name_list = getChild<LLNameListCtrl>("estate_manager_name_list"); if (manager_name_list) { @@ -2299,13 +2269,18 @@ void LLPanelEstateInfo::getEstateOwner() class LLEstateChangeInfoResponder : public LLHTTPClient::Responder { public: - LLEstateChangeInfoResponder(void* userdata) : mpPanel((LLPanelEstateInfo*)userdata) {}; + LLEstateChangeInfoResponder(LLPanelEstateInfo* panel) + { + mpPanel = panel->getHandle(); + } // if we get a normal response, handle it here virtual void result(const LLSD& content) { // refresh the panel from the database - mpPanel->refresh(); + LLPanelEstateInfo* panel = dynamic_cast<LLPanelEstateInfo*>(mpPanel.get()); + if (panel) + panel->refresh(); } // if we get an error response @@ -2315,7 +2290,7 @@ public: << status << ": " << reason << llendl; } private: - LLPanelEstateInfo* mpPanel; + LLHandle<LLPanel> mpPanel; }; // tries to send estate info using a cap; returns true if it succeeded @@ -2353,7 +2328,7 @@ bool LLPanelEstateInfo::commitEstateInfoCaps() body["owner_abuse_email"] = childGetValue("abuse_email_address").asString(); // we use a responder so that we can re-get the data after committing to the database - LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder((void*)this)); + LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder(this)); return true; } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 68ed4e0c89..95833af8a1 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -109,9 +109,9 @@ class LLPanelRegionInfo : public LLPanel public: LLPanelRegionInfo(); - static void onBtnSet(void* user_data); - static void onChangeChildCtrl(LLUICtrl* ctrl, void* user_data); - static void onChangeAnything(LLUICtrl* ctrl, void* user_data); + void onBtnSet(); + void onChangeChildCtrl(LLUICtrl* ctrl); + void onChangeAnything(); static void onChangeText(LLLineEditor* caller, void* user_data); virtual bool refreshFromRegion(LLViewerRegion* region); @@ -128,7 +128,7 @@ protected: void initHelpBtn(const std::string& name, const std::string& xml_alert); // Callback for all help buttons, data is name of XML alert to show. - static void onClickHelp(void* data); + void onClickHelp(std::string xml_alert); // Returns TRUE if update sent and apply button should be // disabled. @@ -239,9 +239,9 @@ public: protected: virtual BOOL sendUpdate(); - static void onChangeUseEstateTime(LLUICtrl* ctrl, void* user_data); - static void onChangeFixedSun(LLUICtrl* ctrl, void* user_data); - static void onChangeSunHour(LLUICtrl* ctrl, void*); + void onChangeUseEstateTime(); + void onChangeFixedSun(); + void onChangeSunHour(); static void onClickDownloadRaw(void*); static void onClickUploadRaw(void*); @@ -256,8 +256,8 @@ class LLPanelEstateInfo : public LLPanelRegionInfo public: static void initDispatch(LLDispatcher& dispatch); - static void onChangeFixedSun(LLUICtrl* ctrl, void* user_data); - static void onChangeUseGlobalTime(LLUICtrl* ctrl, void* user_data); + void onChangeFixedSun(); + void onChangeUseGlobalTime(); static void onClickEditSky(void* userdata); static void onClickEditSkyHelp(void* userdata); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index e00b352c9b..92980c22c7 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1038,12 +1038,13 @@ void LLFloaterTools::getMediaState() &&first_object->permModify() )) { - childSetEnabled("media_tex", FALSE); + childSetEnabled("Add_Media", FALSE); +/* childSetEnabled("media_tex", FALSE); childSetEnabled("add_media", FALSE); childSetEnabled("delete_media", FALSE); childSetEnabled("edit_media", FALSE); childSetEnabled("media_info", FALSE); - media_info->setEnabled(FALSE); + media_info->setEnabled(FALSE);*/ media_info->clear(); clearMediaSettings(); return; @@ -1054,13 +1055,14 @@ void LLFloaterTools::getMediaState() if(!has_media_capability) { - childSetEnabled("media_tex", FALSE); + childSetEnabled("Add_Media", FALSE); + /* childSetEnabled("media_tex", FALSE); childSetEnabled("add_media", FALSE); childSetEnabled("delete_media", FALSE); childSetEnabled("edit_media", FALSE); childSetEnabled("media_info", FALSE); media_info->setEnabled(FALSE); - media_info->clear(); + media_info->clear();*/ clearMediaSettings(); return; } @@ -1081,6 +1083,7 @@ void LLFloaterTools::getMediaState() LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, has_media ); bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA); + const LLMediaEntry default_media_data; struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry> @@ -1108,6 +1111,7 @@ void LLFloaterTools::getMediaState() // update UI depending on whether "object" (prim or face) has media // and whether or not you are allowed to edit it. + childSetEnabled("Add_Media", editable); // IF all the faces have media (or all dont have media) if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) { @@ -1120,7 +1124,7 @@ void LLFloaterTools::getMediaState() if(media_data_get!=default_media_data) { //TODO: get media title - //media_title = media_data_get->getTile(); + //media_title = media_data_get->getTitle(); //LLFloaterMediaSettings::getInstance()->mIdenticalValidMedia = true; media_title = media_data_get.getHomeURL(); } @@ -1155,7 +1159,7 @@ void LLFloaterTools::getMediaState() if(media_data_get!=default_media_data) { //TODO: get media title - //media_title = media_data_get->getTile(); + //media_title = media_data_get->getTitle(); media_title = media_data_get.getHomeURL(); } diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 1c3443ae80..8d2d48f1af 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -35,8 +35,6 @@ #include "llfloatertos.h" // viewer includes -#include "llappviewer.h" -#include "llstartup.h" #include "llviewerstats.h" #include "llviewerwindow.h" @@ -50,13 +48,15 @@ #include "lluictrlfactory.h" #include "llvfile.h" #include "message.h" +#include "llstartup.h" // login_alert_done -LLFloaterTOS::LLFloaterTOS(const LLSD& message) -: LLModalDialog( message ), - mMessage(message.asString()), +LLFloaterTOS::LLFloaterTOS(const LLSD& data) +: LLModalDialog( data["message"].asString() ), + mMessage(data["message"].asString()), mWebBrowserWindowId( 0 ), - mLoadCompleteCount( 0 ) + mLoadCompleteCount( 0 ), + mReplyPumpName(data["reply_pump"].asString()) { } @@ -193,25 +193,12 @@ void LLFloaterTOS::onContinue( void* userdata ) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User agrees with TOS." << llendl; - if (self->getInstanceName() == "message_tos") - { - gAcceptTOS = TRUE; - } - else - { - gAcceptCriticalMessage = TRUE; - } - // Testing TOS dialog - #if ! LL_RELEASE_FOR_DOWNLOAD - if ( LLStartUp::getStartupState() == STATE_LOGIN_WAIT ) + if(self->mReplyPumpName != "") { - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true)); } - else - #endif - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); // Go back and finish authentication self->closeFloater(); // destroys this object } @@ -221,7 +208,12 @@ void LLFloaterTOS::onCancel( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User disagrees with TOS." << llendl; LLNotifications::instance().add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done); - LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + + if(self->mReplyPumpName != "") + { + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false)); + } + self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS self->closeFloater(); // destroys this object } @@ -241,3 +233,4 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev } } } + diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 49f982aa80..1d573e8170 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -36,6 +36,7 @@ #include "llmodaldialog.h" #include "llassetstorage.h" #include "llmediactrl.h" +#include <boost/function.hpp> class LLButton; class LLRadioGroup; @@ -48,7 +49,7 @@ class LLFloaterTOS : public LLViewerMediaObserver { public: - LLFloaterTOS(const LLSD& message); + LLFloaterTOS(const LLSD& data); virtual ~LLFloaterTOS(); BOOL postBuild(); @@ -68,6 +69,7 @@ private: std::string mMessage; int mWebBrowserWindowId; int mLoadCompleteCount; + std::string mReplyPumpName; }; #endif // LL_LLFLOATERTOS_H diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 3591daf92d..f83a426cda 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -71,6 +71,10 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) { LLFontDescriptor labelfontdesc("SansSerif", "Small", style); rtn = LLFontGL::getFont(labelfontdesc); + if (!rtn) + { + rtn = LLFontGL::getFontDefault(); + } sFonts[style] = rtn; } return rtn; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ab6f50aaf3..b631c991ae 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -40,7 +40,7 @@ #include "llerror.h" #include "llbutton.h" #include "llhttpclient.h" -#include "llsdutil.h" +#include "llsdutil_math.h" #include "llstring.h" #include "lluictrlfactory.h" diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h index 68accca3a3..a461c2fa16 100644 --- a/indra/newview/llinspect.h +++ b/indra/newview/llinspect.h @@ -58,3 +58,4 @@ private: }; #endif + diff --git a/indra/newview/llinventoryactions.h b/indra/newview/llinventoryactions.h new file mode 100644 index 0000000000..79247e3abb --- /dev/null +++ b/indra/newview/llinventoryactions.h @@ -0,0 +1,47 @@ +/** + * @file llinventoryactions.h + * @brief inventory callback functions + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYACTIONS_H +#define LL_LLINVENTORYACTIONS_H + +#include "lluictrl.h" + +class LLPanelInventory; +class LLInventoryView; +class LLInventoryPanel; + +void init_object_inventory_panel_actions(LLPanelInventory *panel, LLUICtrl::CommitCallbackRegistry::Registrar& registrar); +void init_inventory_actions(LLInventoryView *floater, LLUICtrl::CommitCallbackRegistry::Registrar& registrar); +void init_inventory_panel_actions(LLInventoryPanel *panel, LLUICtrl::CommitCallbackRegistry::Registrar& registrar); + +#endif // LL_LLINVENTORYACTIONS_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ca9ebf8dc1..3aa35d98f8 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3878,7 +3878,10 @@ std::string LLObjectBridge::getLabelSuffix() const { std::string attachment_point_name = avatar->getAttachedPointName(mUUID); LLStringUtil::toLower(attachment_point_name); - return LLItemBridge::getLabelSuffix() + std::string(" (worn on ") + attachment_point_name + std::string(")"); + + LLStringUtil::format_map_t args; + args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str(); + return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); } else { @@ -4294,7 +4297,7 @@ std::string LLWearableBridge::getLabelSuffix() const { if( gAgentWearables.isWearingItem( mUUID ) ) { - return LLItemBridge::getLabelSuffix() + " (worn)"; + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); } else { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6009e8e610..d5a527773c 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2010,63 +2010,56 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const } bool LLInventoryModel::loadSkeleton( - const LLInventoryModel::options_t& options, + const LLSD& options, const LLUUID& owner_id) { lldebugs << "importing inventory skeleton for " << owner_id << llendl; typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t; cat_set_t temp_cats; - - update_map_t child_counts; - - LLUUID id; - LLAssetType::EType preferred_type; bool rv = true; - for(options_t::const_iterator it = options.begin(); it < options.end(); ++it) - { - LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id); - response_t::const_iterator no_response = (*it).end(); - response_t::const_iterator skel; - skel = (*it).find("name"); - if(skel == no_response) goto clean_cat; - cat->rename(std::string((*skel).second)); - skel = (*it).find("folder_id"); - if(skel == no_response) goto clean_cat; - id.set((*skel).second); - // if an id is null, it locks the viewer. - if(id.isNull()) goto clean_cat; - cat->setUUID(id); - skel = (*it).find("parent_id"); - if(skel == no_response) goto clean_cat; - id.set((*skel).second); - cat->setParent(id); - skel = (*it).find("type_default"); - if(skel == no_response) - { - preferred_type = LLAssetType::AT_NONE; + + for(LLSD::array_const_iterator it = options.beginArray(), + end = options.endArray(); it != end; ++it) + { + LLSD name = (*it)["name"]; + LLSD folder_id = (*it)["folder_id"]; + LLSD parent_id = (*it)["parent_id"]; + LLSD version = (*it)["version"]; + if(name.isDefined() + && folder_id.isDefined() + && parent_id.isDefined() + && version.isDefined() + && folder_id.asUUID().notNull() // if an id is null, it locks the viewer. + ) + { + LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id); + cat->rename(name.asString()); + cat->setUUID(folder_id.asUUID()); + cat->setParent(parent_id.asUUID()); + + LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLSD type_default = (*it)["type_default"]; + if(type_default.isDefined()) + { + preferred_type = (LLAssetType::EType)type_default.asInteger(); + } + cat->setPreferredType(preferred_type); + cat->setVersion(version.asInteger()); + temp_cats.insert(cat); } else { - S32 t = atoi((*skel).second.c_str()); - preferred_type = (LLAssetType::EType)t; + llwarns << "Unable to import near " << name.asString() << llendl; + rv = false; } - cat->setPreferredType(preferred_type); - skel = (*it).find("version"); - if(skel == no_response) goto clean_cat; - cat->setVersion(atoi((*skel).second.c_str())); - temp_cats.insert(cat); - continue; - clean_cat: - llwarns << "Unable to import near " << cat->getName() << llendl; - rv = false; - //delete cat; // automatic when cat is reasigned or destroyed } S32 cached_category_count = 0; S32 cached_item_count = 0; if(!temp_cats.empty()) { + update_map_t child_counts; cat_array_t categories; item_array_t items; cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded. @@ -2241,85 +2234,84 @@ bool LLInventoryModel::loadSkeleton( return rv; } -bool LLInventoryModel::loadMeat( - const LLInventoryModel::options_t& options, const LLUUID& owner_id) +bool LLInventoryModel::loadMeat(const LLSD& options, const LLUUID& owner_id) { llinfos << "importing inventory for " << owner_id << llendl; - LLPermissions default_perm; - default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null); - LLPointer<LLViewerInventoryItem> item; - LLUUID id; - LLAssetType::EType type; - LLInventoryType::EType inv_type; bool rv = true; - for(options_t::const_iterator it = options.begin(); it < options.end(); ++it) - { - item = new LLViewerInventoryItem; - response_t::const_iterator no_response = (*it).end(); - response_t::const_iterator meat; - meat = (*it).find("name"); - if(meat == no_response) goto clean_item; - item->rename(std::string((*meat).second)); - meat = (*it).find("item_id"); - if(meat == no_response) goto clean_item; - id.set((*meat).second); - item->setUUID(id); - meat = (*it).find("parent_id"); - if(meat == no_response) goto clean_item; - id.set((*meat).second); - item->setParent(id); - meat = (*it).find("type"); - if(meat == no_response) goto clean_item; - type = (LLAssetType::EType)atoi((*meat).second.c_str()); - item->setType(type); - meat = (*it).find("inv_type"); - if(meat != no_response) - { - inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str()); - item->setInventoryType(inv_type); - } - meat = (*it).find("data_id"); - if(meat == no_response) goto clean_item; - id.set((*meat).second); - if(LLAssetType::AT_CALLINGCARD == type) - { - LLPermissions perm; - perm.init(id, owner_id, LLUUID::null, LLUUID::null); - item->setPermissions(perm); + for(LLSD::array_const_iterator it = options.beginArray(), + end = options.endArray(); it != end; ++it) + { + LLSD name = (*it)["name"]; + LLSD item_id = (*it)["item_id"]; + LLSD parent_id = (*it)["parent_id"]; + LLSD asset_type = (*it)["type"]; + LLSD data_id = (*it)["data_id"]; + if(name.isDefined() + && item_id.isDefined() + && parent_id.isDefined() + && asset_type.isDefined() + && data_id.isDefined()) + { + LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem; + item->rename(name.asString()); + item->setUUID(item_id.asUUID()); + item->setParent(parent_id.asUUID()); + LLAssetType::EType type = (LLAssetType::EType)asset_type.asInteger(); + item->setType(type); + + LLSD llsd_inv_type = (*it)["inv_type"]; + if(llsd_inv_type.isDefined()) + { + LLInventoryType::EType inv_type = (LLInventoryType::EType)llsd_inv_type.asInteger(); + item->setInventoryType(inv_type); + } + + if(LLAssetType::AT_CALLINGCARD == type) + { + LLPermissions perm; + perm.init(data_id.asUUID(), owner_id, LLUUID::null, LLUUID::null); + item->setPermissions(perm); + } + else + { + LLPermissions default_perm; + default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null); + LLSD llsd_perm_mask = (*it)["perm_mask"]; + if(llsd_perm_mask.isDefined()) + { + PermissionMask perm_mask = llsd_perm_mask.asInteger(); + default_perm.initMasks( + perm_mask, perm_mask, perm_mask, perm_mask, perm_mask); + } + else + { + default_perm.initMasks( + PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE); + } + item->setPermissions(default_perm); + item->setAssetUUID(data_id.asUUID()); + } + + LLSD flags = (*it)["flags"]; + if(flags.isDefined()) + { + // Not sure how well LLSD.asInteger() maps to + // unsigned long - using strtoul() + item->setFlags(strtoul(flags.asString().c_str(), NULL, 0)); + } + + LLSD time = (*it)["time"]; + if(time.isDefined()) + { + item->setCreationDate(time.asInteger()); + } + addItem(item); } else { - meat = (*it).find("perm_mask"); - if(meat != no_response) - { - PermissionMask perm_mask = atoi((*meat).second.c_str()); - default_perm.initMasks( - perm_mask, perm_mask, perm_mask, perm_mask, perm_mask); - } - else - { - default_perm.initMasks( - PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE); - } - item->setPermissions(default_perm); - item->setAssetUUID(id); - } - meat = (*it).find("flags"); - if(meat != no_response) - { - item->setFlags(strtoul((*meat).second.c_str(), NULL, 0)); - } - meat = (*it).find("time"); - if(meat != no_response) - { - item->setCreationDate(atoi((*meat).second.c_str())); + llwarns << "Unable to import near " << name.asString() << llendl; + rv = false; } - addItem(item); - continue; - clean_item: - llwarns << "Unable to import near " << item->getName() << llendl; - rv = false; - //delete item; // automatic when item is reassigned or destroyed } return rv; } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index c2d8717b70..7d4f3372e9 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -332,10 +332,8 @@ public: // methods to load up inventory skeleton & meat. These are used // during authentication. return true if everything parsed. - typedef std::map<std::string, std::string> response_t; - typedef std::vector<response_t> options_t; - bool loadSkeleton(const options_t& options, const LLUUID& owner_id); - bool loadMeat(const options_t& options, const LLUUID& owner_id); + bool loadSkeleton(const LLSD& options, const LLUUID& owner_id); + bool loadMeat(const LLSD& options, const LLUUID& owner_id); // This is a brute force method to rebuild the entire parent-child // relations. diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp index 0bd3e42556..6bcbe6f58c 100644 --- a/indra/newview/lllocaltextureobject.cpp +++ b/indra/newview/lllocaltextureobject.cpp @@ -47,7 +47,7 @@ LLLocalTextureObject::LLLocalTextureObject() : mImage = NULL; } -LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, LLUUID& id) +LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id) { mImage = image; gGL.getTexUnit(0)->bind(mImage); diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h index 461756ee46..c8b8aa924b 100644 --- a/indra/newview/lllocaltextureobject.h +++ b/indra/newview/lllocaltextureobject.h @@ -35,7 +35,8 @@ #include <boost/shared_ptr.hpp> -class LLViewerFetchedTexture; +#include "llviewertexture.h" + class LLUUID; class LLTexLayer; class LLTextureEntry; @@ -49,7 +50,7 @@ class LLLocalTextureObject { public: LLLocalTextureObject(); - LLLocalTextureObject(LLViewerFetchedTexture* image, LLUUID& id); + LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id); LLLocalTextureObject(const LLLocalTextureObject& lto); ~LLLocalTextureObject(); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp new file mode 100644 index 0000000000..e5f347ddc4 --- /dev/null +++ b/indra/newview/lllogininstance.cpp @@ -0,0 +1,475 @@ +/** + * @file lllogininstance.cpp + * @brief Viewer's host for a login connection. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lllogininstance.h" + +// llcommon +#include "llevents.h" +#include "llmd5.h" +#include "stringize.h" + +// llmessage (!) +#include "llfiltersd2xmlrpc.h" // for xml_escape_string() + +// login +#include "lllogin.h" + +// newview +#include "llviewernetwork.h" +#include "llviewercontrol.h" +#include "llurlsimstring.h" +#include "llfloaterreg.h" +#include "llnotifications.h" +#include "llwindow.h" +#if LL_LINUX || LL_SOLARIS +#include "lltrans.h" +#endif + +static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; +static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; + +std::string construct_start_string(); + +LLLoginInstance::LLLoginInstance() : + mLoginModule(new LLLogin()), + mNotifications(NULL), + mLoginState("offline"), + mUserInteraction(true), + mSkipOptionalUpdate(false), + mAttemptComplete(false), + mTransferRate(0.0f), + mDispatcher("LLLoginInstance", "change") +{ + mLoginModule->getEventPump().listen("lllogininstance", + boost::bind(&LLLoginInstance::handleLoginEvent, this, _1)); + mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1)); + mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1)); + mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1)); +} + +LLLoginInstance::~LLLoginInstance() +{ +} + +void LLLoginInstance::connect(const LLSD& credentials) +{ + std::vector<std::string> uris; + LLViewerLogin::getInstance()->getLoginURIs(uris); + connect(uris.front(), credentials); +} + +void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials) +{ + mAttemptComplete = false; // Reset attempt complete at this point! + constructAuthParams(credentials); + mLoginModule->connect(uri, mRequestData); +} + +void LLLoginInstance::reconnect() +{ + // Sort of like connect, only using the pre-existing + // request params. + std::vector<std::string> uris; + LLViewerLogin::getInstance()->getLoginURIs(uris); + mLoginModule->connect(uris.front(), mRequestData); +} + +void LLLoginInstance::disconnect() +{ + mAttemptComplete = false; // Reset attempt complete at this point! + mRequestData.clear(); + mLoginModule->disconnect(); +} + +LLSD LLLoginInstance::getResponse() +{ + return mResponseData; +} + +void LLLoginInstance::constructAuthParams(const LLSD& credentials) +{ + // Set up auth request options. +//#define LL_MINIMIAL_REQUESTED_OPTIONS + LLSD requested_options; + // *Note: this is where gUserAuth used to be created. + requested_options.append("inventory-root"); + requested_options.append("inventory-skeleton"); + //requested_options.append("inventory-meat"); + //requested_options.append("inventory-skel-targets"); +#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS) + if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary")) + { + requested_options.append("inventory-lib-root"); + requested_options.append("inventory-lib-owner"); + requested_options.append("inventory-skel-lib"); + // requested_options.append("inventory-meat-lib"); + } + + requested_options.append("initial-outfit"); + requested_options.append("gestures"); + requested_options.append("event_categories"); + requested_options.append("event_notifications"); + requested_options.append("classified_categories"); + requested_options.append("adult_compliant"); + //requested_options.append("inventory-targets"); + requested_options.append("buddy-list"); + requested_options.append("ui-config"); +#endif + requested_options.append("tutorial_setting"); + requested_options.append("login-flags"); + requested_options.append("global-textures"); + if(gSavedSettings.getBOOL("ConnectAsGod")) + { + gSavedSettings.setBOOL("UseDebugMenus", TRUE); + requested_options.append("god-connect"); + } + + char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ + LLMD5 hashed_mac; + hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); + hashed_mac.finalize(); + hashed_mac.hex_digest(hashed_mac_string); + + // prepend "$1$" to the password to indicate its the md5'd version. + std::string dpasswd("$1$"); + dpasswd.append(credentials["passwd"].asString()); + + // (re)initialize the request params with creds. + LLSD request_params(credentials); + request_params["passwd"] = dpasswd; + 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_mac_string; + request_params["version"] = gCurrentVersion; // Includes channel name + request_params["channel"] = gSavedSettings.getString("VersionChannelName"); + request_params["id0"] = mSerialNumber; + + mRequestData.clear(); + mRequestData["method"] = "login_to_simulator"; + mRequestData["params"] = request_params; + mRequestData["options"] = requested_options; +} + +bool LLLoginInstance::handleLoginEvent(const LLSD& event) +{ + std::cout << "LoginListener called!: \n"; + std::cout << event << "\n"; + + if(!(event.has("state") && event.has("change") && event.has("progress"))) + { + llerrs << "Unknown message from LLLogin: " << event << llendl; + } + + mLoginState = event["state"].asString(); + mResponseData = event["data"]; + + if(event.has("transfer_rate")) + { + mTransferRate = event["transfer_rate"].asReal(); + } + + // Call the method registered in constructor, if any, for more specific + // handling + LLEventDispatcher::Callable method(mDispatcher.get(event["change"])); + if (! method.empty()) + { + method(event); + } + return false; +} + +void LLLoginInstance::handleLoginFailure(const LLSD& event) +{ + // Login has failed. + // Figure out why and respond... + LLSD response = event["data"]; + std::string reason_response = response["reason"].asString(); + std::string message_response = response["message"].asString(); + if(mUserInteraction) + { + // For the cases of critical message or TOS agreement, + // start the TOS dialog. The dialog response will be handled + // by the LLLoginInstance::handleTOSResponse() callback. + // The callback intiates the login attempt next step, either + // to reconnect or to end the attempt in failure. + if(reason_response == "tos") + { + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_tos", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "agree_to_tos")); + } + else if(reason_response == "critical") + { + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_critical", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical")); + } + else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) + { + gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); + updateApp(true, message_response); + } + else if(reason_response == "optional") + { + updateApp(false, message_response); + } + else + { + attemptComplete(); + } + } + else // no user interaction + { + attemptComplete(); + } +} + +void LLLoginInstance::handleLoginSuccess(const LLSD& event) +{ + if(gSavedSettings.getBOOL("ForceMandatoryUpdate")) + { + LLSD response = event["data"]; + std::string message_response = response["message"].asString(); + + // Testing update... + gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); + + // Don't confuse startup by leaving login "online". + mLoginModule->disconnect(); + updateApp(true, message_response); + } + else + { + attemptComplete(); + } +} + +void LLLoginInstance::handleDisconnect(const LLSD& event) +{ + // placeholder +} + +bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) +{ + if(accepted) + { + // Set the request data to true and retry login. + mRequestData["params"][key] = true; + reconnect(); + } + else + { + attemptComplete(); + } + + LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME); + return true; +} + + +void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) +{ + // store off config state, as we might quit soon + gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); + LLUIColorTable::instance().saveUserSettings(); + + std::ostringstream message; + std::string msg; + if (!auth_msg.empty()) + { + msg = "(" + auth_msg + ") \n"; + } + + LLSD args; + args["MESSAGE"] = msg; + + LLSD payload; + payload["mandatory"] = mandatory; + +/* + We're constructing one of the following 6 strings here: + "DownloadWindowsMandatory" + "DownloadWindowsReleaseForDownload" + "DownloadWindows" + "DownloadMacMandatory" + "DownloadMacReleaseForDownload" + "DownloadMac" + + I've called them out explicitly in this comment so that they can be grepped for. + + Also, we assume that if we're not Windows we're Mac. If we ever intend to support + Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but + we'd rather deliver the wrong message than no message, so until Linux is supported + we'll leave it alone. + */ + std::string notification_name = "Download"; + +#if LL_WINDOWS + notification_name += "Windows"; +#elif LL_DARWIN + notification_name += "Mac"; +#else + notification_name += "Linux"; +#endif + + if (mandatory) + { + notification_name += "Mandatory"; + } + else + { +#if LL_RELEASE_FOR_DOWNLOAD + notification_name += "ReleaseForDownload"; +#endif + } + + if(mNotifications) + { + mNotifications->add(notification_name, args, payload, + boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); + } + + /* *NOTE:Mani Experiment with Event API interface. + if(!mUpdateAppResponse) + { + bool make_unique = true; + mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique)); + mUpdateAppResponse->listen("diaupdateDialogCallback", + boost::bind(&LLLoginInstance::updateDialogCallback, + this, _1 + ) + ); + } + + LLSD event; + event["op"] = "requestAdd"; + event["name"] = notification_name; + event["substitutions"] = args; + event["payload"] = payload; + event["reply"] = mUpdateAppResponse->getName(); + + LLEventPumps::getInstance()->obtain("LLNotifications").post(event); + */ +} + +bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + std::string update_exe_path; + bool mandatory = notification["payload"]["mandatory"].asBoolean(); + +#if !LL_RELEASE_FOR_DOWNLOAD + if (option == 2) + { + // This condition attempts to skip the + // update if using a dev build. + // The relog probably won't work if the + // update is mandatory. :) + + // *REMOVE:Mani - Saving for reference... + //LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); + mSkipOptionalUpdate = true; + reconnect(); + return false; + } +#endif + + if (option == 1) + { + // ...user doesn't want to do it + if (mandatory) + { + // Mandatory update, user chose to not to update... + // The login attemp is complete, startup should + // quit when detecting this. + attemptComplete(); + + // *REMOVE:Mani - Saving for reference... + //LLAppViewer::instance()->forceQuit(); + // // Bump them back to the login screen. + // //reset_login(); + } + else + { + // Optional update, user chose to skip + mSkipOptionalUpdate = true; + reconnect(); + } + return false; + } + + if(mUpdaterLauncher) + { + mUpdaterLauncher(); + } + + attemptComplete(); + + return false; +} + +std::string construct_start_string() +{ + std::string start; + if (LLURLSimString::parse()) + { + // a startup URL was specified + std::string unescaped_start = + STRINGIZE( "uri:" + << LLURLSimString::sInstance.mSimName << "&" + << LLURLSimString::sInstance.mX << "&" + << LLURLSimString::sInstance.mY << "&" + << LLURLSimString::sInstance.mZ); + start = xml_escape_string(unescaped_start); + } + else + { + start = gSavedSettings.getString("LoginLocation"); + } + return start; +} + diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h new file mode 100644 index 0000000000..19d7449bc1 --- /dev/null +++ b/indra/newview/lllogininstance.h @@ -0,0 +1,114 @@ +/** + * @file lllogininstance.h + * @brief A host for the viewer's login connection. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLLOGININSTANCE_H +#define LL_LLLOGININSTANCE_H + +#include "lleventdispatcher.h" +#include <boost/scoped_ptr.hpp> +#include <boost/function.hpp> +class LLLogin; +class LLEventStream; +class LLNotificationsInterface; + +// This class hosts the login module and is used to +// negotiate user authentication attempts. +class LLLoginInstance : public LLSingleton<LLLoginInstance> +{ +public: + LLLoginInstance(); + ~LLLoginInstance(); + + void connect(const LLSD& credential); // Connect to the current grid choice. + void connect(const std::string& uri, const LLSD& credential); // Connect to the given uri. + void reconnect(); // reconnect using the current credentials. + void disconnect(); + + bool authFailure() { return mAttemptComplete && mLoginState == "offline"; } + bool authSuccess() { return mAttemptComplete && mLoginState == "online"; } + + const std::string& getLoginState() { return mLoginState; } + LLSD getResponse(const std::string& key) { return getResponse()[key]; } + LLSD getResponse(); + + // Only valid when authSuccess == true. + const F64 getLastTransferRateBPS() { return mTransferRate; } + + // Set whether this class will drive user interaction. + // If not, login failures like 'need tos agreement' will + // end the login attempt. + void setUserInteraction(bool state) { mUserInteraction = state; } + bool getUserInteraction() { return mUserInteraction; } + + // Whether to tell login to skip optional update request. + // False by default. + void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; } + void setSerialNumber(const std::string& sn) { mSerialNumber = sn; } + void setLastExecEvent(int lee) { mLastExecEvent = lee; } + + void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; } + + typedef boost::function<void()> UpdaterLauncherCallback; + void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; } + +private: + void constructAuthParams(const LLSD& credentials); + void updateApp(bool mandatory, const std::string& message); + bool updateDialogCallback(const LLSD& notification, const LLSD& response); + + bool handleLoginEvent(const LLSD& event); + void handleLoginFailure(const LLSD& event); + void handleLoginSuccess(const LLSD& event); + void handleDisconnect(const LLSD& event); + + bool handleTOSResponse(bool v, const std::string& key); + + void attemptComplete() { mAttemptComplete = true; } // In the future an event? + + boost::scoped_ptr<LLLogin> mLoginModule; + LLNotificationsInterface* mNotifications; + + std::string mLoginState; + LLSD mRequestData; + LLSD mResponseData; + bool mUserInteraction; + bool mSkipOptionalUpdate; + bool mAttemptComplete; + F64 mTransferRate; + std::string mSerialNumber; + int mLastExecEvent; + UpdaterLauncherCallback mUpdaterLauncher; + boost::scoped_ptr<LLEventStream> mUpdateAppResponse; + LLEventDispatcher mDispatcher; +}; + +#endif diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 4fa7f62c68..15efd0100a 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -321,36 +321,9 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) { BOOL result = FALSE; - // FIXME: THIS IS SO WRONG. - // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... - if (mMediaSource) { - if( MASK_CONTROL & mask ) - { - if( 'C' == key ) - { - mMediaSource->copy(); - result = TRUE; - } - else - if( 'V' == key ) - { - mMediaSource->paste(); - result = TRUE; - } - else - if( 'X' == key ) - { - mMediaSource->cut(); - result = TRUE; - } - } - - if(!result) - { - result = mMediaSource->handleKeyHere(key, mask); - } + result = mMediaSource->handleKeyHere(key, mask); } return result; @@ -373,12 +346,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { BOOL result = FALSE; - // only accept 'printable' characters, sigh... - if (uni_char >= 32 // discard 'control' characters - && uni_char != 127) // SDL thinks this is 'delete' - yuck. + if (mMediaSource) { - if (mMediaSource) - result = mMediaSource->handleUnicodeCharHere(uni_char); + result = mMediaSource->handleUnicodeCharHere(uni_char); } return result; @@ -905,6 +875,18 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL; }; break; + + case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_NAME_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; + }; + break; }; // chain all events to any potential observers of this object. diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 6a932d76bf..6ae42d23d3 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -34,15 +34,18 @@ #include "llmediadataclient.h" +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + #include <boost/lexical_cast.hpp> #include "llhttpstatuscodes.h" -#include "llnotifications.h" #include "llsdutil.h" #include "llmediaentry.h" #include "lltextureentry.h" #include "llviewerregion.h" -#include "llvovolume.h" // // When making a request @@ -55,7 +58,9 @@ // - Any request that gets a 503 still goes through the retry logic // -// Some helpful logging macros +const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s) +const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs +const U32 LLMediaDataClient::MAX_RETRIES = 4; ////////////////////////////////////////////////////////////////////////////////////// // @@ -66,7 +71,7 @@ LLMediaDataClient::Request::Request(const std::string &cap_name, const LLSD& sd_payload, - LLVOVolume *obj, + LLMediaDataClientObject *obj, LLMediaDataClient *mdc) : mCapName(cap_name), mPayload(sd_payload), @@ -79,38 +84,39 @@ LLMediaDataClient::Request::Request(const std::string &cap_name, LLMediaDataClient::Request::~Request() { + LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL; mMDC = NULL; - mObject = NULL; + mObject = NULL; } std::string LLMediaDataClient::Request::getCapability() const { - return getObject()->getRegion()->getCapability(getCapName()); + return getObject()->getCapabilityUrl(getCapName()); } // Helper function to get the "type" of request, which just pokes around to // discover it. LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const { - if (mCapName == "ObjectMediaNavigate") - { - return NAVIGATE; - } - else if (mCapName == "ObjectMedia") - { - const std::string &verb = mPayload["verb"]; - if (verb == "GET") - { - return GET; - } - else if (verb == "UPDATE") - { - return UPDATE; - } - } - llassert(false); - return GET; + if (mCapName == "ObjectMediaNavigate") + { + return NAVIGATE; + } + else if (mCapName == "ObjectMedia") + { + const std::string &verb = mPayload["verb"]; + if (verb == "GET") + { + return GET; + } + else if (verb == "UPDATE") + { + return UPDATE; + } + } + llassert(false); + return GET; } const char *LLMediaDataClient::Request::getTypeAsString() const @@ -138,6 +144,17 @@ void LLMediaDataClient::Request::reEnqueue() const mMDC->enqueue(this); } +F32 LLMediaDataClient::Request::getRetryTimerDelay() const +{ + return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY : + mMDC->mRetryTimerDelay; +} + +U32 LLMediaDataClient::Request::getMaxNumRetries() const +{ + return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries; +} + std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) { s << "<request>" @@ -164,15 +181,21 @@ LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr) // virtual LLMediaDataClient::Responder::RetryTimer::~RetryTimer() { + LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL; + + // XXX This is weird: Instead of doing the work in tick() (which re-schedules + // a timer, which might be risky), do it here, in the destructor. Yes, it is very odd. + // Instead of retrying, we just put the request back onto the queue + LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL; + mResponder->getRequest()->reEnqueue(); + + // Release the ref to the responder. mResponder = NULL; } // virtual BOOL LLMediaDataClient::Responder::RetryTimer::tick() { - // Instead of retrying, we just put the request back onto the queue - LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL; - mResponder->getRequest()->reEnqueue(); // Don't fire again return TRUE; } @@ -191,35 +214,35 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request) LLMediaDataClient::Responder::~Responder() { - mRequest = NULL; + LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL; + mRequest = NULL; } /*virtual*/ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) { - extern LLControlGroup gSavedSettings; - if (status == HTTP_SERVICE_UNAVAILABLE) { - F32 retry_timeout = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); - if (retry_timeout <= 0.0) - { - retry_timeout = (F32)UNAVAILABLE_RETRY_TIMER_DELAY; - } - LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; + F32 retry_timeout = mRequest->getRetryTimerDelay(); mRequest->incRetryCount(); - // Start timer (instances are automagically tracked by - // InstanceTracker<> and LLEventTimer) - new RetryTimer(F32(retry_timeout/*secs*/), this); + if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) + { + LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; + + // Start timer (instances are automagically tracked by + // InstanceTracker<> and LLEventTimer) + new RetryTimer(F32(retry_timeout/*secs*/), this); + } + else { + LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " << + mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; + } } else { std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason; - LL_INFOS("LLMediaDataClient") << *mRequest << " error(" << msg << ")" << LL_ENDL; - LLSD args; - args["ERROR"] = msg; - LLNotifications::instance().add("ObjectMediaFailure", args); + LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL; } } @@ -227,7 +250,7 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) /*virtual*/ void LLMediaDataClient::Responder::result(const LLSD& content) { - LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_pretty_print_sd(content) << LL_ENDL; + LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL; } @@ -256,29 +279,25 @@ bool LLMediaDataClient::Comparator::operator() (const request_ptr_t &o1, const r // Calculate the scores for each. F64 o1_score = Comparator::getObjectScore(o1->getObject()); F64 o2_score = Comparator::getObjectScore(o2->getObject()); - - return ( o1_score > o2_score ); + + // XXX Weird: a higher score should go earlier, but by observation I notice + // that this causes further-away objects load first. This is counterintuitive + // to the priority_queue Comparator, which states that this function should + // return 'true' if o1 should be *before* o2. + // In other words, I'd have expected that the following should return + // ( o1_score > o2_score). + return ( o1_score < o2_score ); } // static -F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj) +F64 LLMediaDataClient::Comparator::getObjectScore(const LLMediaDataClientObject::ptr_t &obj) { // *TODO: make this less expensive? - F32 dist = obj->getRenderPosition().length() + 0.1; // avoids div by 0 + F64 dist = obj->getDistanceFromAvatar() + 0.1; // avoids div by 0 // square the distance so that they are in the same "unit magnitude" as // the interest (which is an area) dist *= dist; - F64 interest = (F64)1; - int i = 0; - int end = obj->getNumTEs(); - for ( ; i < end; ++i) - { - const viewer_media_t &impl = obj->getMediaImpl(i); - if (!impl.isNull()) - { - interest += impl->getInterest(); - } - } + F64 interest = obj->getTotalMediaInterest() + 1.0; return interest/dist; } @@ -286,7 +305,7 @@ F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj) ////////////////////////////////////////////////////////////////////////////////////// // // LLMediaDataClient::PriorityQueue -// Queue of LLVOVolume smart pointers to request media for. +// Queue of LLMediaDataClientObject smart pointers to request media for. // ////////////////////////////////////////////////////////////////////////////////////// @@ -308,7 +327,7 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::PriorityQueue ////////////////////////////////////////////////////////////////////////////////////// // // LLMediaDataClient::QueueTimer -// Queue of LLVOVolume smart pointers to request media for. +// Queue of LLMediaDataClientObject smart pointers to request media for. // ////////////////////////////////////////////////////////////////////////////////////// @@ -320,6 +339,7 @@ LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc) LLMediaDataClient::QueueTimer::~QueueTimer() { + LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL; mMDC->setIsRunning(false); mMDC = NULL; } @@ -342,15 +362,15 @@ BOOL LLMediaDataClient::QueueTimer::tick() return TRUE; } - LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL; + LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL; // Peel one off of the items from the queue, and execute request request_ptr_t request = queue.top(); llassert(!request.isNull()); - const ll_vo_volume_ptr_t &object = request->getObject(); + const LLMediaDataClientObject *object = request->getObject(); bool performed_request = false; - llassert(!object.isNull()); - if (!object.isNull() && object->hasMedia()) + llassert(NULL != object); + if (NULL != object && object->hasMedia()) { std::string url = request->getCapability(); if (!url.empty()) @@ -367,17 +387,22 @@ BOOL LLMediaDataClient::QueueTimer::tick() } } else { - if (!object->hasMedia()) + if (NULL == object) { - LL_INFOS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL; + LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL; + } + else if (!object->hasMedia()) + { + LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL; } } - bool exceeded_retries = request->getRetryCount() > LLMediaDataClient::MAX_RETRIES; + bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries; if (performed_request || exceeded_retries) // Try N times before giving up { if (exceeded_retries) { - LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " << LLMediaDataClient::MAX_RETRIES << " tries...popping object id " << object->getID() << LL_ENDL; + LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " + << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL; // XXX Should we bring up a warning dialog?? } queue.pop(); @@ -394,15 +419,12 @@ void LLMediaDataClient::startQueueTimer() { if (! mQueueTimerIsRunning) { - extern LLControlGroup gSavedSettings; - F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); - if (queue_timer_delay <= 0.0f) - { - queue_timer_delay = (F32)LLMediaDataClient::QUEUE_TIMER_DELAY; - } - LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << queue_timer_delay << " seconds)" << LL_ENDL; + LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL; // LLEventTimer automagically takes care of the lifetime of this object - new QueueTimer(queue_timer_delay, this); + new QueueTimer(mQueueTimerDelay, this); + } + else { + LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL; } } @@ -411,9 +433,9 @@ void LLMediaDataClient::stopQueueTimer() mQueueTimerIsRunning = false; } -void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload) +void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload) { - if (NULL == object || ! object->hasMedia()) return; + if (object.isNull() || ! object->hasMedia()) return; // Push the object on the priority queue enqueue(new Request(getCapabilityName(), payload, object, this)); @@ -422,8 +444,8 @@ void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload) void LLMediaDataClient::enqueue(const Request *request) { LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL; - // Push the request on the priority queue - // Sadly, we have to const-cast because items put into the queue are not const + // Push the request on the priority queue + // Sadly, we have to const-cast because items put into the queue are not const pRequestQueue->push(const_cast<LLMediaDataClient::Request*>(request)); LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL; // Start the timer if not already running @@ -436,21 +458,31 @@ void LLMediaDataClient::enqueue(const Request *request) // ////////////////////////////////////////////////////////////////////////////////////// -LLMediaDataClient::LLMediaDataClient() +LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, + F32 retry_timer_delay, + U32 max_retries) + : mQueueTimerDelay(queue_timer_delay), + mRetryTimerDelay(retry_timer_delay), + mMaxNumRetries(max_retries), + mQueueTimerIsRunning(false) { pRequestQueue = new PriorityQueue(); } - LLMediaDataClient::~LLMediaDataClient() { stopQueueTimer(); - + // This should clear the queue, and hopefully call all the destructors. - while (! pRequestQueue->empty()) pRequestQueue->pop(); - + LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " << + (pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL; delete pRequestQueue; - pRequestQueue = NULL; + pRequestQueue = NULL; +} + +bool LLMediaDataClient::isEmpty() const +{ + return (NULL == pRequestQueue) ? true : pRequestQueue->empty(); } ////////////////////////////////////////////////////////////////////////////////////// @@ -462,79 +494,78 @@ LLMediaDataClient::~LLMediaDataClient() LLMediaDataClient::Responder *LLObjectMediaDataClient::createResponder(const request_ptr_t &request) const { - return new LLObjectMediaDataClient::Responder(request); + return new LLObjectMediaDataClient::Responder(request); } const char *LLObjectMediaDataClient::getCapabilityName() const { - return "ObjectMedia"; + return "ObjectMedia"; } -void LLObjectMediaDataClient::fetchMedia(LLVOVolume *object) +void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object) { - LLSD sd_payload; - sd_payload["verb"] = "GET"; - sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); - request(object, sd_payload); + LLSD sd_payload; + sd_payload["verb"] = "GET"; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); + request(object, sd_payload); } -void LLObjectMediaDataClient::updateMedia(LLVOVolume *object) +void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object) { - LLSD sd_payload; - sd_payload["verb"] = "UPDATE"; - sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); - LLSD object_media_data; - for (int i=0; i < object->getNumTEs(); i++) { - LLTextureEntry *texture_entry = object->getTE(i); - llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia()); - const LLSD &media_data = - (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD(); - object_media_data.append(media_data); - } - sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; - - LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_pretty_print_sd(sd_payload) << LL_ENDL; - - request(object, sd_payload); + LLSD sd_payload; + sd_payload["verb"] = "UPDATE"; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); + LLSD object_media_data; + int i = 0; + int end = object->getMediaDataCount(); + for ( ; i < end ; ++i) + { + object_media_data.append(object->getMediaDataLLSD(i)); + } + sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; + + LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL; + + request(object, sd_payload); } /*virtual*/ void LLObjectMediaDataClient::Responder::result(const LLSD& content) { - const LLMediaDataClient::Request::Type type = getRequest()->getType(); - llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE) - if (type == LLMediaDataClient::Request::GET) - { - LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_pretty_print_sd(content) << LL_ENDL; - - // Look for an error - if (content.has("error")) - { - const LLSD &error = content["error"]; - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << + const LLMediaDataClient::Request::Type type = getRequest()->getType(); + llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE) + if (type == LLMediaDataClient::Request::GET) + { + LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_print_sd(content) << LL_ENDL; + + // Look for an error + if (content.has("error")) + { + const LLSD &error = content["error"]; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; - - // XXX Warn user? - } - else { - // Check the data - const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY]; - if (object_id != getRequest()->getObject()->getID()) - { - // NOT good, wrong object id!! - LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; - return; - } - - // Otherwise, update with object media data - getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]); - } - } - else if (type == LLMediaDataClient::Request::UPDATE) - { - // just do what our superclass does - LLMediaDataClient::Responder::result(content); - } + + // XXX Warn user? + } + else { + // Check the data + const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY]; + if (object_id != getRequest()->getObject()->getID()) + { + // NOT good, wrong object id!! + LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; + return; + } + + // Otherwise, update with object media data + getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]); + } + } + else if (type == LLMediaDataClient::Request::UPDATE) + { + // just do what our superclass does + LLMediaDataClient::Responder::result(content); + } } ////////////////////////////////////////////////////////////////////////////////////// @@ -545,21 +576,21 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content) ////////////////////////////////////////////////////////////////////////////////////// LLMediaDataClient::Responder *LLObjectMediaNavigateClient::createResponder(const request_ptr_t &request) const { - return new LLObjectMediaNavigateClient::Responder(request); + return new LLObjectMediaNavigateClient::Responder(request); } const char *LLObjectMediaNavigateClient::getCapabilityName() const { - return "ObjectMediaNavigate"; + return "ObjectMediaNavigate"; } -void LLObjectMediaNavigateClient::navigate(LLVOVolume *object, U8 texture_index, const std::string &url) +void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url) { - LLSD sd_payload; - sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); + LLSD sd_payload; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID(); sd_payload[LLMediaEntry::CURRENT_URL_KEY] = url; sd_payload[LLTextureEntry::TEXTURE_INDEX_KEY] = (LLSD::Integer)texture_index; - request(object, sd_payload); + request(object, sd_payload); } /*virtual*/ @@ -573,16 +604,18 @@ void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string } else { // bounce the face back - bounceBack(); LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL; + const LLSD &payload = getRequest()->getPayload(); + // bounce the face back + getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); } } /*virtual*/ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) { - LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_pretty_print_sd(content) << LL_ENDL; - + LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL; + if (content.has("error")) { const LLSD &error = content["error"]; @@ -590,38 +623,19 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) if (ERROR_PERMISSION_DENIED_CODE == error_code) { - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL; + const LLSD &payload = getRequest()->getPayload(); // bounce the face back - bounceBack(); + getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); } else { - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; - } + } // XXX Warn user? } - else { - // just do what our superclass does - LLMediaDataClient::Responder::result(content); - } -} - - -void LLObjectMediaNavigateClient::Responder::bounceBack() -{ - const LLSD &payload = getRequest()->getPayload(); - U8 texture_index = (U8)(LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]; - viewer_media_t impl = getRequest()->getObject()->getMediaImpl(texture_index); - // Find the media entry for this navigate - LLMediaEntry* mep = NULL; - LLTextureEntry *te = getRequest()->getObject()->getTE(texture_index); - if(te) - { - mep = te->getMediaData(); - } - - if (mep && impl) - { -// impl->navigateTo(mep->getCurrentURL()); - } + else { + // just do what our superclass does + LLMediaDataClient::Responder::result(content); + } } diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index 59c4334251..9d0aa0981e 100755 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -36,12 +36,36 @@ #include "llhttpclient.h" #include <queue> #include "llrefcount.h" +#include "llpointer.h" #include "lltimer.h" -// Forward decls -class LLVOVolume; -typedef LLPointer<LLVOVolume> ll_vo_volume_ptr_t; +// Link seam for LLVOVolume +class LLMediaDataClientObject : public LLRefCount +{ +public: + // Get the number of media data items + virtual U8 getMediaDataCount() const = 0; + // Get the media data at index, as an LLSD + virtual LLSD getMediaDataLLSD(U8 index) const = 0; + // Get this object's UUID + virtual LLUUID getID() const = 0; + // Navigate back to previous URL + virtual void mediaNavigateBounceBack(U8 index) = 0; + // Does this object have media? + virtual bool hasMedia() const = 0; + // Update the object's media data to the given array + virtual void updateObjectMediaData(LLSD const &media_data_array) = 0; + // Return the distance from the object to the avatar + virtual F64 getDistanceFromAvatar() const = 0; + // Return the total "interest" of the media (on-screen area) + virtual F64 getTotalMediaInterest() const = 0; + // Return the given cap url + virtual std::string getCapabilityUrl(const std::string &name) const = 0; + + // smart pointer + typedef LLPointer<LLMediaDataClientObject> ptr_t; +}; // This object creates a priority queue for requests. // Abstracts the Cap URL, the request, and the responder @@ -50,15 +74,23 @@ class LLMediaDataClient : public LLRefCount public: LOG_CLASS(LLMediaDataClient); - const static int QUEUE_TIMER_DELAY = 1; // seconds(s) - const static int MAX_RETRIES = 4; + const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s) + const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs + const static U32 MAX_RETRIES;// = 4; // Constructor - LLMediaDataClient(); + LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, + F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, + U32 max_retries = MAX_RETRIES); // Make the request - void request(LLVOVolume *object, const LLSD &payload); - + void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload); + + F32 getRetryTimerDelay() const { return mRetryTimerDelay; } + + // Returns true iff the queue is empty + bool isEmpty() const; + protected: // Destructor virtual ~LLMediaDataClient(); // use unref @@ -73,10 +105,10 @@ protected: NAVIGATE }; - Request(const std::string &cap_name, const LLSD& sd_payload, LLVOVolume *obj, LLMediaDataClient *mdc); + Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc); const std::string &getCapName() const { return mCapName; } const LLSD &getPayload() const { return mPayload; } - LLVOVolume *getObject() const { return mObject; } + LLMediaDataClientObject *getObject() const { return mObject; } U32 getNum() const { return mNum; } @@ -92,6 +124,9 @@ protected: // Re-enqueue thyself void reEnqueue() const; + F32 getRetryTimerDelay() const; + U32 getMaxNumRetries() const; + public: friend std::ostream& operator<<(std::ostream &s, const Request &q); @@ -101,7 +136,7 @@ protected: private: std::string mCapName; LLSD mPayload; - ll_vo_volume_ptr_t mObject; + LLMediaDataClientObject::ptr_t mObject; // Simple tracking const U32 mNum; static U32 sNum; @@ -115,8 +150,6 @@ protected: // Responder class Responder : public LLHTTPClient::Responder { - static const int UNAVAILABLE_RETRY_TIMER_DELAY = 5; // secs - public: Responder(const request_ptr_t &request); //If we get back an error (not found, etc...), handle it here @@ -163,9 +196,10 @@ private: public: bool operator() (const request_ptr_t &o1, const request_ptr_t &o2) const; private: - static F64 getObjectScore(const ll_vo_volume_ptr_t &obj); + static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj); }; + // PriorityQueue class PriorityQueue : public std::priority_queue< request_ptr_t, std::vector<request_ptr_t>, @@ -193,6 +227,10 @@ private: void startQueueTimer(); void stopQueueTimer(); void setIsRunning(bool val) { mQueueTimerIsRunning = val; } + + const F32 mQueueTimerDelay; + const F32 mRetryTimerDelay; + const U32 mMaxNumRetries; bool mQueueTimerIsRunning; @@ -204,11 +242,15 @@ private: class LLObjectMediaDataClient : public LLMediaDataClient { public: - LLObjectMediaDataClient() {} + LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, + F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, + U32 max_retries = MAX_RETRIES) + : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) + {} ~LLObjectMediaDataClient() {} - void fetchMedia(LLVOVolume *object); - void updateMedia(LLVOVolume *object); + void fetchMedia(LLMediaDataClientObject *object); + void updateMedia(LLMediaDataClientObject *object); protected: // Subclasses must override this factory method to return a new responder @@ -230,14 +272,18 @@ protected: // MediaDataResponder specific for the ObjectMediaNavigate cap class LLObjectMediaNavigateClient : public LLMediaDataClient { +public: // NOTE: from llmediaservice.h static const int ERROR_PERMISSION_DENIED_CODE = 8002; -public: - LLObjectMediaNavigateClient() {} + LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, + F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, + U32 max_retries = MAX_RETRIES) + : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries) + {} ~LLObjectMediaNavigateClient() {} - void navigate(LLVOVolume *object, U8 texture_index, const std::string &url); + void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url); protected: // Subclasses must override this factory method to return a new responder @@ -254,7 +300,7 @@ protected: virtual void error(U32 status, const std::string& reason); virtual void result(const LLSD &content); private: - void bounceBack(); + void mediaNavigateBounceBack(); }; }; diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index 8dd09d5ec7..28ddaa61c4 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -66,7 +66,6 @@ #include "llfocusmgr.h" #include "llnearbychatbar.h" - void handle_mouselook(void*) { gAgent.changeCameraToMouselook(); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index faa938c772..83fb147a49 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -36,6 +36,7 @@ #include "llbutton.h" #include "llfloaterreg.h" #include "llsdutil.h" +#include "llsdutil_math.h" #include "llaccordionctrltab.h" #include "llagent.h" diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 3177ef9a21..f9dde03451 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -1,440 +1,448 @@ -/** - * @file llpanelmediasettingsgeneral.cpp - * @brief LLPanelMediaSettingsGeneral class implementation - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmediasettingsgeneral.h" -#include "llcombobox.h" -#include "llcheckboxctrl.h" -#include "llspinctrl.h" -#include "lluictrlfactory.h" -#include "llviewerwindow.h" -#include "llviewermedia.h" -#include "llsdutil.h" -#include "llselectmgr.h" -#include "llbutton.h" -#include "lltexturectrl.h" -#include "llurl.h" -#include "llwindow.h" -#include "llmediaentry.h" -#include "llmediactrl.h" -#include "llpanelcontents.h" -#include "llpluginclassmedia.h" -#include "llfloatermediasettings.h" -#include "llfloatertools.h" -#include "lltrans.h" - -//////////////////////////////////////////////////////////////////////////////// -// -LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() : - mControls( NULL ), - mAutoLoop( NULL ), - mFirstClick( NULL ), - mAutoZoom( NULL ), - mAutoPlay( NULL ), - mAutoScale( NULL ), - mWidthPixels( NULL ), - mHeightPixels( NULL ), - mHomeURL( NULL ), - mCurrentURL( NULL ), - mAltImageEnable( NULL ), - mParent( NULL ), - mMediaEditable(false) -{ - // build dialog from XML - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml"); -// mCommitCallbackRegistrar.add("Media.ResetCurrentUrl", boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this)); -// mCommitCallbackRegistrar.add("Media.CommitHomeURL", boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this)); - -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLPanelMediaSettingsGeneral::postBuild() -{ - // connect member vars with UI widgets - mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY ); - mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY ); - mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY ); - mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY ); - mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY ); - mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); - mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY ); - mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); - mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY ); - mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY ); - mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY ); - mPreviewMedia = getChild<LLMediaCtrl>("preview_media"); - - // watch commit action for HOME URL - childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this); - childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this); - // interrogates controls and updates widgets as required - updateMediaPreview(); - updateCurrentURL(); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::draw() -{ - // housekeeping - LLPanel::draw(); - - // enable/disable pixel values image entry based on auto scale checkbox - if ( mAutoScale->getValue().asBoolean() == false ) - { - childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true ); - childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true ); - } - else - { - childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false ); - childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false ); - }; - - // enable/disable UI based on type of media - bool reset_button_is_active = true; - if( mPreviewMedia ) - { - LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin(); - if( media_plugin ) - { - // some controls are only appropriate for time or browser type plugins - // so we selectively enable/disable them - need to do it in draw - // because the information from plugins arrives assynchronously - bool show_time_controls = media_plugin->pluginSupportsMediaTime(); - if ( show_time_controls ) - { - childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false ); - reset_button_is_active = false; - childSetEnabled( "current_url_label", false ); - childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true ); - } - else - { - childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true ); - reset_button_is_active = true; - childSetEnabled( "current_url_label", true ); - childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false ); - }; - }; - }; - - // current URL can change over time. -// updateCurrentURL(); - - // enable/disable RESRET button depending on permissions - // since this is the same as a navigate action - bool user_can_press_reset = mMediaEditable; - - // several places modify this widget so we must collect states in one place - if ( reset_button_is_active ) - { - // user has perms to press reset button and it is active - if ( user_can_press_reset ) - { - childSetEnabled( "current_url_reset_btn", true ); - } - // user does not has perms to press reset button and it is active - else - { - childSetEnabled( "current_url_reset_btn", false ); - }; - } - else - // reset button is inactive so we just slam it to off - other states don't matter - { - childSetEnabled( "current_url_reset_btn", false ); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable) -{ - LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; - self->mAltImageEnable ->clear(); - self->mAutoLoop->clear(); - self->mAutoPlay->clear(); - self->mAutoScale->clear(); - self->mAutoZoom ->clear(); - self->mControls->clear(); - self->mCurrentURL->clear(); - self->mFirstClick->clear(); - self->mHeightPixels->clear(); - self->mHomeURL->clear(); - self->mWidthPixels->clear(); - self->mAltImageEnable ->setEnabled(editable); - self->mAutoLoop ->setEnabled(editable); - self->mAutoPlay ->setEnabled(editable); - self->mAutoScale ->setEnabled(editable); - self->mAutoZoom ->setEnabled(editable); - self->mControls ->setEnabled(editable); - self->mCurrentURL ->setEnabled(editable); - self->mFirstClick ->setEnabled(editable); - self->mHeightPixels ->setEnabled(editable); - self->mHomeURL ->setEnabled(editable); - self->mWidthPixels ->setEnabled(editable); - self->mPreviewMedia->unloadMediaSource(); -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable) -{ - LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; - self->mMediaEditable = editable; - - //llinfos << "---------------" << llendl; - //llinfos << ll_pretty_print_sd(media_settings) << llendl; - //llinfos << "---------------" << llendl; - - // IF all the faces have media (or all dont have media) - if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) - { - if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) - { - self->clearValues(self, self->mMediaEditable); - // only show multiple - self->mHomeURL ->setText(LLTrans::getString("Multiple Media")); - return; - } - - } - else - { - if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) - { - self->clearValues(self, self->mMediaEditable); - // only show multiple - self->mHomeURL ->setText(LLTrans::getString("Multiple Media")); - return; - } - - } - std::string base_key( "" ); - std::string tentative_key( "" ); - - struct - { - std::string key_name; - LLUICtrl* ctrl_ptr; - std::string ctrl_type; - - } data_set [] = - { - { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" }, - { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" }, - { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" }, - { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" }, - { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" }, - { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" }, - { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" }, - { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" }, - { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" }, - { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" }, - { LLMediaEntry::ALT_IMAGE_ENABLE_KEY, self->mAltImageEnable, "LLCheckBoxCtrl" }, - { "", NULL , "" } - }; - - for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) - { - base_key = std::string( data_set[ i ].key_name ); - tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); - // TODO: CP - I bet there is a better way to do this using Boost - if ( media_settings[ base_key ].isDefined() ) - { - if ( data_set[ i ].ctrl_type == "LLLineEditor" ) - { - static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )-> - setText( media_settings[ base_key ].asString() ); - } - else - if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) - static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> - setValue( media_settings[ base_key ].asBoolean() ); - else - if ( data_set[ i ].ctrl_type == "LLComboBox" ) - static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )-> - setCurrentByIndex( media_settings[ base_key ].asInteger() ); - else - if ( data_set[ i ].ctrl_type == "LLSpinCtrl" ) - static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )-> - setValue( media_settings[ base_key ].asInteger() ); - - data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable); - data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); - }; - }; - - // interrogates controls and updates widgets as required - self->updateMediaPreview(); - self->updateCurrentURL(); -} - -//////////////////////////////////////////////////////////////////////////////// -// Helper to set media control to media URL as required -void LLPanelMediaSettingsGeneral::updateMediaPreview() -{ - if ( mHomeURL->getValue().asString().length() > 0 ) - { - mPreviewMedia->navigateTo( mHomeURL->getValue().asString() ); - } - else - // new home URL will be empty if media is deleted but - // we still need to clean out the preview. - { - mPreviewMedia->unloadMediaSource(); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// Helper to set current URL -void LLPanelMediaSettingsGeneral::updateCurrentURL() -{ - if( mCurrentURL->getText().empty() ) - { - childSetText( "current_url", mHomeURL->getText() ); - } - -} - -//////////////////////////////////////////////////////////////////////////////// - -// virtual -void LLPanelMediaSettingsGeneral::onClose(bool app_quitting) -{ - if(mPreviewMedia) - { - mPreviewMedia->unloadMediaSource(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata ) -{ - LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; - self->updateMediaPreview(); -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata) -{ - LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; - self->navigateHomeSelectedFace(); -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsGeneral::apply( void* userdata ) -{ - LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; - self->mHomeURL->onCommit(); - // build LLSD Fragment - LLSD media_data_general; - self->getValues(media_data_general); - - // this merges contents of LLSD passed in with what's there so this is ok - LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in ) -{ - fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue(); - fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue(); - fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue(); - fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue(); - fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue(); - fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex(); - // XXX Don't send current URL! - //fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue(); - fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue(); - fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue(); - fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue(); - fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent ) -{ - mParent = parent; -}; - -bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace() -{ - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - struct functor_navigate_media : public LLSelectedTEGetFunctor< bool> - { - bool get( LLViewerObject* object, S32 face ) - { - if ( object ) - if ( object->getTE(face) ) - if ( object->getTE(face)->getMediaData() ) - { - if(object->permModify()) - { - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID()); - if(media_impl) - { - media_impl->navigateHome(); - return true; - } - } - } - return false; - }; - - } functor_navigate_media; - - bool all_face_media_navigated = false; - LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); - selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated ); - - return all_face_media_navigated; -} - +/**
+ * @file llpanelmediasettingsgeneral.cpp
+ * @brief LLPanelMediaSettingsGeneral class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llpanelmediasettingsgeneral.h"
+#include "llcombobox.h"
+#include "llcheckboxctrl.h"
+#include "llspinctrl.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+#include "llviewermedia.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llbutton.h"
+#include "lltexturectrl.h"
+#include "llurl.h"
+#include "llwindow.h"
+#include "llmediaentry.h"
+#include "llmediactrl.h"
+#include "llpanelcontents.h"
+#include "llpermissions.h"
+#include "llpluginclassmedia.h"
+#include "llfloatermediasettings.h"
+#include "llfloatertools.h"
+#include "lltrans.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
+ mControls( NULL ),
+ mAutoLoop( NULL ),
+ mFirstClick( NULL ),
+ mAutoZoom( NULL ),
+ mAutoPlay( NULL ),
+ mAutoScale( NULL ),
+ mWidthPixels( NULL ),
+ mHeightPixels( NULL ),
+ mHomeURL( NULL ),
+ mCurrentURL( NULL ),
+ mParent( NULL ),
+ mMediaEditable(false)
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsGeneral::postBuild()
+{
+ // connect member vars with UI widgets
+ mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
+ mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
+ mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
+ mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
+ mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
+ mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
+ mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
+ mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
+ mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
+ mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
+ mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
+
+ // watch commit action for HOME URL
+ childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
+ childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this);
+ // interrogates controls and updates widgets as required
+ updateMediaPreview();
+ updateCurrentURL();
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ // enable/disable pixel values image entry based on auto scale checkbox
+ if ( mAutoScale->getValue().asBoolean() == false )
+ {
+ childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
+ childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
+ }
+ else
+ {
+ childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
+ childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
+ };
+
+ // enable/disable UI based on type of media
+ bool reset_button_is_active = true;
+ if( mPreviewMedia )
+ {
+ LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
+ if( media_plugin )
+ {
+ // some controls are only appropriate for time or browser type plugins
+ // so we selectively enable/disable them - need to do it in draw
+ // because the information from plugins arrives assynchronously
+ bool show_time_controls = media_plugin->pluginSupportsMediaTime();
+ if ( show_time_controls )
+ {
+ childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
+ reset_button_is_active = false;
+ childSetEnabled( "current_url_label", false );
+ childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
+ }
+ else
+ {
+ childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
+ reset_button_is_active = true;
+ childSetEnabled( "current_url_label", true );
+ childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
+ };
+ };
+ };
+
+ // current URL can change over time.
+// updateCurrentURL();
+
+ LLPermissions perm;
+ bool user_can_press_reset = mMediaEditable;
+
+ // several places modify this widget so we must collect states in one place
+ if ( reset_button_is_active )
+ {
+ // user has perms to press reset button and it is active
+ if ( user_can_press_reset )
+ {
+ childSetEnabled( "current_url_reset_btn", true );
+ }
+ // user does not has perms to press reset button and it is active
+ else
+ {
+ childSetEnabled( "current_url_reset_btn", false );
+ };
+ }
+ else
+ // reset button is inactive so we just slam it to off - other states don't matter
+ {
+ childSetEnabled( "current_url_reset_btn", false );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->mAutoLoop->clear();
+ self->mAutoPlay->clear();
+ self->mAutoScale->clear();
+ self->mAutoZoom ->clear();
+ self->mControls->clear();
+ self->mCurrentURL->clear();
+ self->mFirstClick->clear();
+ self->mHeightPixels->clear();
+ self->mHomeURL->clear();
+ self->mWidthPixels->clear();
+ self->mAutoLoop ->setEnabled(editable);
+ self->mAutoPlay ->setEnabled(editable);
+ self->mAutoScale ->setEnabled(editable);
+ self->mAutoZoom ->setEnabled(editable);
+ self->mControls ->setEnabled(editable);
+ self->mCurrentURL ->setEnabled(editable);
+ self->mFirstClick ->setEnabled(editable);
+ self->mHeightPixels ->setEnabled(editable);
+ self->mHomeURL ->setEnabled(editable);
+ self->mWidthPixels ->setEnabled(editable);
+ self->mPreviewMedia->unloadMediaSource();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->mMediaEditable = editable;
+
+ //llinfos << "---------------" << llendl;
+ //llinfos << ll_pretty_print_sd(media_settings) << llendl;
+ //llinfos << "---------------" << llendl;
+
+ // IF all the faces have media (or all dont have media)
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, self->mMediaEditable);
+ // only show multiple
+ self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, self->mMediaEditable);
+ // only show multiple
+ self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
+ return;
+ }
+
+ }
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" },
+ { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" },
+ { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" },
+ { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" },
+ { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" },
+ { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" },
+ { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLLineEditor" )
+ {
+ static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
+ setText( media_settings[ base_key ].asString() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ else
+ if ( data_set[ i ].ctrl_type == "LLComboBox" )
+ static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
+ setCurrentByIndex( media_settings[ base_key ].asInteger() );
+ else
+ if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
+ static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asInteger() );
+
+ data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable);
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+
+ // interrogates controls and updates widgets as required
+ self->updateMediaPreview();
+ self->updateCurrentURL();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set media control to media URL as required
+void LLPanelMediaSettingsGeneral::updateMediaPreview()
+{
+ if ( mHomeURL->getValue().asString().length() > 0 )
+ {
+ mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
+ }
+ else
+ // new home URL will be empty if media is deleted but
+ // we still need to clean out the preview.
+ {
+ mPreviewMedia->unloadMediaSource();
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set current URL
+void LLPanelMediaSettingsGeneral::updateCurrentURL()
+{
+ if( mCurrentURL->getText().empty() )
+ {
+ childSetText( "current_url", mHomeURL->getText() );
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// virtual
+void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
+{
+ if(mPreviewMedia)
+ {
+ mPreviewMedia->unloadMediaSource();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
+{
+ LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+
+ // check url user is trying to enter for home URL will pass whitelist
+ // and decline to accept it if it doesn't.
+ std::string home_url = self->mHomeURL->getValue().asString();
+ if ( ! self->mParent->passesWhiteList( home_url ) )
+ {
+ LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
+ return;
+ };
+
+ self->updateMediaPreview();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata)
+{
+ LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->navigateHomeSelectedFace();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::apply( void* userdata )
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->mHomeURL->onCommit();
+ // build LLSD Fragment
+ LLSD media_data_general;
+ self->getValues(media_data_general);
+
+ // this merges contents of LLSD passed in with what's there so this is ok
+ LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
+ fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
+ fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
+ fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
+ fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
+ fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
+ fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
+ fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
+ fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
+ fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
+{
+ mParent = parent;
+};
+
+bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace()
+{
+ // HACK: This is directly referencing an impl name. BAD!
+ // This can be removed when we have a truly generic media browser that only
+ // builds an impl based on the type of url it is passed.
+ struct functor_navigate_media : public LLSelectedTEGetFunctor< bool>
+ {
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ {
+ if(object->permModify())
+ {
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
+ if(media_impl)
+ {
+ media_impl->navigateHome();
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ } functor_navigate_media;
+
+ bool all_face_media_navigated = false;
+ LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
+ selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated );
+
+ return all_face_media_navigated;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLPanelMediaSettingsGeneral::getHomeUrl()
+{
+ return mHomeURL->getValue().asString();
+}
+
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h index 1b60909786..e82a31382e 100644 --- a/indra/newview/llpanelmediasettingsgeneral.h +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -64,6 +64,8 @@ public: bool navigateHomeSelectedFace(); void updateMediaPreview(); void updateCurrentURL(); + + const std::string getHomeUrl(); protected: LLFloaterMediaSettings* mParent; @@ -76,7 +78,6 @@ private: LLComboBox* mControls; LLCheckBoxCtrl* mAutoLoop; LLCheckBoxCtrl* mFirstClick; -// LLTextureCtrl* mMediaPreview; LLCheckBoxCtrl* mAutoZoom; LLCheckBoxCtrl* mAutoPlay; LLCheckBoxCtrl* mAutoScale; @@ -84,7 +85,6 @@ private: LLSpinCtrl* mHeightPixels; LLLineEditor* mHomeURL; LLLineEditor* mCurrentURL; - LLCheckBoxCtrl* mAltImageEnable; LLMediaCtrl* mPreviewMedia; }; diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp index cea105d7de..f5607aa287 100644 --- a/indra/newview/llpanelmediasettingssecurity.cpp +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -1,255 +1,343 @@ -/** - * @file llpanelmediasettingssecurity.cpp - * @brief LLPanelMediaSettingsSecurity class implementation - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llfloaterreg.h" -#include "llpanelmediasettingssecurity.h" -#include "llpanelcontents.h" -#include "llcheckboxctrl.h" -#include "llscrolllistctrl.h" -#include "llscrolllistitem.h" -#include "lluictrlfactory.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llsdutil.h" -#include "llselectmgr.h" -#include "llmediaentry.h" -#include "llfloaterwhitelistentry.h" -#include "llfloatermediasettings.h" -//////////////////////////////////////////////////////////////////////////////// -// -LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() -{ - // build dialog from XML - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml"); - mCommitCallbackRegistrar.add("Media.whitelistAdd", boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this)); - mCommitCallbackRegistrar.add("Media.whitelistDelete", boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this)); -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLPanelMediaSettingsSecurity::postBuild() -{ - mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY ); - mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY ); - - childSetAction("whitelist_add", onBtnAdd, this); - childSetAction("whitelist_del", onBtnDel, this); - - setDefaultBtn("whitelist_add"); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLPanelMediaSettingsSecurity::draw() -{ - // housekeeping - LLPanel::draw(); - - // if list is empty, disable DEL button and checkbox to enable use of list - if ( mWhiteListList->isEmpty() ) - { - childSetEnabled( "whitelist_del", false ); - childSetEnabled( LLMediaEntry::WHITELIST_KEY, false ); - childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false ); - } - else - { - childSetEnabled( "whitelist_del", true ); - childSetEnabled( LLMediaEntry::WHITELIST_KEY, true ); - childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true ); - }; - - // if nothing is selected, disable DEL button - if ( mWhiteListList->getSelectedValue().asString().empty() ) - { - childSetEnabled( "whitelist_del", false ); - } - else - { - childSetEnabled( "whitelist_del", true ); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable) -{ - LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; - - if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) - { - if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) - { - self->clearValues(self, editable); - // only show multiple - return; - } - - } - else - { - if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) - { - self->clearValues(self, editable); - // only show multiple - return; - } - - } - std::string base_key( "" ); - std::string tentative_key( "" ); - - struct - { - std::string key_name; - LLUICtrl* ctrl_ptr; - std::string ctrl_type; - - } data_set [] = +/**
+ * @file llpanelmediasettingssecurity.cpp
+ * @brief LLPanelMediaSettingsSecurity class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterreg.h"
+#include "llpanelmediasettingssecurity.h"
+#include "llpanelcontents.h"
+#include "llcheckboxctrl.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llfloaterwhitelistentry.h"
+#include "llfloatermediasettings.h"
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() :
+ mParent( NULL )
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
+ mCommitCallbackRegistrar.add("Media.whitelistAdd", boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
+ mCommitCallbackRegistrar.add("Media.whitelistDelete", boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsSecurity::postBuild()
+{
+ mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
+ mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
+
+ childSetAction("whitelist_add", onBtnAdd, this);
+ childSetAction("whitelist_del", onBtnDel, this);
+
+ setDefaultBtn("whitelist_add");
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ // if list is empty, disable DEL button and checkbox to enable use of list
+ if ( mWhiteListList->isEmpty() )
+ {
+ childSetEnabled( "whitelist_del", false );
+ childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
+ childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
+ }
+ else
+ {
+ childSetEnabled( "whitelist_del", true );
+ childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
+ childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
+ };
+
+ // if nothing is selected, disable DEL button
+ if ( mWhiteListList->getSelectedValue().asString().empty() )
+ {
+ childSetEnabled( "whitelist_del", false );
+ }
+ else
+ {
+ childSetEnabled( "whitelist_del", true );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable)
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" },
+ { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ {
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" )
+ {
+ // get control
+ LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr );
+ list->deleteAllItems();
+
+ // points to list of white list URLs
+ LLSD url_list = media_settings[ base_key ];
+
+ // iterate over them and add to scroll list
+ LLSD::array_iterator iter = url_list.beginArray();
+ while( iter != url_list.endArray() )
+ {
+ // TODO: is iter guaranteed to be valid here?
+ std::string url = *iter;
+ list->addSimpleElement( url );
+ ++iter;
+ };
+ };
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable)
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+ self->mEnableWhiteList->clear();
+ self->mWhiteListList->deleteAllItems();
+ self->mEnableWhiteList->setEnabled(editable);
+ self->mWhiteListList->setEnabled(editable);
+}
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::apply( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ // build LLSD Fragment
+ LLSD media_data_security;
+ self->getValues(media_data_security);
+ // this merges contents of LLSD passed in with what's there so this is ok
+ LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
+
+ // iterate over white list and extract items
+ std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
+ fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
+ while( iter != white_list_items.end() )
+ {
+ std::string white_list_url = (*iter)->getValue().asString();
+ fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
+ ++iter;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Try to make a valid URL if a fragment (
+// white list list box widget and build a list to test against. Can also
+const std::string LLPanelMediaSettingsSecurity::makeValidUrl( const std::string& src_url )
+{
+ // use LLURI to determine if we have a valid scheme
+ LLURI candidate_url( src_url ); + if ( candidate_url.scheme().empty() ) { - { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" }, - { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" }, - { "", NULL , "" } + // build a URL comprised of default scheme and the original fragment
+ const std::string default_scheme( "http://" );
+ return default_scheme + src_url;
}; - for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) - { - base_key = std::string( data_set[ i ].key_name ); - tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); - - // TODO: CP - I bet there is a better way to do this using Boost - if ( media_settings[ base_key ].isDefined() ) - { - if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) - { - static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> - setValue( media_settings[ base_key ].asBoolean() ); - } - else - if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" ) - { - // get control - LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr ); - list->deleteAllItems(); - - // points to list of white list URLs - LLSD url_list = media_settings[ base_key ]; - - // iterate over them and add to scroll list - LLSD::array_iterator iter = url_list.beginArray(); - while( iter != url_list.endArray() ) - { - // TODO: is iter guaranteed to be valid here? - std::string url = *iter; - list->addSimpleElement( url ); - ++iter; - }; - }; - data_set[ i ].ctrl_ptr->setEnabled(editable); - data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); - }; - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable) -{ - LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; - self->mEnableWhiteList->clear(); - self->mWhiteListList->deleteAllItems(); - self->mEnableWhiteList->setEnabled(editable); - self->mWhiteListList->setEnabled(editable); -} -//////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::apply( void* userdata ) -{ - LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; - - // build LLSD Fragment - LLSD media_data_security; - self->getValues(media_data_security); - // this merges contents of LLSD passed in with what's there so this is ok - LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security ); -} - + // we *could* test the "default scheme" + "original fragment" URL again + // using LLURI to see if it's valid but I think the outcome is the same + // in either case - our only option is to return the original URL +
+ // we *think* the original url passed in was valid
+ return src_url;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// wrapper for testing a URL against the whitelist. We grab entries from
+// white list list box widget and build a list to test against. Can also
+// optionally pass the URL that you are trying to add to the widget since
+// it won't be added until this call returns.
+bool LLPanelMediaSettingsSecurity::passesWhiteList( const std::string& added_url,
+ const std::string& test_url )
+{
+ // the checkUrlAgainstWhitelist(..) function works on a vector
+ // of strings for the white list entries - in this panel, the white list
+ // is stored in the widgets themselves so we need to build something compatible.
+ std::vector< std::string > whitelist_strings;
+ whitelist_strings.clear(); // may not be required - I forget what the spec says.
+
+ // step through whitelist widget entries and grab them as strings
+ std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
+ while( iter != white_list_items.end() )
+ {
+ const std::string whitelist_url = (*iter)->getValue().asString();
+ whitelist_strings.push_back( whitelist_url );
+
+ ++iter;
+ };
+
+ // add in the URL that might be added to the whitelist so we can test that too
+ if ( added_url.length() )
+ whitelist_strings.push_back( added_url );
+
+ // possible the URL is just a fragment so we validize it
+ const std::string valid_url = makeValidUrl( test_url );
+
+ // indicate if the URL passes whitelist
+ return LLMediaEntry::checkUrlAgainstWhitelist( valid_url, whitelist_strings );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url)
+{
+ // grab home URL from the general panel (via the parent floater)
+ std::string home_url( "" );
+ if ( mParent )
+ home_url = mParent->getHomeUrl();
+
+ // if the home URL is blank (user hasn't entered it yet) then
+ // don't bother to check if it passes the white list
+ if ( home_url.empty() )
+ {
+ mWhiteListList->addSimpleElement( url );
+ return;
+ };
+
+ // if the URL passes the white list, add it
+ if ( passesWhiteList( url, home_url ) )
+ {
+ mWhiteListList->addSimpleElement( url );
+ }
+ else
+ // display a message indicating you can't do that
+ {
+ LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
+{
+ LLFloaterReg::showInstance("whitelist_entry");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ self->mWhiteListList->deleteSelectedItems();
+}
+
//////////////////////////////////////////////////////////////////////////////// // -void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in ) -{ - fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue(); - - // iterate over white list and extract items - std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData(); - std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin(); - fill_me_in[LLMediaEntry::WHITELIST_KEY].clear(); - while( iter != white_list_items.end() ) - { - std::string white_list_url = (*iter)->getValue().asString(); - fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url ); - ++iter; - }; -} - - -/////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url) -{ - mWhiteListList->addSimpleElement( url ); -} - -/////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata ) -{ - LLFloaterReg::showInstance("whitelist_entry"); -} - -/////////////////////////////////////////////////////////////////////////////// -// static -void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata ) +void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent ) { - LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; + mParent = parent; +}; - self->mWhiteListList->deleteSelectedItems(); -} diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h index b7cf67c039..b78ee92193 100644 --- a/indra/newview/llpanelmediasettingssecurity.h +++ b/indra/newview/llpanelmediasettingssecurity.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl; class LLScrollListCtrl; +class LLFloaterMediaSettings; class LLPanelMediaSettingsSecurity : public LLPanel { @@ -52,6 +53,12 @@ class LLPanelMediaSettingsSecurity : public LLPanel static void initValues( void* userdata, const LLSD& media_settings,bool editable ); static void clearValues( void* userdata, bool editable); void addWhiteListItem(const std::string& url); + void setParent( LLFloaterMediaSettings* parent ); + const std::string makeValidUrl( const std::string& src_url ); + bool passesWhiteList( const std::string& added_url, const std::string& test_url );
+ + protected: + LLFloaterMediaSettings* mParent; private: LLCheckBoxCtrl* mEnableWhiteList; diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index c6840721a3..61e18195b8 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -58,6 +58,7 @@ //#include "llviewermenu.h" // create_landmark() #include "llweb.h" #include "llsdutil.h" +#include "llsdutil_math.h" LLPanelPlace::LLPanelPlace() : LLPanel(), diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 609b205920..cb9f7184f0 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -67,6 +67,7 @@ #include "llviewerregion.h" #include "llviewertexteditor.h" #include "llworldmap.h" +#include "llsdutil_math.h" //---------------------------------------------------------------------------- // Aux types and methods diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index a7f0ce16d3..d68897b64f 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -4905,7 +4905,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) { inspect_item_id = inspect_instance->getSelectedUUID(); } - LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID(); for (S32 pass = 0; pass < 2; pass++) { for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); @@ -4919,11 +4918,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) { continue; } - if (objectp->getID() == focus_item_id) - { - node->renderOneSilhouette(gFocusMgr.getFocusColor()); - } - else if(objectp->getID() == inspect_item_id) + if(objectp->getID() == inspect_item_id) { node->renderOneSilhouette(sHighlightInspectColor); } @@ -4977,6 +4972,19 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } } +#if 0 + // Hilight focused media object + { + LLViewerObject* objectp = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if(objectp) + { + // FIXME: how do I construct a silhouette for an object that's not selected? + // Would we need to add another LLObjectSelectionHandle for this purpose? + node->renderOneSilhouette(gFocusMgr.getFocusColor()); + } + } +#endif + if (for_hud && avatar) { glMatrixMode(GL_PROJECTION); diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 329d7d26ee..a11ee05532 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -111,12 +111,72 @@ bool LLSideTray::instanceCreated () return sInstance!=0; } -LLSideTrayTab::LLSideTrayTab(const Params& params):mMainPanel(0) +////////////////////////////////////////////////////////////////////////////// +// LLSideTrayTab +// Represents a single tab in the side tray, only used by LLSideTray +////////////////////////////////////////////////////////////////////////////// + +class LLSideTrayTab: public LLPanel { - mImagePath = params.image_path; - mTabTitle = params.tab_title; - mDescription = params.description; + friend class LLUICtrlFactory; + friend class LLSideTray; +public: + + struct Params + : public LLInitParam::Block<Params, LLPanel::Params> + { + // image name + Optional<std::string> image; + Optional<std::string> image_selected; + Optional<std::string> tab_title; + Optional<std::string> description; + Params() + : image("image"), + image_selected("image_selected"), + tab_title("tab_title","no title"), + description("description","no description") + {}; + }; +protected: + LLSideTrayTab(const Params& params); + + +public: + virtual ~LLSideTrayTab(); + + /*virtual*/ BOOL postBuild (); + /*virtual*/ bool addChild (LLView* view, S32 tab_group); + + + void arrange (S32 width, S32 height); + void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); + + static LLSideTrayTab* createInstance (); + + const std::string& getDescription () const { return mDescription;} + const std::string& getTabTitle() const { return mTabTitle;} + + void draw(); + + void onOpen (const LLSD& key); + +private: + std::string mTabTitle; + std::string mImage; + std::string mImageSelected; + std::string mDescription; + + LLView* mMainPanel; +}; +LLSideTrayTab::LLSideTrayTab(const Params& p) +: LLPanel(), + mTabTitle(p.tab_title), + mImage(p.image), + mImageSelected(p.image_selected), + mDescription(p.description), + mMainPanel(NULL) +{ // Necessary for focus movement among child controls setFocusRoot(TRUE); } @@ -221,6 +281,18 @@ LLSideTrayTab* LLSideTrayTab::createInstance () return tab; } +////////////////////////////////////////////////////////////////////////////// +// LLSideTray +////////////////////////////////////////////////////////////////////////////// + +LLSideTray::Params::Params() +: collapsed("collapsed",false), + tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"), + tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"), + default_button_width("tab_btn_width",32), + default_button_height("tab_btn_height",32), + default_button_margin("tab_btn_margin",0) +{} //virtual LLSideTray::LLSideTray(Params& params) @@ -255,35 +327,6 @@ BOOL LLSideTray::postBuild() setMouseOpaque(false); return true; } - -/** - * add new panel to tab with tab_name name - * @param tab_name - name of sidebar tab to add new panel - * @param panel - pointer to panel - */ -bool LLSideTray::addPanel ( const std::string& tab_name - ,LLPanel* panel ) -{ - return false; -} -/** - * Add new tab to side bar - * @param tab_name - name of the new tab - * @param image - image for new sidebar button - * @param title - title for new tab - */ -bool LLSideTray::addTab ( const std::string& tab_name - ,const std::string& image - ,const std::string& title) -{ - LLSideTrayTab::Params params; - params.image_path = image; - params.tab_title = title; - LLSideTrayTab* tab = LLUICtrlFactory::create<LLSideTrayTab> (params); - addChild(tab,1); - return true; -} - LLSideTrayTab* LLSideTray::getTab(const std::string& name) { @@ -291,15 +334,19 @@ LLSideTrayTab* LLSideTray::getTab(const std::string& name) } - -void LLSideTray::toggleTabButton (LLSideTrayTab* tab) +void LLSideTray::toggleTabButton(LLSideTrayTab* tab) { if(tab == NULL) return; - string name = tab->getName(); - std::map<std::string,LLButton*>::iterator tIt = mTabButtons.find(name); - if(tIt!=mTabButtons.end()) - tIt->second->setToggleState(!tIt->second->getToggleState()); + std::string name = tab->getName(); + std::map<std::string,LLButton*>::iterator it = mTabButtons.find(name); + if(it != mTabButtons.end()) + { + LLButton* btn = it->second; + bool new_state = !btn->getToggleState(); + btn->setToggleState(new_state); + btn->setImageOverlay( new_state ? tab->mImageSelected : tab->mImage ); + } } bool LLSideTray::selectTabByIndex(size_t index) @@ -307,9 +354,7 @@ bool LLSideTray::selectTabByIndex(size_t index) if(index>=mTabs.size()) return false; - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(mTabs[index]); - if(sidebar_tab == NULL) - return false; + LLSideTrayTab* sidebar_tab = mTabs[index]; return selectTabByName(sidebar_tab->getName()); } @@ -338,9 +383,7 @@ bool LLSideTray::selectTabByName (const std::string& name) child_vector_const_iter_t child_it; for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; + LLSideTrayTab* sidebar_tab = *child_it; sidebar_tab->setVisible(sidebar_tab == mActiveTab); } return true; @@ -393,25 +436,28 @@ bool LLSideTray::addChild(LLView* view, S32 tab_group) void LLSideTray::createButtons () { - //create show/hide button - mCollapseButton = createButton(EXPANDED_NAME,"",boost::bind(&LLSideTray::onToggleCollapse, this)); - //create buttons for tabs child_vector_const_iter_t child_it = mTabs.begin(); - ++child_it; - for ( ; child_it != mTabs.end(); ++child_it) { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; + LLSideTrayTab* sidebar_tab = *child_it; - string name = sidebar_tab->getName(); + std::string name = sidebar_tab->getName(); - LLButton* button = createButton("",sidebar_tab->mImagePath,boost::bind(&LLSideTray::onTabButtonClick, this, sidebar_tab->getName())); - mTabButtons[sidebar_tab->getName()] = button; + // The "home" button will open/close the whole panel, this will need to + // change if the home screen becomes its own tab. + if (name == "sidebar_home") + { + mCollapseButton = createButton("",sidebar_tab->mImage, + boost::bind(&LLSideTray::onToggleCollapse, this)); + } + else + { + LLButton* button = createButton("",sidebar_tab->mImage, + boost::bind(&LLSideTray::onTabButtonClick, this, name)); + mTabButtons[name] = button; + } } - } void LLSideTray::onTabButtonClick(string name) @@ -480,9 +526,7 @@ void LLSideTray::arrange () int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2; for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; + LLSideTrayTab* sidebar_tab = *child_it; ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset ,sidetray_params.default_button_width @@ -505,34 +549,56 @@ void LLSideTray::arrange () //arrange tabs for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; - + LLSideTrayTab* sidebar_tab = *child_it; sidebar_tab->setRect(ctrl_rect); sidebar_tab->arrange(mMaxBarWidth,getRect().getHeight()); } } -void LLSideTray::collapseSideBar () +void LLSideTray::collapseSideBar() { mCollapsed = true; - mCollapseButton->setLabel(COLLAPSED_NAME); + // Reset all overlay images, because there is no "selected" tab when the + // whole side tray is hidden. + child_vector_const_iter_t it = mTabs.begin(); + for ( ; it != mTabs.end(); ++it ) + { + LLSideTrayTab* tab = *it; + std::string name = tab->getName(); + std::map<std::string,LLButton*>::const_iterator btn_it = + mTabButtons.find(name); + if (btn_it != mTabButtons.end()) + { + LLButton* btn = btn_it->second; + btn->setImageOverlay( tab->mImage ); + } + } + + // Home tab doesn't put its button in mTabButtons + LLSideTrayTab* home_tab = getTab("sidebar_home"); + if (home_tab) + { + mCollapseButton->setImageOverlay( home_tab->mImage ); + } mActiveTab->setVisible(FALSE); reflectCollapseChange(); setFocus( FALSE ); } -void LLSideTray::expandSideBar () + +void LLSideTray::expandSideBar() { mCollapsed = false; - mCollapseButton->setLabel(EXPANDED_NAME); + LLSideTrayTab* home_tab = getTab("sidebar_home"); + if (home_tab) + { + mCollapseButton->setImageOverlay( home_tab->mImageSelected ); + } LLSD key;//empty mActiveTab->onOpen(key); mActiveTab->setVisible(TRUE); reflectCollapseChange(); - } void LLSideTray::highlightFocused() @@ -588,9 +654,7 @@ void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent) int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2; for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; + LLSideTrayTab* sidebar_tab = *child_it; ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset ,sidetray_params.default_button_width @@ -612,9 +676,7 @@ void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent) for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; + LLSideTrayTab* sidebar_tab = *child_it; sidebar_tab->reshape(mMaxBarWidth,getRect().getHeight()); ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight()); sidebar_tab->setRect(ctrl_rect); diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 6ea6bafac9..b49251ec79 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -36,59 +36,9 @@ #include "llpanel.h" #include "string" -class LLSideTray; +class LLSideTrayTab; class LLAccordionCtrl; -class LLSideTrayTab: public LLPanel -{ - friend class LLUICtrlFactory; - friend class LLSideTray; -public: - - struct Params - : public LLInitParam::Block<Params, LLPanel::Params> - { - // image name - Optional<std::string> image_path; - Optional<std::string> tab_title; - Optional<std::string> description; - Params() - : image_path("image"), - tab_title("tab_title","no title"), - description("description","no description") - {}; - }; -protected: - LLSideTrayTab(const Params& params); - - -public: - virtual ~LLSideTrayTab(); - - /*virtual*/ BOOL postBuild (); - /*virtual*/ bool addChild (LLView* view, S32 tab_group); - - - void arrange (S32 width, S32 height); - void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); - - static LLSideTrayTab* createInstance (); - - const std::string& getDescription () const { return mDescription;} - const std::string& getTabTitle() const { return mTabTitle;} - - void draw(); - - void onOpen (const LLSD& key); - -private: - std::string mTabTitle; - std::string mImagePath; - std::string mDescription; - - LLView* mMainPanel; -}; - // added inheritance from LLDestroyClass<LLSideTray> to enable Side Tray perform necessary actions // while disconnecting viewer in LLAppViewer::disconnectViewer(). // LLDestroyClassList::instance().fireCallbacks() calls destroyClass method. See EXT-245. @@ -112,21 +62,14 @@ public: Optional<S32> default_button_height; Optional<S32> default_button_margin; - Params() - : collapsed("collapsed",false), - tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"), - tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"), - default_button_width("tab_btn_width",32), - default_button_height("tab_btn_height",32), - default_button_margin("tab_btn_margin",0) - {}; + Params(); }; static LLSideTray* getInstance (); static bool instanceCreated (); protected: LLSideTray(Params& params); - typedef std::vector<LLView*> child_vector_t; + typedef std::vector<LLSideTrayTab*> child_vector_t; typedef child_vector_t::iterator child_vector_iter_t; typedef child_vector_t::const_iterator child_vector_const_iter_t; typedef child_vector_t::reverse_iterator child_vector_reverse_iter_t; @@ -146,23 +89,6 @@ public: */ bool selectTabByIndex(size_t index); - /** - * add new panel to tab with tab_name name - * @param tab_name - name of sidebar tab to add new panel - * @param panel - pointer to panel - */ - bool addPanel ( const std::string& tab_name - ,LLPanel* panel ); - /** - * Add new tab to side bar - * @param tab_name - name of the new tab - * @param image - image for new sidebar button - * @param title - title for new tab - */ - bool addTab ( const std::string& tab_name - ,const std::string& image - ,const std::string& title); - /** * Activate tab with "panel_name" panel * if no such tab - return NULL, otherwise a pointer to the panel diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8793d22646..43b039f94e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -56,7 +56,6 @@ #include "llcachename.h" #include "lldir.h" #include "llerrorcontrol.h" -#include "llfiltersd2xmlrpc.h" #include "llfloaterreg.h" #include "llfocusmgr.h" #include "llhttpsender.h" @@ -66,10 +65,11 @@ #include "llmemorystream.h" #include "llmessageconfig.h" #include "llmoveview.h" +#include "llteleporthistory.h" #include "llregionhandle.h" #include "llsd.h" #include "llsdserialize.h" -#include "llsdutil.h" +#include "llsdutil_math.h" #include "llsecondlifeurls.h" #include "llstring.h" #include "lluserrelations.h" @@ -103,7 +103,6 @@ #include "llfloaterland.h" #include "llfloaterpreference.h" #include "llfloatertopobjects.h" -#include "llfloatertos.h" #include "llfloaterworldmap.h" #include "llgesturemgr.h" #include "llgroupmgr.h" @@ -116,6 +115,7 @@ #include "llfriendcard.h" #include "llkeyboard.h" #include "llloginhandler.h" // gLoginHandler, SLURL support +#include "lllogininstance.h" // Host the login module. #include "llpanellogin.h" #include "llmutelist.h" #include "llnotify.h" @@ -133,7 +133,6 @@ #include "llsecondlifeurls.h" #include "llselectmgr.h" #include "llsky.h" -#include "llsrv.h" #include "llstatview.h" #include "lltrans.h" #include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance @@ -146,7 +145,6 @@ #include "llurlsimstring.h" #include "llurlhistory.h" #include "llurlwhitelist.h" -#include "lluserauth.h" #include "llvieweraudio.h" #include "llviewerassetstorage.h" #include "llviewercamera.h" @@ -190,6 +188,9 @@ #include "llappearancemgr.h" #include "llavatariconctrl.h" +#include "lllogin.h" +#include "llevents.h" + #if LL_WINDOWS #include "llwindebug.h" #include "lldxhardware.h" @@ -203,12 +204,12 @@ // exported globals // bool gAgentMovementCompleted = false; -std::string gInitialOutfit; -std::string gInitialOutfitGender; std::string SCREEN_HOME_FILENAME = "screen_home.bmp"; std::string SCREEN_LAST_FILENAME = "screen_last.bmp"; +LLPointer<LLViewerTexture> gStartTexture; + // // Imported globals // @@ -218,12 +219,6 @@ extern S32 gStartImageHeight; // // local globals // - -LLPointer<LLViewerTexture> gStartTexture; - -static LLHost gAgentSimHost; -static BOOL gSkipOptionalUpdate = FALSE; - static bool gGotUseCircuitCodeAck = false; static std::string sInitialOutfit; static std::string sInitialOutfitGender; // "male" or "female" @@ -232,6 +227,18 @@ static bool gUseCircuitCallbackCalled = false; EStartupState LLStartUp::gStartupState = STATE_FIRST; +// *NOTE:Mani - to reconcile with giab changes... +static std::string gFirstname; +static std::string gLastname; +static std::string gPassword; + +static U64 gFirstSimHandle = 0; +static LLHost gFirstSim; +static std::string gFirstSimSeedCap; +static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f); +static std::string gAgentStartLocation = "safe"; + +static LLEventStream sStartupStateWatcher("StartupState"); // // local function declaration @@ -244,8 +251,6 @@ void show_first_run_dialog(); bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); bool login_alert_status(const LLSD& notification, const LLSD& response); -void update_app(BOOL mandatory, const std::string& message); -bool update_dialog_callback(const LLSD& notification, const LLSD& response); void login_packet_failed(void**, S32 result); void use_circuit_callback(void**, S32 result); void register_viewer_callbacks(LLMessageSystem* msg); @@ -255,6 +260,8 @@ void init_start_screen(S32 location_id); void release_start_screen(); void reset_login(); void apply_udp_blacklist(const std::string& csv); +bool process_login_success_response(); +void transition_back_to_login_panel(const std::string& emsg); void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group) { @@ -314,9 +321,6 @@ void update_texture_fetch() gTextureList.updateImages(0.10f); } -static std::vector<std::string> sAuthUris; -static S32 sAuthUriNum = -1; - //Copies landmarks from the "Library" to "My Favorites" void populate_favorites_bar() { @@ -388,23 +392,11 @@ bool idle_startup() // auth/transform loop will do. static F32 progress = 0.10f; - static std::string auth_method; static std::string auth_desc; static std::string auth_message; - static std::string firstname; - static std::string lastname; - static LLUUID web_login_key; - static std::string password; - static std::vector<const char*> requested_options; - - static U64 first_sim_handle = 0; - static LLHost first_sim; - static std::string first_sim_seed_cap; static LLVector3 initial_sun_direction(1.f, 0.f, 0.f); static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server - static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f); - static std::string agent_start_location = "safe"; // last location by default static S32 agent_location_id = START_LOCATION_ID_LAST; @@ -412,7 +404,7 @@ bool idle_startup() static bool show_connect_box = true; - static bool stipend_since_login = false; + //static bool stipend_since_login = false; // HACK: These are things from the main loop that usually aren't done // until initialization is complete, but need to be done here for things @@ -433,12 +425,7 @@ bool idle_startup() LLStringUtil::setLocale (LLTrans::getString(system)); - if (gNoRender) - { - // HACK, skip optional updates if you're running drones - gSkipOptionalUpdate = TRUE; - } - else + if (!gNoRender) { //note: Removing this line will cause incorrect button size in the login screen. -- bao. gTextureList.updateImages(0.01f) ; @@ -754,24 +741,23 @@ bool idle_startup() || !gLoginHandler.getWebLoginKey().isNull() ) { // We have at least some login information on a SLURL - firstname = gLoginHandler.getFirstName(); - lastname = gLoginHandler.getLastName(); - web_login_key = gLoginHandler.getWebLoginKey(); + gFirstname = gLoginHandler.getFirstName(); + gLastname = gLoginHandler.getLastName(); // Show the login screen if we don't have everything show_connect_box = - firstname.empty() || lastname.empty() || web_login_key.isNull(); + gFirstname.empty() || gLastname.empty(); } else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3) { LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); - firstname = cmd_line_login[0].asString(); - lastname = cmd_line_login[1].asString(); + gFirstname = cmd_line_login[0].asString(); + gLastname = cmd_line_login[1].asString(); LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); char md5pass[33]; /* Flawfinder: ignore */ pass.hex_digest(md5pass); - password = md5pass; + gPassword = md5pass; #ifdef USE_VIEWER_AUTH show_connect_box = true; @@ -782,9 +768,9 @@ bool idle_startup() } else if (gSavedSettings.getBOOL("AutoLogin")) { - firstname = gSavedSettings.getString("FirstName"); - lastname = gSavedSettings.getString("LastName"); - password = LLStartUp::loadPasswordFromDisk(); + gFirstname = gSavedSettings.getString("FirstName"); + gLastname = gSavedSettings.getString("LastName"); + gPassword = LLStartUp::loadPasswordFromDisk(); gSavedSettings.setBOOL("RememberPassword", TRUE); #ifdef USE_VIEWER_AUTH @@ -797,9 +783,9 @@ bool idle_startup() { // if not automatically logging in, display login dialog // a valid grid is selected - firstname = gSavedSettings.getString("FirstName"); - lastname = gSavedSettings.getString("LastName"); - password = LLStartUp::loadPasswordFromDisk(); + gFirstname = gSavedSettings.getString("FirstName"); + gLastname = gSavedSettings.getString("LastName"); + gPassword = LLStartUp::loadPasswordFromDisk(); show_connect_box = true; } @@ -835,7 +821,7 @@ bool idle_startup() // Load all the name information out of the login view // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't // show the login view until login_show() is called below. - // LLPanelLogin::getFields(firstname, lastname, password); + // LLPanelLogin::getFields(gFirstname, gLastname, gPassword); if (gNoRender) { @@ -847,7 +833,7 @@ bool idle_startup() // Show the login dialog login_show(); // connect dialog is already shown, so fill in the names - LLPanelLogin::setFields( firstname, lastname, password); + LLPanelLogin::setFields( gFirstname, gLastname, gPassword); LLPanelLogin::giveFocus(); @@ -911,34 +897,34 @@ bool idle_startup() //reset the values that could have come in from a slurl if (!gLoginHandler.getWebLoginKey().isNull()) { - firstname = gLoginHandler.getFirstName(); - lastname = gLoginHandler.getLastName(); - web_login_key = gLoginHandler.getWebLoginKey(); + gFirstname = gLoginHandler.getFirstName(); + gLastname = gLoginHandler.getLastName(); +// gWebLoginKey = gLoginHandler.getWebLoginKey(); } if (show_connect_box) { // TODO if not use viewer auth // Load all the name information out of the login view - LLPanelLogin::getFields(&firstname, &lastname, &password); + LLPanelLogin::getFields(&gFirstname, &gLastname, &gPassword); // end TODO // HACK: Try to make not jump on login gKeyboard->resetKeys(); } - if (!firstname.empty() && !lastname.empty()) + if (!gFirstname.empty() && !gLastname.empty()) { - gSavedSettings.setString("FirstName", firstname); - gSavedSettings.setString("LastName", lastname); + gSavedSettings.setString("FirstName", gFirstname); + gSavedSettings.setString("LastName", gLastname); - LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL; - gDebugInfo["LoginName"] = firstname + " " + lastname; + LL_INFOS("AppInit") << "Attempting login as: " << gFirstname << " " << gLastname << LL_ENDL; + gDebugInfo["LoginName"] = gFirstname + " " + gLastname; } // create necessary directories // *FIX: these mkdir's should error check - gDirUtilp->setLindenUserDir(firstname, lastname); + gDirUtilp->setLindenUserDir(gFirstname, gLastname); LLFile::mkdir(gDirUtilp->getLindenUserDir()); // Set PerAccountSettingsFile to the default value. @@ -972,7 +958,7 @@ bool idle_startup() gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath")); } - gDirUtilp->setPerAccountChatLogsDir(firstname, lastname); + gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname); LLFile::mkdir(gDirUtilp->getChatLogsDir()); LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); @@ -1000,13 +986,6 @@ bool idle_startup() if (show_connect_box) { - if ( LLPanelLogin::isGridComboDirty() ) - { - // User picked a grid from the popup, so clear the - // stored uris and they will be reacquired from the grid choice. - sAuthUris.clear(); - } - std::string location; LLPanelLogin::getLocation( location ); LLURLSimString::setString( location ); @@ -1038,7 +1017,7 @@ bool idle_startup() agent_location_id = START_LOCATION_ID_URL; // doesn't really matter what location_which is, since - // agent_start_look_at will be overwritten when the + // gAgentStartLookAt will be overwritten when the // UserLoginLocationReply arrives location_which = START_LOCATION_ID_LAST; } @@ -1071,616 +1050,138 @@ bool idle_startup() gVFS->pokeFiles(); - // skipping over STATE_UPDATE_CHECK because that just waits for input LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); return FALSE; } - if (STATE_UPDATE_CHECK == LLStartUp::getStartupState()) - { - // wait for user to give input via dialog box - return FALSE; - } - if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState()) { -//#define LL_MINIMIAL_REQUESTED_OPTIONS gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); - // *Note: this is where gUserAuth used to be created. - requested_options.clear(); - requested_options.push_back("inventory-root"); - requested_options.push_back("inventory-skeleton"); - //requested_options.push_back("inventory-meat"); - //requested_options.push_back("inventory-skel-targets"); -#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS) - if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary")) - { - requested_options.push_back("inventory-lib-root"); - requested_options.push_back("inventory-lib-owner"); - requested_options.push_back("inventory-skel-lib"); - // requested_options.push_back("inventory-meat-lib"); - } - - requested_options.push_back("initial-outfit"); - requested_options.push_back("gestures"); - requested_options.push_back("event_categories"); - requested_options.push_back("event_notifications"); - requested_options.push_back("classified_categories"); - requested_options.push_back("adult_compliant"); - //requested_options.push_back("inventory-targets"); - requested_options.push_back("buddy-list"); - requested_options.push_back("ui-config"); -#endif - requested_options.push_back("tutorial_setting"); - requested_options.push_back("login-flags"); - requested_options.push_back("global-textures"); - if(gSavedSettings.getBOOL("ConnectAsGod")) - { - gSavedSettings.setBOOL("UseDebugMenus", TRUE); - requested_options.push_back("god-connect"); - } - std::vector<std::string> uris; - LLViewerLogin::getInstance()->getLoginURIs(uris); - std::vector<std::string>::const_iterator iter, end; - for (iter = uris.begin(), end = uris.end(); iter != end; ++iter) - { - std::vector<std::string> rewritten; - rewritten = LLSRV::rewriteURI(*iter); - sAuthUris.insert(sAuthUris.end(), - rewritten.begin(), rewritten.end()); - } - sAuthUriNum = 0; - auth_method = "login_to_simulator"; - + // Update progress status and the display loop. auth_desc = LLTrans::getString("LoginInProgress"); - LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - } - - if (STATE_LOGIN_AUTHENTICATE == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_LOGIN_AUTHENTICATE" << LL_ENDL; set_startup_status(progress, auth_desc, auth_message); progress += 0.02f; display_startup(); - - std::stringstream start; - if (LLURLSimString::parse()) - { - // a startup URL was specified - std::stringstream unescaped_start; - unescaped_start << "uri:" - << LLURLSimString::sInstance.mSimName << "&" - << LLURLSimString::sInstance.mX << "&" - << LLURLSimString::sInstance.mY << "&" - << LLURLSimString::sInstance.mZ; - start << xml_escape_string(unescaped_start.str()); - - } - else - { - start << gSavedSettings.getString("LoginLocation"); - } - - char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ - LLMD5 hashed_mac; - hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); - hashed_mac.finalize(); - hashed_mac.hex_digest(hashed_mac_string); - - // TODO if statement here to use web_login_key - sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1); - LLUserAuth::getInstance()->authenticate( - sAuthUris[sAuthUriNum], - auth_method, - firstname, - lastname, - password, // web_login_key, - start.str(), - gSkipOptionalUpdate, - gAcceptTOS, - gAcceptCriticalMessage, - gLastExecEvent, - requested_options, - hashed_mac_string, - LLAppViewer::instance()->getSerialNumber()); - - // reset globals - gAcceptTOS = FALSE; - gAcceptCriticalMessage = FALSE; - LLStartUp::setStartupState( STATE_LOGIN_NO_DATA_YET ); - return FALSE; - } - if(STATE_LOGIN_NO_DATA_YET == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_LOGIN_NO_DATA_YET" << LL_ENDL; - // If we get here we have gotten past the potential stall - // in curl, so take "may appear frozen" out of progress bar. JC - auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); - set_startup_status(progress, auth_desc, auth_message); - // Process messages to keep from dropping circuit. - LLMessageSystem* msg = gMessageSystem; - while (msg->checkAllMessages(gFrameCount, gServicePump)) - { - } - msg->processAcks(); - LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse(); - if(LLUserAuth::E_NO_RESPONSE_YET == error) + // Setting initial values... + LLLoginInstance* login = LLLoginInstance::getInstance(); + login->setNotificationsInterface(LLNotifications::getInstance()); + if(gNoRender) { - LL_DEBUGS("AppInit") << "waiting..." << LL_ENDL; - return FALSE; + // HACK, skip optional updates if you're running drones + login->setSkipOptionalUpdate(true); } - LLStartUp::setStartupState( STATE_LOGIN_DOWNLOADING ); - progress += 0.01f; - set_startup_status(progress, auth_desc, auth_message); - return FALSE; - } - if(STATE_LOGIN_DOWNLOADING == LLStartUp::getStartupState()) - { - LL_DEBUGS("AppInit") << "STATE_LOGIN_DOWNLOADING" << LL_ENDL; - // Process messages to keep from dropping circuit. - LLMessageSystem* msg = gMessageSystem; - while (msg->checkAllMessages(gFrameCount, gServicePump)) - { - } - msg->processAcks(); - LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse(); - if(LLUserAuth::E_DOWNLOADING == error) - { - LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL; - return FALSE; - } + login->setUserInteraction(show_connect_box); + login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); + login->setLastExecEvent(gLastExecEvent); + login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance())); + + // This call to LLLoginInstance::connect() starts the + // authentication process. + LLSD credentials; + credentials["first"] = gFirstname; + credentials["last"] = gLastname; + credentials["passwd"] = gPassword; + login->connect(credentials); + LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); - progress += 0.01f; - set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message); return FALSE; } - if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) + if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) { - LL_DEBUGS("AppInit") << "STATE_LOGIN_PROCESS_RESPONSE" << LL_ENDL; std::ostringstream emsg; - bool quit = false; - bool update = false; - std::string login_response; - std::string reason_response; - std::string message_response; - bool successful_login = false; - LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse(); - // reset globals - gAcceptTOS = FALSE; - gAcceptCriticalMessage = FALSE; - switch(error) - { - case LLUserAuth::E_OK: - login_response = LLUserAuth::getInstance()->getResponse("login"); - if(login_response == "true") - { - // Yay, login! - successful_login = true; - } - else if(login_response == "indeterminate") + emsg << "Login failed.\n"; + if(LLLoginInstance::getInstance()->authFailure()) + { + LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): " + << LLLoginInstance::getInstance()->getResponse() << LL_ENDL; + // Still have error conditions that may need some + // sort of handling. + std::string reason_response = LLLoginInstance::getInstance()->getResponse("reason"); + std::string message_response = LLLoginInstance::getInstance()->getResponse("message"); + + if(!message_response.empty()) { - LL_INFOS("AppInit") << "Indeterminate login..." << LL_ENDL; - sAuthUris = LLSRV::rewriteURI(LLUserAuth::getInstance()->getResponse("next_url")); - sAuthUriNum = 0; - auth_method = LLUserAuth::getInstance()->getResponse("next_method"); - auth_message = LLUserAuth::getInstance()->getResponse("message"); - if(auth_method.substr(0, 5) == "login") + // XUI: fix translation for strings returned during login + // We need a generic table for translations + std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ]; + if ( big_reason.size() == 0 ) { - auth_desc.assign(LLTrans::getString("LoginAuthenticating")); + emsg << message_response; } else { - auth_desc.assign(LLTrans::getString("LoginMaintenance")); + emsg << big_reason; } - // ignoring the duration & options array for now. - // Go back to authenticate. - LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - return FALSE; - } - else - { - emsg << "Login failed.\n"; - reason_response = LLUserAuth::getInstance()->getResponse("reason"); - message_response = LLUserAuth::getInstance()->getResponse("message"); - - if (!message_response.empty()) - { - // XUI: fix translation for strings returned during login - // We need a generic table for translations - std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ]; - if ( big_reason.size() == 0 ) - { - emsg << message_response; - } - else - { - emsg << big_reason; - } - } - - if(reason_response == "tos") - { - if (show_connect_box) - { - LL_DEBUGS("AppInit") << "Need tos agreement" << LL_ENDL; - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - LLFloaterReg::showInstance("message_tos", LLSD(message_response)); - // LLFloaterTOS deletes itself. - return false; - } - else - { - quit = true; - } - } - if(reason_response == "critical") - { - if (show_connect_box) - { - LL_DEBUGS("AppInit") << "Need critical message" << LL_ENDL; - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - LLFloaterReg::showInstance("message_critical", LLSD(message_response)); - // LLFloaterTOS deletes itself. - return false; - } - else - { - quit = true; - } - } - if(reason_response == "key") - { - // Couldn't login because user/password is wrong - // Clear the password - password = ""; - } - if(reason_response == "update") - { - auth_message = LLUserAuth::getInstance()->getResponse("message"); - update = true; - } - if(reason_response == "optional") - { - LL_DEBUGS("AppInit") << "Login got optional update" << LL_ENDL; - auth_message = LLUserAuth::getInstance()->getResponse("message"); - if (show_connect_box) - { - update_app(FALSE, auth_message); - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - gSkipOptionalUpdate = TRUE; - return false; - } - } - } - break; - case LLUserAuth::E_COULDNT_RESOLVE_HOST: - case LLUserAuth::E_SSL_PEER_CERTIFICATE: - case LLUserAuth::E_UNHANDLED_ERROR: - case LLUserAuth::E_SSL_CACERT: - case LLUserAuth::E_SSL_CONNECT_ERROR: - default: - if (sAuthUriNum >= (int) sAuthUris.size() - 1) - { - emsg << "Unable to connect to " << LLAppViewer::instance()->getSecondLifeTitle() << ".\n"; - emsg << LLUserAuth::getInstance()->errorMessage(); - } else { - sAuthUriNum++; - std::ostringstream s; - LLStringUtil::format_map_t args; - args["[NUMBER]"] = llformat("%d", sAuthUriNum + 1); - auth_desc = LLTrans::getString("LoginAttempt", args); - LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE ); - return FALSE; - } - break; - } - - if (update || gSavedSettings.getBOOL("ForceMandatoryUpdate")) - { - gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE); - update_app(TRUE, auth_message); - LLStartUp::setStartupState( STATE_UPDATE_CHECK ); - return false; - } - - // Version update and we're not showing the dialog - if(quit) - { - LLUserAuth::getInstance()->reset(); - LLAppViewer::instance()->forceQuit(); - return false; - } - - if(successful_login) - { - std::string text; - text = LLUserAuth::getInstance()->getResponse("udp_blacklist"); - if(!text.empty()) - { - apply_udp_blacklist(text); } - // unpack login data needed by the application - text = LLUserAuth::getInstance()->getResponse("agent_id"); - if(!text.empty()) gAgentID.set(text); - gDebugInfo["AgentID"] = text; - - text = LLUserAuth::getInstance()->getResponse("session_id"); - if(!text.empty()) gAgentSessionID.set(text); - gDebugInfo["SessionID"] = text; - - text = LLUserAuth::getInstance()->getResponse("secure_session_id"); - if(!text.empty()) gAgent.mSecureSessionID.set(text); - - text = LLUserAuth::getInstance()->getResponse("first_name"); - if(!text.empty()) + if(reason_response == "key") { - // Remove quotes from string. Login.cgi sends these to force - // names that look like numbers into strings. - firstname.assign(text); - LLStringUtil::replaceChar(firstname, '"', ' '); - LLStringUtil::trim(firstname); + // Couldn't login because user/password is wrong + // Clear the password + gPassword = ""; } - text = LLUserAuth::getInstance()->getResponse("last_name"); - if(!text.empty()) lastname.assign(text); - gSavedSettings.setString("FirstName", firstname); - gSavedSettings.setString("LastName", lastname); - if (gSavedSettings.getBOOL("RememberPassword")) + if(reason_response == "update" + || reason_response == "optional") { - // Successful login means the password is valid, so save it. - LLStartUp::savePasswordToDisk(password); + // In the case of a needed update, quit. + // Its either downloading or declined. + // If optional was skipped this case shouldn't + // be reached. + LLLoginInstance::getInstance()->disconnect(); + LLAppViewer::instance()->forceQuit(); } else { - // Don't leave password from previous session sitting around - // during this login session. - LLStartUp::deletePasswordFromDisk(); - } - - // this is the base used to construct help URLs - text = LLUserAuth::getInstance()->getResponse("help_url_format"); - if (!text.empty()) - { - // replace the default help URL format - gSavedSettings.setString("HelpURLFormat",text); - - // don't fall back to Nebraska's pre-connection static help - gSavedSettings.setBOOL("HelpUseLocal", false); - } - - // this is their actual ability to access content - text = LLUserAuth::getInstance()->getResponse("agent_access_max"); - if (!text.empty()) - { - // agent_access can be 'A', 'M', and 'PG'. - gAgent.setMaturity(text[0]); - } - - // this is the value of their preference setting for that content - // which will always be <= agent_access_max - text = LLUserAuth::getInstance()->getResponse("agent_region_access"); - if (!text.empty()) - { - int preferredMaturity = LLAgent::convertTextToMaturity(text[0]); - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - } - // During the AO transition, this flag will be true. Then the flag will - // go away. After the AO transition, this code and all the code that - // uses it can be deleted. - text = LLUserAuth::getInstance()->getResponse("ao_transition"); - if (!text.empty()) - { - if (text == "1") - { - gAgent.setAOTransition(); - } - } - - text = LLUserAuth::getInstance()->getResponse("start_location"); - if(!text.empty()) agent_start_location.assign(text); - text = LLUserAuth::getInstance()->getResponse("circuit_code"); - if(!text.empty()) - { - gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); - } - std::string sim_ip_str = LLUserAuth::getInstance()->getResponse("sim_ip"); - std::string sim_port_str = LLUserAuth::getInstance()->getResponse("sim_port"); - if(!sim_ip_str.empty() && !sim_port_str.empty()) - { - U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); - first_sim.set(sim_ip_str, sim_port); - if (first_sim.isOk()) - { - gMessageSystem->enableCircuit(first_sim, TRUE); - } - } - std::string region_x_str = LLUserAuth::getInstance()->getResponse("region_x"); - std::string region_y_str = LLUserAuth::getInstance()->getResponse("region_y"); - if(!region_x_str.empty() && !region_y_str.empty()) - { - U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); - U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); - first_sim_handle = to_region_handle(region_x, region_y); - } - - const std::string look_at_str = LLUserAuth::getInstance()->getResponse("look_at"); - if (!look_at_str.empty()) - { - size_t len = look_at_str.size(); - LLMemoryStream mstr((U8*)look_at_str.c_str(), len); - LLSD sd = LLSDSerialize::fromNotation(mstr, len); - agent_start_look_at = ll_vector3_from_sd(sd); - } - - text = LLUserAuth::getInstance()->getResponse("seed_capability"); - if (!text.empty()) first_sim_seed_cap = text; - - text = LLUserAuth::getInstance()->getResponse("seconds_since_epoch"); - if(!text.empty()) - { - U32 server_utc_time = strtoul(text.c_str(), NULL, 10); - if(server_utc_time) + // Don't pop up a notification in the TOS case because + // LLFloaterTOS::onCancel() already scolded the user. + if (reason_response != "tos") { - time_t now = time(NULL); - gUTCOffset = (server_utc_time - now); - } - } - - std::string home_location = LLUserAuth::getInstance()->getResponse("home"); - if(!home_location.empty()) - { - size_t len = home_location.size(); - LLMemoryStream mstr((U8*)home_location.c_str(), len); - LLSD sd = LLSDSerialize::fromNotation(mstr, len); - S32 region_x = sd["region_handle"][0].asInteger(); - S32 region_y = sd["region_handle"][1].asInteger(); - U64 region_handle = to_region_handle(region_x, region_y); - LLVector3 position = ll_vector3_from_sd(sd["position"]); - gAgent.setHomePosRegion(region_handle, position); - } - - gAgent.mMOTD.assign(LLUserAuth::getInstance()->getResponse("message")); - LLUserAuth::options_t options; - if(LLUserAuth::getInstance()->getOptions("inventory-root", options)) - { - LLUserAuth::response_t::iterator it; - it = options[0].find("folder_id"); - if(it != options[0].end()) - { - gInventory.setRootFolderID( LLUUID( (*it).second ) ); - } - } - - options.clear(); - if(LLUserAuth::getInstance()->getOptions("login-flags", options)) - { - LLUserAuth::response_t::iterator it; - LLUserAuth::response_t::iterator no_flag = options[0].end(); - it = options[0].find("ever_logged_in"); - if(it != no_flag) - { - if((*it).second == "N") gAgent.setFirstLogin(TRUE); - else gAgent.setFirstLogin(FALSE); - } - it = options[0].find("stipend_since_login"); - if(it != no_flag) - { - if((*it).second == "Y") stipend_since_login = true; - } - it = options[0].find("gendered"); - if(it != no_flag) - { - if((*it).second == "Y") gAgent.setGenderChosen(TRUE); - } - it = options[0].find("daylight_savings"); - if(it != no_flag) - { - if((*it).second == "Y") gPacificDaylightTime = TRUE; - else gPacificDaylightTime = FALSE; + LLSD args; + args["ERROR_MESSAGE"] = emsg.str(); + LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; + LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); } //setup map of datetime strings to codes and slt & local time offset from utc LLStringOps::setupDatetimeInfo (gPacificDaylightTime); + transition_back_to_login_panel(emsg.str()); + show_connect_box = true; } - options.clear(); - if (LLUserAuth::getInstance()->getOptions("initial-outfit", options) - && !options.empty()) - { - LLUserAuth::response_t::iterator it; - LLUserAuth::response_t::iterator it_end = options[0].end(); - it = options[0].find("folder_name"); - if(it != it_end) - { - // Initial outfit is a folder in your inventory, - // must be an exact folder-name match. - sInitialOutfit = (*it).second; - } - it = options[0].find("gender"); - if (it != it_end) - { - sInitialOutfitGender = (*it).second; - } - } - - options.clear(); - if(LLUserAuth::getInstance()->getOptions("global-textures", options)) - { - // Extract sun and moon texture IDs. These are used - // in the LLVOSky constructor, but I can't figure out - // how to pass them in. JC - LLUserAuth::response_t::iterator it; - LLUserAuth::response_t::iterator no_texture = options[0].end(); - it = options[0].find("sun_texture_id"); - if(it != no_texture) - { - gSunTextureID.set((*it).second); - } - it = options[0].find("moon_texture_id"); - if(it != no_texture) - { - gMoonTextureID.set((*it).second); - } - it = options[0].find("cloud_texture_id"); - if(it != no_texture) - { - gCloudTextureID.set((*it).second); - } - } - - - // JC: gesture loading done below, when we have an asset system - // in place. Don't delete/clear user_credentials until then. - - if(gAgentID.notNull() - && gAgentSessionID.notNull() - && gMessageSystem->mOurCircuitCode - && first_sim.isOk() - && gInventory.getRootFolderID().notNull()) + } + else if(LLLoginInstance::getInstance()->authSuccess()) + { + if(process_login_success_response()) { - LLStartUp::setStartupState( STATE_WORLD_INIT ); + // Pass the user information to the voice chat server interface. + gVoiceClient->userAuthorized(gFirstname, gLastname, gAgentID); + LLStartUp::setStartupState( STATE_WORLD_INIT); } else { - if (gNoRender) - { - LL_WARNS("AppInit") << "Bad login - missing return values" << LL_ENDL; - LL_WARNS("AppInit") << emsg << LL_ENDL; - exit(0); - } - // Bounce back to the login screen. LLSD args; args["ERROR_MESSAGE"] = emsg.str(); + LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL; LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); - reset_login(); - gSavedSettings.setBOOL("AutoLogin", FALSE); + transition_back_to_login_panel(emsg.str()); show_connect_box = true; } - - // Pass the user information to the voice chat server interface. - gVoiceClient->userAuthorized(firstname, lastname, gAgentID); } - else // if(successful_login) + else { - if (gNoRender) - { - LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL; - LL_WARNS("AppInit") << emsg << LL_ENDL; - exit(0); - } - // Bounce back to the login screen. - LLSD args; - args["ERROR_MESSAGE"] = emsg.str(); - LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); - reset_login(); - gSavedSettings.setBOOL("AutoLogin", FALSE); - show_connect_box = true; + // Still waiting for response. + // *TODO:Mani - Actually check for login progress. + // If we get here we have gotten past the potential stall + // in curl, so take "may appear frozen" out of progress bar. JC + auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); + set_startup_status(progress, auth_desc, auth_message); } + return FALSE; } @@ -1740,14 +1241,14 @@ bool idle_startup() // This is necessary because creating objects before this is set will result in a // bad mPositionAgent cache. - gAgent.initOriginGlobal(from_region_handle(first_sim_handle)); + gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle)); - LLWorld::getInstance()->addRegion(first_sim_handle, first_sim); + LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; - regionp->setSeedCapability(first_sim_seed_cap); + regionp->setSeedCapability(gFirstSimSeedCap); LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; // Set agent's initial region to be the one we just created. @@ -1886,7 +1387,7 @@ bool idle_startup() // the coordinates handed to us to fit in the local region. gAgent.setPositionAgent(agent_start_position_region); - gAgent.resetAxes(agent_start_look_at); + gAgent.resetAxes(gAgentStartLookAt); gAgent.stopCameraAnimation(); gAgent.resetCamera(); @@ -1925,18 +1426,18 @@ bool idle_startup() LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL; } - gUseCircuitCallbackCalled = FALSE; + gUseCircuitCallbackCalled = false; - msg->enableCircuit(first_sim, TRUE); + msg->enableCircuit(gFirstSim, TRUE); // now, use the circuit info to tell simulator about us! - LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << LL_ENDL; + LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL; msg->newMessageFast(_PREHASH_UseCircuitCode); msg->nextBlockFast(_PREHASH_CircuitCode); msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); msg->sendReliable( - first_sim, + gFirstSim, MAX_TIMEOUT_COUNT, FALSE, TIMEOUT_SECONDS, @@ -2047,105 +1548,99 @@ bool idle_startup() LLAgentLanguage::update(); // unpack thin inventory - LLUserAuth::options_t options; - options.clear(); + LLSD response = LLLoginInstance::getInstance()->getResponse(); //bool dump_buffer = false; - - if(LLUserAuth::getInstance()->getOptions("inventory-lib-root", options) - && !options.empty()) + + LLSD inv_lib_root = response["inventory-lib-root"]; + if(inv_lib_root.isDefined()) { // should only be one - LLUserAuth::response_t::iterator it; - it = options[0].find("folder_id"); - if(it != options[0].end()) + LLSD id = inv_lib_root[0]["folder_id"]; + if(id.isDefined()) { - gInventory.setLibraryRootFolderID( LLUUID( (*it).second ) ); + gInventory.setLibraryRootFolderID(id.asUUID()); } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("inventory-lib-owner", options) - && !options.empty()) + + LLSD inv_lib_owner = response["inventory-lib-owner"]; + if(inv_lib_owner.isDefined()) { // should only be one - LLUserAuth::response_t::iterator it; - it = options[0].find("agent_id"); - if(it != options[0].end()) + LLSD id = inv_lib_owner[0]["agent_id"]; + if(id.isDefined()) { - gInventory.setLibraryOwnerID( LLUUID( (*it).second ) ); + gInventory.setLibraryOwnerID( LLUUID(id.asUUID())); } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options) - && gInventory.getLibraryOwnerID().notNull()) + + LLSD inv_skel_lib = response["inventory-skel-lib"]; + if(inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull()) { - if(!gInventory.loadSkeleton(options, gInventory.getLibraryOwnerID())) + if(!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID())) { LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL; } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("inventory-skeleton", options)) + + LLSD inv_skeleton = response["inventory-skeleton"]; + if(inv_skeleton.isDefined()) { - if(!gInventory.loadSkeleton(options, gAgent.getID())) + if(!gInventory.loadSkeleton(inv_skeleton, gAgent.getID())) { LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL; } } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("buddy-list", options)) + LLSD buddy_list = response["buddy-list"]; + if(buddy_list.isDefined()) { - LLUserAuth::options_t::iterator it = options.begin(); - LLUserAuth::options_t::iterator end = options.end(); LLAvatarTracker::buddy_map_t list; LLUUID agent_id; S32 has_rights = 0, given_rights = 0; - for (; it != end; ++it) + for(LLSD::array_const_iterator it = buddy_list.beginArray(), + end = buddy_list.endArray(); it != end; ++it) { - LLUserAuth::response_t::const_iterator option_it; - option_it = (*it).find("buddy_id"); - if(option_it != (*it).end()) + LLSD buddy_id = (*it)["buddy_id"]; + if(buddy_id.isDefined()) { - agent_id.set((*option_it).second); + agent_id = buddy_id.asUUID(); } - option_it = (*it).find("buddy_rights_has"); - if(option_it != (*it).end()) + + LLSD buddy_rights_has = (*it)["buddy_rights_has"]; + if(buddy_rights_has.isDefined()) { - has_rights = atoi((*option_it).second.c_str()); + has_rights = buddy_rights_has.asInteger(); } - option_it = (*it).find("buddy_rights_given"); - if(option_it != (*it).end()) + + LLSD buddy_rights_given = (*it)["buddy_rights_given"]; + if(buddy_rights_given.isDefined()) { - given_rights = atoi((*option_it).second.c_str()); + given_rights = buddy_rights_given.asInteger(); } + list[agent_id] = new LLRelationship(given_rights, has_rights, false); } LLAvatarTracker::instance().addBuddyList(list); } - options.clear(); - bool show_hud = false; - if(LLUserAuth::getInstance()->getOptions("tutorial_setting", options)) + LLSD tutorial_setting = response["tutorial_setting"]; + if(tutorial_setting.isDefined()) { - LLUserAuth::options_t::iterator it = options.begin(); - LLUserAuth::options_t::iterator end = options.end(); - for (; it != end; ++it) + for(LLSD::array_const_iterator it = tutorial_setting.beginArray(), + end = tutorial_setting.endArray(); it != end; ++it) { - LLUserAuth::response_t::const_iterator option_it; - option_it = (*it).find("tutorial_url"); - if(option_it != (*it).end()) + LLSD tutorial_url = (*it)["tutorial_url"]; + if(tutorial_url.isDefined()) { // Tutorial floater will append language code - gSavedSettings.setString("TutorialURL", option_it->second); + gSavedSettings.setString("TutorialURL", tutorial_url.asString()); } - option_it = (*it).find("use_tutorial"); - if(option_it != (*it).end()) + + LLSD use_tutorial = (*it)["use_tutorial"]; + if(use_tutorial.asString() == "true") { - if (option_it->second == "true") - { - show_hud = true; - } + show_hud = true; } } } @@ -2157,19 +1652,22 @@ bool idle_startup() LLFloaterReg::showInstance("hud", LLSD(), FALSE); } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("event_categories", options)) + LLSD event_categories = response["event_categories"]; + if(event_categories.isDefined()) { - LLEventInfo::loadCategories(options); + LLEventInfo::loadCategories(event_categories); } - if(LLUserAuth::getInstance()->getOptions("event_notifications", options)) + + LLSD event_notifications = response["event_notifications"]; + if(event_notifications.isDefined()) { - gEventNotifier.load(options); + gEventNotifier.load(event_notifications); } - options.clear(); - if(LLUserAuth::getInstance()->getOptions("classified_categories", options)) + + LLSD classified_categories = response["classified_categories"]; + if(classified_categories.isDefined()) { - LLClassifiedInfo::loadCategories(options); + LLClassifiedInfo::loadCategories(classified_categories); } @@ -2233,7 +1731,7 @@ bool idle_startup() // This is actually a pessimistic computation, because TCP may not have enough // time to ramp up on the (small) default inventory file to truly measure max // bandwidth. JC - F64 rate_bps = LLUserAuth::getInstance()->getLastTransferRateBPS(); + F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS(); const F32 FAST_RATE_BPS = 600.f * 1024.f; const F32 FASTER_RATE_BPS = 750.f * 1024.f; F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); @@ -2281,34 +1779,20 @@ bool idle_startup() // JC: Initialize "active" gestures. This may also trigger // many gesture downloads, if this is the user's first // time on this machine or -purge has been run. - LLUserAuth::options_t gesture_options; - if (LLUserAuth::getInstance()->getOptions("gestures", gesture_options)) + LLSD gesture_options + = LLLoginInstance::getInstance()->getResponse("gestures"); + if (gesture_options.isDefined()) { LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size() << LL_ENDL; std::vector<LLUUID> item_ids; - LLUserAuth::options_t::iterator resp_it; - for (resp_it = gesture_options.begin(); - resp_it != gesture_options.end(); - ++resp_it) + for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(), + end = gesture_options.endArray(); resp_it != end; ++resp_it) { - const LLUserAuth::response_t& response = *resp_it; - LLUUID item_id; - LLUUID asset_id; - LLUserAuth::response_t::const_iterator option_it; - - option_it = response.find("item_id"); - if (option_it != response.end()) - { - const std::string& uuid_string = (*option_it).second; - item_id.set(uuid_string); - } - option_it = response.find("asset_id"); - if (option_it != response.end()) - { - const std::string& uuid_string = (*option_it).second; - asset_id.set(uuid_string); - } + // If the id is not specifed in the LLSD, + // the LLSD operator[]() will return a null LLUUID. + LLUUID item_id = (*resp_it)["item_id"]; + LLUUID asset_id = (*resp_it)["asset_id"]; if (item_id.notNull() && asset_id.notNull()) { @@ -2364,8 +1848,8 @@ bool idle_startup() if (!gAgent.isFirstLogin()) { bool url_ok = LLURLSimString::sInstance.parse(); - if ((url_ok && agent_start_location == "url") || - (!url_ok && ((agent_start_location == gSavedSettings.getString("LoginLocation"))))) + if ((url_ok && gAgentStartLocation == "url") || + (!url_ok && ((gAgentStartLocation == gSavedSettings.getString("LoginLocation"))))) { // Start location is OK // Disabled code to restore camera location and focus if logging in to default location @@ -2578,8 +2062,10 @@ bool idle_startup() // then the data is cached for the viewer's lifetime) LLProductInfoRequestManager::instance(); + // *FIX:Mani - What do I do here? + // Need we really clear the Auth response data? // Clean up the userauth stuff. - LLUserAuth::getInstance()->reset(); + // LLUserAuth::getInstance()->reset(); LLStartUp::setStartupState( STATE_STARTED ); @@ -2869,230 +2355,6 @@ bool login_alert_status(const LLSD& notification, const LLSD& response) return false; } -void update_app(BOOL mandatory, const std::string& auth_msg) -{ - // store off config state, as we might quit soon - gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - LLUIColorTable::instance().saveUserSettings(); - std::ostringstream message; - - std::string msg; - if (!auth_msg.empty()) - { - msg = "("+ auth_msg + ") \n"; - } - - LLSD args; - args["MESSAGE"] = msg; - - LLSD payload; - payload["mandatory"] = mandatory; - -/* - We're constructing one of the following 6 strings here: - "DownloadWindowsMandatory" - "DownloadWindowsReleaseForDownload" - "DownloadWindows" - "DownloadMacMandatory" - "DownloadMacReleaseForDownload" - "DownloadMac" - - I've called them out explicitly in this comment so that they can be grepped for. - - Also, we assume that if we're not Windows we're Mac. If we ever intend to support - Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but - we'd rather deliver the wrong message than no message, so until Linux is supported - we'll leave it alone. - */ - std::string notification_name = "Download"; - -#if LL_WINDOWS - notification_name += "Windows"; -#elif LL_DARWIN - notification_name += "Mac"; -#else - notification_name += "Linux"; -#endif - - if (mandatory) - { - notification_name += "Mandatory"; - } - else - { -#if LL_RELEASE_FOR_DOWNLOAD - notification_name += "ReleaseForDownload"; -#endif - } - - LLNotifications::instance().add(notification_name, args, payload, update_dialog_callback); -} - -bool update_dialog_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - std::string update_exe_path; - bool mandatory = notification["payload"]["mandatory"].asBoolean(); - -#if !LL_RELEASE_FOR_DOWNLOAD - if (option == 2) - { - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - return false; - } -#endif - - if (option == 1) - { - // ...user doesn't want to do it - if (mandatory) - { - LLAppViewer::instance()->forceQuit(); - // Bump them back to the login screen. - //reset_login(); - } - else - { - LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); - } - return false; - } - - // if a sim name was passed in via command line parameter (typically through a SLURL) - if ( LLURLSimString::sInstance.mSimString.length() ) - { - // record the location to start at next time - gSavedSettings.setString("NextLoginLocation", LLURLSimString::sInstance.mSimString); - } - - LLSD query_map = LLSD::emptyMap(); - // *TODO place os string in a global constant -#if LL_WINDOWS - query_map["os"] = "win"; -#elif LL_DARWIN - query_map["os"] = "mac"; -#elif LL_LINUX - query_map["os"] = "lnx"; -#elif LL_SOLARIS - query_map["os"] = "sol"; -#endif - // *TODO change userserver to be grid on both viewer and sim, since - // userserver no longer exists. - query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); - query_map["channel"] = gSavedSettings.getString("VersionChannelName"); - // *TODO constantize this guy - // *NOTE: This URL is also used in win_setup/lldownloader.cpp - LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); - - if(LLAppViewer::sUpdaterInfo) - { - delete LLAppViewer::sUpdaterInfo ; - } - LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; - -#if LL_WINDOWS - LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); - if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) - { - delete LLAppViewer::sUpdaterInfo ; - LLAppViewer::sUpdaterInfo = NULL ; - - // We're hosed, bail - LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - return false; - } - - LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; - - std::string updater_source = gDirUtilp->getAppRODataDir(); - updater_source += gDirUtilp->getDirDelimiter(); - updater_source += "updater.exe"; - - LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source - << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath - << LL_ENDL; - - - if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) - { - delete LLAppViewer::sUpdaterInfo ; - LLAppViewer::sUpdaterInfo = NULL ; - - LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - return false; - } - - LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; - - LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; - - //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. - LLAppViewer::instance()->removeMarkerFile(); // In case updater fails - -#elif LL_DARWIN - LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; - LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; - LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); - LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; - - LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; - - // Run the auto-updater. - system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ - -#elif (LL_LINUX || LL_SOLARIS) && LL_GTK - // we tell the updater where to find the xml containing string - // translations which it can use for its own UI - std::string xml_strings_file = "strings.xml"; - std::vector<std::string> xui_path_vec = LLUI::getXUIPaths(); - std::string xml_search_paths; - std::vector<std::string>::const_iterator iter; - // build comma-delimited list of xml paths to pass to updater - for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) - { - std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() - + gDirUtilp->getDirDelimiter() - + (*iter); - llinfos << "Got a XUI path: " << this_skin_dir << llendl; - xml_search_paths.append(this_skin_dir); - ++iter; - if (iter != xui_path_vec.end()) - xml_search_paths.append(","); // comma-delimit - } - // build the overall command-line to run the updater correctly - update_exe_path = - gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + - " --url \"" + update_url.asString() + "\"" + - " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" + - " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" + - " --stringsdir \"" + xml_search_paths + "\"" + - " --stringsfile \"" + xml_strings_file + "\""; - - LL_INFOS("AppInit") << "Calling updater: " - << update_exe_path << LL_ENDL; - - // *TODO: we could use the gdk equivilant to ensure the updater - // gets started on the same screen. - GError *error = NULL; - if (!g_spawn_command_line_async(update_exe_path.c_str(), &error)) - { - llerrs << "Failed to launch updater: " - << error->message - << llendl; - } - if (error) - g_error_free(error); -#else - OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); -#endif - LLAppViewer::instance()->forceQuit(); - return false; -} void use_circuit_callback(void**, S32 result) { @@ -3439,11 +2701,7 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_LOGIN_SHOW ); RTNENUM( STATE_LOGIN_WAIT ); RTNENUM( STATE_LOGIN_CLEANUP ); - RTNENUM( STATE_UPDATE_CHECK ); RTNENUM( STATE_LOGIN_AUTH_INIT ); - RTNENUM( STATE_LOGIN_AUTHENTICATE ); - RTNENUM( STATE_LOGIN_NO_DATA_YET ); - RTNENUM( STATE_LOGIN_DOWNLOADING ); RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); RTNENUM( STATE_WORLD_INIT ); RTNENUM( STATE_SEED_GRANTED_WAIT ); @@ -3463,14 +2721,17 @@ std::string LLStartUp::startupStateToString(EStartupState state) #undef RTNENUM } - // static void LLStartUp::setStartupState( EStartupState state ) { LL_INFOS("AppInit") << "Startup state changing from " << - startupStateToString(gStartupState) << " to " << + getStartupStateString() << " to " << startupStateToString(state) << LL_ENDL; gStartupState = state; + LLSD stateInfo; + stateInfo["str"] = getStartupStateString(); + stateInfo["enum"] = state; + sStartupStateWatcher.post(stateInfo); } @@ -3584,3 +2845,277 @@ void apply_udp_blacklist(const std::string& csv) } +bool process_login_success_response() +{ + LLSD response = LLLoginInstance::getInstance()->getResponse(); + + std::string text(response["udp_blacklist"]); + if(!text.empty()) + { + apply_udp_blacklist(text); + } + + // unpack login data needed by the application + text = response["agent_id"].asString(); + if(!text.empty()) gAgentID.set(text); + gDebugInfo["AgentID"] = text; + + text = response["session_id"].asString(); + if(!text.empty()) gAgentSessionID.set(text); + gDebugInfo["SessionID"] = text; + + text = response["secure_session_id"].asString(); + if(!text.empty()) gAgent.mSecureSessionID.set(text); + + text = response["first_name"].asString(); + if(!text.empty()) + { + // Remove quotes from string. Login.cgi sends these to force + // names that look like numbers into strings. + gFirstname.assign(text); + LLStringUtil::replaceChar(gFirstname, '"', ' '); + LLStringUtil::trim(gFirstname); + } + text = response["last_name"].asString(); + if(!text.empty()) + { + gLastname.assign(text); + } + gSavedSettings.setString("FirstName", gFirstname); + gSavedSettings.setString("LastName", gLastname); + + if (gSavedSettings.getBOOL("RememberPassword")) + { + // Successful login means the password is valid, so save it. + LLStartUp::savePasswordToDisk(gPassword); + } + else + { + // Don't leave password from previous session sitting around + // during this login session. + LLStartUp::deletePasswordFromDisk(); + } + + // this is their actual ability to access content + text = response["agent_access_max"].asString(); + if (!text.empty()) + { + // agent_access can be 'A', 'M', and 'PG'. + gAgent.setMaturity(text[0]); + } + + // this is the value of their preference setting for that content + // which will always be <= agent_access_max + text = response["agent_region_access"].asString(); + if (!text.empty()) + { + int preferredMaturity = LLAgent::convertTextToMaturity(text[0]); + gSavedSettings.setU32("PreferredMaturity", preferredMaturity); + } + // During the AO transition, this flag will be true. Then the flag will + // go away. After the AO transition, this code and all the code that + // uses it can be deleted. + text = response["ao_transition"].asString(); + if (!text.empty()) + { + if (text == "1") + { + gAgent.setAOTransition(); + } + } + + text = response["start_location"].asString(); + if(!text.empty()) + { + gAgentStartLocation.assign(text); + } + + text = response["circuit_code"].asString(); + if(!text.empty()) + { + gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10); + } + std::string sim_ip_str = response["sim_ip"]; + std::string sim_port_str = response["sim_port"]; + if(!sim_ip_str.empty() && !sim_port_str.empty()) + { + U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10); + gFirstSim.set(sim_ip_str, sim_port); + if (gFirstSim.isOk()) + { + gMessageSystem->enableCircuit(gFirstSim, TRUE); + } + } + std::string region_x_str = response["region_x"]; + std::string region_y_str = response["region_y"]; + if(!region_x_str.empty() && !region_y_str.empty()) + { + U32 region_x = strtoul(region_x_str.c_str(), NULL, 10); + U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); + gFirstSimHandle = to_region_handle(region_x, region_y); + } + + const std::string look_at_str = response["look_at"]; + if (!look_at_str.empty()) + { + size_t len = look_at_str.size(); + LLMemoryStream mstr((U8*)look_at_str.c_str(), len); + LLSD sd = LLSDSerialize::fromNotation(mstr, len); + gAgentStartLookAt = ll_vector3_from_sd(sd); + } + + text = response["seed_capability"].asString(); + if (!text.empty()) gFirstSimSeedCap = text; + + text = response["seconds_since_epoch"].asString(); + if(!text.empty()) + { + U32 server_utc_time = strtoul(text.c_str(), NULL, 10); + if(server_utc_time) + { + time_t now = time(NULL); + gUTCOffset = (server_utc_time - now); + } + } + + // this is the base used to construct help URLs + text = response["help_url_format"].asString(); + if (!text.empty()) + { + // replace the default help URL format + gSavedSettings.setString("HelpURLFormat",text); + + // don't fall back to Nebraska's pre-connection static help + gSavedSettings.setBOOL("HelpUseLocal", false); + } + + std::string home_location = response["home"]; + if(!home_location.empty()) + { + size_t len = home_location.size(); + LLMemoryStream mstr((U8*)home_location.c_str(), len); + LLSD sd = LLSDSerialize::fromNotation(mstr, len); + S32 region_x = sd["region_handle"][0].asInteger(); + S32 region_y = sd["region_handle"][1].asInteger(); + U64 region_handle = to_region_handle(region_x, region_y); + LLVector3 position = ll_vector3_from_sd(sd["position"]); + gAgent.setHomePosRegion(region_handle, position); + } + + gAgent.mMOTD.assign(response["message"]); + + // Options... + // Each 'option' is an array of submaps. + // It appears that we only ever use the first element of the array. + LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"]; + if(inv_root_folder_id.notNull()) + { + gInventory.setRootFolderID(inv_root_folder_id); + //gInventory.mock(gAgent.getInventoryRootID()); + } + + LLSD login_flags = response["login-flags"][0]; + if(login_flags.size()) + { + std::string flag = login_flags["ever_logged_in"]; + if(!flag.empty()) + { + gAgent.setFirstLogin((flag == "N") ? TRUE : FALSE); + } + + /* Flag is currently ignored by the viewer. + flag = login_flags["stipend_since_login"]; + if(flag == "Y") + { + stipend_since_login = true; + } + */ + + flag = login_flags["gendered"].asString(); + if(flag == "Y") + { + gAgent.setGenderChosen(TRUE); + } + + flag = login_flags["daylight_savings"].asString(); + if(flag == "Y") + { + gPacificDaylightTime = (flag == "Y") ? TRUE : FALSE; + } + + //setup map of datetime strings to codes and slt & local time offset from utc + LLStringOps::setupDatetimeInfo (gPacificDaylightTime); + } + + LLSD initial_outfit = response["initial-outfit"][0]; + if(initial_outfit.size()) + { + std::string flag = initial_outfit["folder_name"]; + if(!flag.empty()) + { + // Initial outfit is a folder in your inventory, + // must be an exact folder-name match. + sInitialOutfit = flag; + } + + flag = initial_outfit["gender"].asString(); + if(!flag.empty()) + { + sInitialOutfitGender = flag; + } + } + + LLSD global_textures = response["global-textures"][0]; + if(global_textures.size()) + { + // Extract sun and moon texture IDs. These are used + // in the LLVOSky constructor, but I can't figure out + // how to pass them in. JC + LLUUID id = global_textures["sun_texture_id"]; + if(id.notNull()) + { + gSunTextureID = id; + } + + id = global_textures["moon_texture_id"]; + if(id.notNull()) + { + gMoonTextureID = id; + } + + id = global_textures["cloud_texture_id"]; + if(id.notNull()) + { + gCloudTextureID = id; + } + } + + + bool success = false; + // JC: gesture loading done below, when we have an asset system + // in place. Don't delete/clear user_credentials until then. + if(gAgentID.notNull() + && gAgentSessionID.notNull() + && gMessageSystem->mOurCircuitCode + && gFirstSim.isOk() + && gInventory.getRootFolderID().notNull()) + { + success = true; + } + + return success; +} + +void transition_back_to_login_panel(const std::string& emsg) +{ + if (gNoRender) + { + LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL; + LL_WARNS("AppInit") << emsg << LL_ENDL; + exit(0); + } + + // Bounce back to the login screen. + reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW ); + gSavedSettings.setBOOL("AutoLogin", FALSE); +} diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 4532c5e586..7f869d014f 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -50,11 +50,7 @@ typedef enum { STATE_LOGIN_SHOW, // Show login screen STATE_LOGIN_WAIT, // Wait for user input at login screen STATE_LOGIN_CLEANUP, // Get rid of login screen and start login - STATE_UPDATE_CHECK, // Wait for user at a dialog box (updates, term-of-service, etc) STATE_LOGIN_AUTH_INIT, // Start login to SL servers - STATE_LOGIN_AUTHENTICATE, // Do authentication voodoo - STATE_LOGIN_NO_DATA_YET, // Waiting for authentication replies to start - STATE_LOGIN_DOWNLOADING, // Waiting for authentication replies to download STATE_LOGIN_PROCESS_RESPONSE, // Check authentication reply STATE_WORLD_INIT, // Start building the world STATE_MULTIMEDIA_INIT, // Init the rest of multimedia library @@ -75,8 +71,6 @@ typedef enum { // exported symbols extern bool gAgentMovementCompleted; extern LLPointer<LLViewerTexture> gStartTexture; -extern std::string gInitialOutfit; -extern std::string gInitialOutfitGender; // "male" or "female" class LLStartUp { diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index b015f668e4..b035fd53fd 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -518,11 +518,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) if(!object) { - // We need to clear media hover flag - if (LLViewerMediaFocus::getInstance()->getMouseOverFlag()) - { - LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); - } + LLViewerMediaFocus::getInstance()->clearHover(); } } @@ -1029,7 +1025,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) pick.mObjectFace < 0 || pick.mObjectFace >= objectp->getNumTEs()) { - LLSelectMgr::getInstance()->deselect(); LLViewerMediaFocus::getInstance()->clearFocus(); return false; @@ -1037,11 +1032,7 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - - // is media playing on this face? + // Does this face have media? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL; @@ -1051,11 +1042,9 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) && gSavedSettings.getBOOL("MediaOnAPrimUI") && media_impl.notNull()) { - // LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection(); - if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/ - ! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) ) + if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) ) { - LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); + LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal); } else { @@ -1067,7 +1056,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) return true; } - LLSelectMgr::getInstance()->deselect(); LLViewerMediaFocus::getInstance()->clearFocus(); return false; @@ -1081,50 +1069,50 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick) LLPointer<LLViewerObject> objectp = pick.getObject(); - // Early out cases. Must clear mouse over media focus flag + // Early out cases. Must clear media hover. // did not hit an object or did not hit a valid face if ( objectp.isNull() || pick.mObjectFace < 0 || pick.mObjectFace >= objectp->getNumTEs() ) { - LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + LLViewerMediaFocus::getInstance()->clearHover(); return false; } - - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - - // is media playing on this face? + // Does this face have media? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; if (mep && gSavedSettings.getBOOL("MediaOnAPrimUI")) { viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); - if(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull()) - { - media_impl->mouseMove(pick.mUVCoords); - - gViewerWindow->setCursor(media_impl->getLastSetCursor()); - } - else + + if(media_impl.notNull()) { - gViewerWindow->setCursor(UI_CURSOR_ARROW); - } + // Update media hover object + if (!LLViewerMediaFocus::getInstance()->isHoveringOverFace(objectp, pick.mObjectFace)) + { + LLViewerMediaFocus::getInstance()->setHoverFace(objectp, pick.mObjectFace, media_impl, pick.mNormal); + } + + // If this is the focused media face, send mouse move events. + if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace)) + { + media_impl->mouseMove(pick.mUVCoords); + gViewerWindow->setCursor(media_impl->getLastSetCursor()); + } + else + { + // This is not the focused face -- set the default cursor. + gViewerWindow->setCursor(UI_CURSOR_ARROW); + } - // Set mouse over flag if unset - if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag()) - { - LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace); - LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl); - LLViewerMediaFocus::getInstance()->setPickInfo(pick); + return true; } - - return true; } - LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + + // In all other cases, clear media hover. + LLViewerMediaFocus::getInstance()->clearHover(); return false; } diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp new file mode 100644 index 0000000000..9c643e78de --- /dev/null +++ b/indra/newview/lluilistener.cpp @@ -0,0 +1,50 @@ +/** + * @file lluilistener.cpp + * @author Nat Goodspeed + * @date 2009-08-18 + * @brief Implementation for lluilistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "lluilistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "lluictrl.h" +#include "llerror.h" + +LLUIListener::LLUIListener(const std::string& name): + LLDispatchListener(name, "op") +{ + add("call", &LLUIListener::call, LLSD().insert("function", LLSD())); +} + +void LLUIListener::call(const LLSD& event) const +{ + LLUICtrl::commit_callback_t* func = + LLUICtrl::CommitCallbackRegistry::getValue(event["function"]); + if (! func) + { + // This API is intended for use by a script. It's a fire-and-forget + // API: we provide no reply. Therefore, a typo in the script will + // provide no feedback whatsoever to that script. To rub the coder's + // nose in such an error, crump rather than quietly ignoring it. + LL_ERRS("LLUIListener") << "function '" << event["function"] << "' not found" << LL_ENDL; + } + else + { + // Interestingly, view_listener_t::addMenu() (addCommit(), + // addEnable()) constructs a commit_callback_t callable that accepts + // two parameters but discards the first. Only the second is passed to + // handleEvent(). Therefore we feel completely safe passing NULL for + // the first parameter. + (*func)(NULL, event["parameter"]); + } +} diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h new file mode 100644 index 0000000000..ea904a99ff --- /dev/null +++ b/indra/newview/lluilistener.h @@ -0,0 +1,29 @@ +/** + * @file lluilistener.h + * @author Nat Goodspeed + * @date 2009-08-18 + * @brief Engage named functions as specified by XUI + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLUILISTENER_H) +#define LL_LLUILISTENER_H + +#include "lleventdispatcher.h" +#include <string> + +class LLSD; + +class LLUIListener: public LLDispatchListener +{ +public: + LLUIListener(const std::string& name); + +private: + void call(const LLSD& event) const; +}; + +#endif /* ! defined(LL_LLUILISTENER_H) */ diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp new file mode 100644 index 0000000000..ecba1b8eb0 --- /dev/null +++ b/indra/newview/llviewercontrollistener.cpp @@ -0,0 +1,102 @@ +/** + * @file llviewercontrollistener.cpp + * @author Brad Kittenbrink + * @date 2009-07-09 + * @brief Implementation for llviewercontrollistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewercontrollistener.h" + +#include "llviewercontrol.h" + +LLViewerControlListener gSavedSettingsListener; + +LLViewerControlListener::LLViewerControlListener() + : LLDispatchListener("LLViewerControl", "group") +{ + add("Global", boost::bind(&LLViewerControlListener::set, &gSavedSettings, _1)); + add("PerAccount", boost::bind(&LLViewerControlListener::set, &gSavedPerAccountSettings, _1)); + add("Warning", boost::bind(&LLViewerControlListener::set, &gWarningSettings, _1)); + add("Crash", boost::bind(&LLViewerControlListener::set, &gCrashSettings, _1)); + +#if 0 + add(/*"toggleControl",*/ "Global", boost::bind(&LLViewerControlListener::toggleControl, &gSavedSettings, _1)); + add(/*"toggleControl",*/ "PerAccount", boost::bind(&LLViewerControlListener::toggleControl, &gSavedPerAccountSettings, _1)); + add(/*"toggleControl",*/ "Warning", boost::bind(&LLViewerControlListener::toggleControl, &gWarningSettings, _1)); + add(/*"toggleControl",*/ "Crash", boost::bind(&LLViewerControlListener::toggleControl, &gCrashSettings, _1)); + + add(/*"setDefault",*/ "Global", boost::bind(&LLViewerControlListener::setDefault, &gSavedSettings, _1)); + add(/*"setDefault",*/ "PerAccount", boost::bind(&LLViewerControlListener::setDefault, &gSavedPerAccountSettings, _1)); + add(/*"setDefault",*/ "Warning", boost::bind(&LLViewerControlListener::setDefault, &gWarningSettings, _1)); + add(/*"setDefault",*/ "Crash", boost::bind(&LLViewerControlListener::setDefault, &gCrashSettings, _1)); +#endif // 0 +} + +//static +void LLViewerControlListener::set(LLControlGroup * controls, LLSD const & event_data) +{ + if(event_data.has("key")) + { + std::string key(event_data["key"]); + + if(controls->controlExists(key)) + { + controls->setUntypedValue(key, event_data["value"]); + } + else + { + llwarns << "requested unknown control: \"" << key << '\"' << llendl; + } + } +} + +//static +void LLViewerControlListener::toggleControl(LLControlGroup * controls, LLSD const & event_data) +{ + if(event_data.has("key")) + { + std::string key(event_data["key"]); + + if(controls->controlExists(key)) + { + LLControlVariable * control = controls->getControl(key); + if(control->isType(TYPE_BOOLEAN)) + { + control->set(!control->get().asBoolean()); + } + else + { + llwarns << "requested toggle of non-boolean control: \"" << key << "\", type is " << control->type() << llendl; + } + } + else + { + llwarns << "requested unknown control: \"" << key << '\"' << llendl; + } + } +} + +//static +void LLViewerControlListener::setDefault(LLControlGroup * controls, LLSD const & event_data) +{ + if(event_data.has("key")) + { + std::string key(event_data["key"]); + + if(controls->controlExists(key)) + { + LLControlVariable * control = controls->getControl(key); + control->resetToDefault(); + } + else + { + llwarns << "requested unknown control: \"" << key << '\"' << llendl; + } + } +} diff --git a/indra/newview/llviewercontrollistener.h b/indra/newview/llviewercontrollistener.h new file mode 100644 index 0000000000..cacf97e908 --- /dev/null +++ b/indra/newview/llviewercontrollistener.h @@ -0,0 +1,33 @@ +/** + * @file llviewercontrollistener.h + * @author Brad Kittenbrink + * @date 2009-07-09 + * @brief Event API for subset of LLViewerControl methods + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERCONTROLLISTENER_H +#define LL_LLVIEWERCONTROLLISTENER_H + +#include "lleventdispatcher.h" + +class LLControlGroup; +class LLSD; + +class LLViewerControlListener : public LLDispatchListener +{ +public: + LLViewerControlListener(); + +private: + static void set(LLControlGroup *controls, LLSD const & event_data); + static void toggleControl(LLControlGroup *controls, LLSD const & event_data); + static void setDefault(LLControlGroup *controls, LLSD const & event_data); +}; + +extern LLViewerControlListener gSavedSettingsListener; + +#endif // LL_LLVIEWERCONTROLLISTENER_H diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index b8e945a7b8..0b6ac0e2e2 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -250,7 +250,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels()); } - if((was_loaded || media_entry->getAutoPlay()) && !update_from_self) + if((was_loaded || (media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))) && !update_from_self) { if(!media_entry->getCurrentURL().empty()) { @@ -273,7 +273,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s media_impl->setHomeURL(media_entry->getHomeURL()); - if(media_entry->getAutoPlay()) + if(media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia")) { needs_navigate = true; } @@ -588,7 +588,9 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mHasFocus(false), mPriority(LLPluginClassMedia::PRIORITY_UNLOADED), mDoNavigateOnLoad(false), + mDoNavigateOnLoadRediscoverType(false), mDoNavigateOnLoadServerRequest(false), + mMediaSourceFailedInit(false), mIsUpdated(false) { @@ -638,13 +640,18 @@ void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObser ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) { - if((mMediaSource == NULL) || (mMimeType != mime_type)) + bool mimeTypeChanged = (mMimeType != mime_type); + bool pluginChanged = (LLMIMETypes::implType(mMimeType) != LLMIMETypes::implType(mime_type)); + + if(!mMediaSource || pluginChanged) { - if(! initializePlugin(mime_type)) - { - // This may be the case where the plugin's priority is PRIORITY_UNLOADED - return false; - } + // We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type. + (void)initializePlugin(mime_type); + } + else if(mimeTypeChanged) + { + // The same plugin should be able to handle the new media -- just update the stored mime type. + mMimeType = mime_type; } // play(); @@ -664,7 +671,7 @@ void LLViewerMediaImpl::createMediaSource() { if(! mMediaURL.empty()) { - navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest); + navigateTo(mMediaURL, mMimeType, mDoNavigateOnLoadRediscoverType, mDoNavigateOnLoadServerRequest); } else if(! mMimeType.empty()) { @@ -703,7 +710,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height) { std::string plugin_basename = LLMIMETypes::implType(media_type); - + if(plugin_basename.empty()) { LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; @@ -774,6 +781,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) return false; } + // If we got here, we want to ignore previous init failures. + mMediaSourceFailedInit = false; + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight); if (media_source) @@ -787,6 +797,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) return true; } + // Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes. + mMediaSourceFailedInit = true; + return false; } @@ -828,7 +841,15 @@ void LLViewerMediaImpl::stop() { if(mMediaSource) { - mMediaSource->stop(); + if(mMediaSource->pluginSupportsMediaBrowser()) + { + mMediaSource->browse_stop(); + } + else + { + mMediaSource->stop(); + } + // destroyMediaSource(); } } @@ -1002,21 +1023,69 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::navigateHome() +void LLViewerMediaImpl::navigateBack() { - mMediaURL = mHomeURL; - mDoNavigateOnLoad = !mMediaURL.empty(); - mDoNavigateOnLoadServerRequest = false; - - if(mMediaSource) + if (mMediaSource) + { + if(mMediaSource->pluginSupportsMediaTime()) + { + F64 step_scale = 0.02; // temp , can be changed + F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale); + if(back_step < 0.0) + { + back_step = 0.0; + } + mMediaSource->seek(back_step); + //mMediaSource->start(-2.0); + } + else + { + mMediaSource->browse_back(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateForward() +{ + if (mMediaSource) { - mMediaSource->loadURI( mHomeURL ); + if(mMediaSource->pluginSupportsMediaTime()) + { + F64 step_scale = 0.02; // temp , can be changed + F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale); + if(forward_step > mMediaSource->getDuration()) + { + forward_step = mMediaSource->getDuration(); + } + mMediaSource->seek(forward_step); + //mMediaSource->start(2.0); + } + else + { + mMediaSource->browse_forward(); + } } } ////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateReload() +{ + navigateTo(mMediaURL, "", true, false); +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::navigateHome() +{ + navigateTo(mHomeURL, "", true, false); +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) { + // Helpful to have media urls in log file. Shouldn't be spammy. + llinfos << "url=" << url << " mime_type=" << mime_type << llendl; + if(server_request) { setNavState(MEDIANAVSTATE_SERVER_SENT); @@ -1026,12 +1095,16 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi setNavState(MEDIANAVSTATE_NONE); } - // Always set the current URL. + // Always set the current URL and MIME type. mMediaURL = url; + mMimeType = mime_type; // If the current URL is not null, make the instance do a navigate on load. mDoNavigateOnLoad = !mMediaURL.empty(); + // if mime type discovery was requested, we'll need to do it when the media loads + mDoNavigateOnLoadRediscoverType = rediscover_type; + // and if this was a server request, the navigate on load will also need to be one. mDoNavigateOnLoadServerRequest = server_request; @@ -1042,6 +1115,21 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi return; } + + // If the caller has specified a non-empty MIME type, look that up in our MIME types list. + // If we have a plugin for that MIME type, use that instead of attempting auto-discovery. + // This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type + // but the parcel owner has correctly set the MIME type in the parcel media settings. + + if(!mMimeType.empty() && (mMimeType != "none/none")) + { + std::string plugin_basename = LLMIMETypes::implType(mMimeType); + if(!plugin_basename.empty()) + { + // We have a plugin for this mime type + rediscover_type = false; + } + } if(rediscover_type) { @@ -1101,10 +1189,41 @@ void LLViewerMediaImpl::navigateStop() bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) { bool result = false; + // *NOTE:Mani - if this doesn't exist llmozlib goes crashy in the debug build. + // LLMozlib::init wants to write some files to <exe_dir>/components + std::string debug_init_component_dir( gDirUtilp->getExecutableDir() ); + debug_init_component_dir += "/components"; + LLAPRFile::makeDir(debug_init_component_dir.c_str()); if (mMediaSource) { - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + if( MASK_CONTROL & mask ) + { + if( 'C' == key ) + { + mMediaSource->copy(); + result = true; + } + else + if( 'V' == key ) + { + mMediaSource->paste(); + result = true; + } + else + if( 'X' == key ) + { + mMediaSource->cut(); + result = true; + } + } + + if(!result) + { + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + } } return result; @@ -1117,7 +1236,12 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) if (mMediaSource) { - mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char))); + // only accept 'printable' characters, sigh... + if (uni_char >= 32 // discard 'control' characters + && uni_char != 127) // SDL thinks this is 'delete' - yuck. + { + mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char))); + } } return result; @@ -1148,7 +1272,7 @@ bool LLViewerMediaImpl::canNavigateBack() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::update() { - if(mMediaSource == NULL) + if(mMediaSource == NULL && !mMediaSourceFailedInit) { if(mPriority != LLPluginClassMedia::PRIORITY_UNLOADED) { @@ -1375,6 +1499,18 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla { switch(event) { + case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: + { + // The plugin failed to load properly. Make sure the timer doesn't retry. + mMediaSourceFailedInit = true; + + // TODO: may want a different message for this case? + LLSD args; + args["PLUGIN"] = LLMIMETypes::implType(mMimeType); + LLNotifications::instance().add("MediaPluginFailed", args); + } + break; + case MEDIA_EVENT_PLUGIN_FAILED: { LLSD args; @@ -1423,7 +1559,19 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: { LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL; - setNavState(MEDIANAVSTATE_NONE); + + if(getNavState() == MEDIANAVSTATE_BEGUN) + { + setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED); + } + else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN) + { + setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED); + } + else + { + // all other cases need to leave the state alone. + } } break; @@ -1536,8 +1684,7 @@ void LLViewerMediaImpl::calculateInterest() } else { - // I don't think this case should ever be hit. - LL_WARNS("Plugin") << "no texture!" << LL_ENDL; + // This will be a relatively common case now, since it will always be true for unloaded media. mInterest = 0.0f; } } @@ -1626,9 +1773,11 @@ void LLViewerMediaImpl::setNavState(EMediaNavState state) case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break; case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break; case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break; + case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break; case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break; case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break; case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break; + case MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break; } } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index c9ba5841e9..fc2776ee91 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -141,7 +141,10 @@ public: void mouseMove(const LLVector2& texture_coords); void mouseLeftDoubleClick(S32 x,S32 y ); void mouseCapture(); - + + void navigateBack(); + void navigateForward(); + void navigateReload(); void navigateHome(); void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false); void navigateStop(); @@ -240,12 +243,14 @@ public: typedef enum { - MEDIANAVSTATE_NONE, // State is outside what we need to track for navigation. - MEDIANAVSTATE_BEGUN, // a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed - MEDIANAVSTATE_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a non-server-directed BEGIN - MEDIANAVSTATE_SERVER_SENT, // server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet - MEDIANAVSTATE_SERVER_BEGUN, // MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed - MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED // first LOCATION_CHANGED event after a server-directed BEGIN + MEDIANAVSTATE_NONE, // State is outside what we need to track for navigation. + MEDIANAVSTATE_BEGUN, // a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed + MEDIANAVSTATE_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a non-server-directed BEGIN + MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED, // we received a NAVIGATE_COMPLETE event before the first LOCATION_CHANGED + MEDIANAVSTATE_SERVER_SENT, // server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet + MEDIANAVSTATE_SERVER_BEGUN, // MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed + MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a server-directed BEGIN + MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED // we received a NAVIGATE_COMPLETE event before the first LOCATION_CHANGED }EMediaNavState; @@ -278,7 +283,9 @@ public: bool mHasFocus; LLPluginClassMedia::EPriority mPriority; bool mDoNavigateOnLoad; + bool mDoNavigateOnLoadRediscoverType; bool mDoNavigateOnLoadServerRequest; + bool mMediaSourceFailedInit; private: diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index f9377ab37b..cad8b5f0ce 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -53,7 +53,8 @@ // LLViewerMediaFocus::LLViewerMediaFocus() -: mMouseOverFlag(false) +: mFocusedObjectFace(0), + mHoverObjectFace(0) { } @@ -63,110 +64,100 @@ LLViewerMediaFocus::~LLViewerMediaFocus() // Clean up in cleanupClass() instead. } -void LLViewerMediaFocus::cleanupClass() -{ - LLViewerMediaFocus *self = LLViewerMediaFocus::getInstance(); - - if(self) - { - // mMediaHUD will have been deleted by this point -- don't try to delete it. - - /* Richard says: - all widgets are supposed to be destroyed at the same time - you shouldn't hold on to pointer to them outside of ui code - you can use the LLHandle approach - if you want to be type safe, you'll need to add a LLRootHandle to whatever derived class you are pointing to - look at llview::gethandle - its our version of a weak pointer - */ - if(self->mMediaHUD.get()) - { - self->mMediaHUD.get()->setMediaImpl(NULL); - } - self->mMediaImpl = NULL; - } - -} - - -void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl ) -{ +void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal) +{ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - - if(mMediaImpl.notNull()) + + LLViewerMediaImpl *old_media_impl = getFocusedMediaImpl(); + if(old_media_impl) { - mMediaImpl->focus(false); + old_media_impl->focus(false); } - if (b && media_impl.notNull()) + if (media_impl.notNull() && objectp.notNull()) { bool face_auto_zoom = false; - mMediaImpl = media_impl; - mMediaImpl->focus(true); + media_impl->focus(true); - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->selectObjectOnly(objectp, face); + mFocusedImplID = media_impl->getMediaTextureID(); + mFocusedObjectID = objectp->getID(); + mFocusedObjectFace = face; + mFocusedObjectNormal = pick_normal; - if(objectp.notNull()) + LLTextureEntry* tep = objectp->getTE(face); + if(tep->hasMedia()) { - LLTextureEntry* tep = objectp->getTE(face); - if(! tep->hasMedia()) - { - // Error condition - } LLMediaEntry* mep = tep->getMediaData(); face_auto_zoom = mep->getAutoZoom(); - if(! mep->getAutoPlay()) + if(!media_impl->hasMedia()) { std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL(); media_impl->navigateTo(url, "", true); } } - mFocus = LLSelectMgr::getInstance()->getSelection(); + else + { + // This should never happen. + llwarns << "Can't find media entry for focused face" << llendl; + } + + gFocusMgr.setKeyboardFocus(this); + + // We must do this before processing the media HUD zoom, or it may zoom to the wrong face. + update(); + if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom()) { mMediaHUD.get()->resetZoomLevel(); mMediaHUD.get()->nextZoomLevel(); } - if (!mFocus->isEmpty()) - { - gFocusMgr.setKeyboardFocus(this); - } - mObjectID = objectp->getID(); - mObjectFace = face; - // LLViewerMedia::addObserver(this, mObjectID); - - } else { - gFocusMgr.setKeyboardFocus(NULL); - if(! parcel->getMediaPreventCameraZoom()) + if(hasFocus()) { - if (!mFocus->isEmpty()) + if(mMediaHUD.get()) { - gAgent.setFocusOnAvatar(TRUE, ANIMATE); + mMediaHUD.get()->resetZoomLevel(); } + + gFocusMgr.setKeyboardFocus(NULL); } - mFocus = NULL; - // LLViewerMedia::remObserver(this, mObjectID); - // Null out the media hud media pointer - if(mMediaHUD.get()) - { - mMediaHUD.get()->setMediaImpl(NULL); - } + mFocusedImplID = LLUUID::null; + mFocusedObjectID = LLUUID::null; + mFocusedObjectFace = 0; + } +} - // and null out the media impl - mMediaImpl = NULL; - mObjectID = LLUUID::null; - mObjectFace = 0; +void LLViewerMediaFocus::clearFocus() +{ + setFocusFace(NULL, 0, NULL); +} + +void LLViewerMediaFocus::setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal) +{ + if (media_impl.notNull()) + { + mHoverImplID = media_impl->getMediaTextureID(); + mHoverObjectID = objectp->getID(); + mHoverObjectFace = face; + mHoverObjectNormal = pick_normal; } - if(mMediaHUD.get()) + else { - mMediaHUD.get()->setMediaFocus(b); + mHoverObjectID = LLUUID::null; + mHoverObjectFace = 0; + mHoverImplID = LLUUID::null; } } + +void LLViewerMediaFocus::clearHover() +{ + setHoverFace(NULL, 0, NULL); +} + + bool LLViewerMediaFocus::getFocus() { if (gFocusMgr.getKeyboardFocus() == this) @@ -176,22 +167,15 @@ bool LLViewerMediaFocus::getFocus() return false; } -// This function selects an ideal viewing distance given a selection bounding box, normal, and padding value -void LLViewerMediaFocus::setCameraZoom(F32 padding_factor) +// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value +void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor) { - LLPickInfo& pick = LLToolPie::getInstance()->getPick(); - - if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - pick = mPickInfo; - setFocusFace(true, pick.getObject(), pick.mObjectFace, mMediaImpl); - } - - if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) + if (object) { gAgent.setFocusOnAvatar(FALSE, ANIMATE); - LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + LLBBox bbox = object->getBoundingBoxAgent(); + LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); F32 height; F32 width; F32 depth; @@ -199,7 +183,7 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor) F32 distance; // We need the aspect ratio, and the 3 components of the bbox as height, width, and depth. - F32 aspect_ratio = getBBoxAspectRatio(selection_bbox, pick.mNormal, &height, &width, &depth); + F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth); F32 camera_aspect = LLViewerCamera::getInstance()->getAspect(); // We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for @@ -227,84 +211,97 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor) distance += depth * 0.5; // Finally animate the camera to this new position and focal point - gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(pick.mNormal * distance), - LLSelectMgr::getInstance()->getSelectionCenterGlobal(), LLSelectMgr::getInstance()->getSelection()->getFirstObject()->mID ); + LLVector3d camera_pos, target_pos; + // The target lookat position is the center of the selection (in global coords) + target_pos = center; + // Target look-from (camera) position is "distance" away from the target along the normal + LLVector3d pickNormal = LLVector3d(normal); + pickNormal.normalize(); + camera_pos = target_pos + pickNormal * distance; + if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg) + { + // If the normal points directly up, the camera will "flip" around. + // We try to avoid this by adjusting the target camera position a + // smidge towards current camera position + // *NOTE: this solution is not perfect. All it attempts to solve is the + // "looking down" problem where the camera flips around when it animates + // to that position. You still are not guaranteed to be looking at the + // media in the correct orientation. What this solution does is it will + // put the camera into position keeping as best it can the current + // orientation with respect to the face. In other words, if before zoom + // the media appears "upside down" from the camera, after zooming it will + // still be upside down, but at least it will not flip. + LLVector3d cur_camera_pos = LLVector3d(gAgent.getCameraPositionGlobal()); + LLVector3d delta = (cur_camera_pos - camera_pos); + F64 len = delta.length(); + delta.normalize(); + // Move 1% of the distance towards original camera location + camera_pos += 0.01 * len * delta; + } + + gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() ); + } + else + { + // If we have no object, focus back on the avatar. + gAgent.setFocusOnAvatar(TRUE, ANIMATE); } } void LLViewerMediaFocus::onFocusReceived() { - if(mMediaImpl.notNull()) - mMediaImpl->focus(true); + // Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media. +// LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +// if(media_impl.notNull()) +// media_impl->focus(true); LLFocusableElement::onFocusReceived(); } void LLViewerMediaFocus::onFocusLost() { - if(mMediaImpl.notNull()) - mMediaImpl->focus(false); + // Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media. +// LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); +// if(media_impl.notNull()) +// media_impl->focus(false); + gViewerWindow->focusClient(); - mFocus = NULL; LLFocusableElement::onFocusLost(); } -void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl) + +BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - if (b && media_impl.notNull()) + LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); + if(media_impl) { - if(! mMediaHUD.get()) - { - LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(mMediaImpl); - mMediaHUD = media_hud->getHandle(); - gHUDView->addChild(media_hud); - } - mMediaHUD.get()->setMediaImpl(media_impl); + media_impl->handleKeyHere(key, mask); - if(mMediaImpl.notNull() && (mMediaImpl != media_impl)) + if (key == KEY_ESCAPE) { - mMediaImpl->focus(false); + clearFocus(); } - - mMediaImpl = media_impl; } - mMouseOverFlag = b; -} -LLUUID LLViewerMediaFocus::getSelectedUUID() -{ - LLViewerObject* object = mFocus->getFirstObject(); - return object ? object->getID() : LLUUID::null; -} -#if 0 // Must re-implement when the new media api event system is ready -void LLViewerMediaFocus::onNavigateComplete( const EventType& event_in ) -{ - if (hasFocus() && mLastURL != event_in.getStringValue()) - { - LLViewerMedia::focus(true, mObjectID); - // spoof mouse event to reassert focus - LLViewerMedia::mouseDown(1,1, mObjectID); - LLViewerMedia::mouseUp(1,1, mObjectID); - } - mLastURL = event_in.getStringValue(); -} -#endif -BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) -{ - if(mMediaImpl.notNull()) - mMediaImpl->handleKeyHere(key, mask); + return true; } BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { - if(mMediaImpl.notNull()) - mMediaImpl->handleUnicodeCharHere(uni_char); + LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); + if(media_impl) + media_impl->handleUnicodeCharHere(uni_char); return true; } BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) { BOOL retval = FALSE; - if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia()) + LLViewerMediaImpl* media_impl = getFocusedMediaImpl(); + if(media_impl && media_impl->hasMedia()) { - mMediaImpl->getMediaPlugin()->scrollEvent(x, y, clicks); + // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y. + // The latter is the position of the mouse at the time of the event + // The former is the 'scroll amount' in x and y, respectively. + // All we have for 'scroll amount' here is 'clicks', and no mask. + media_impl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0); retval = TRUE; } return retval; @@ -312,19 +309,45 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) void LLViewerMediaFocus::update() { - if (mMediaHUD.get()) + LLViewerMediaImpl *media_impl = getFocusedMediaImpl(); + LLViewerObject *viewer_object = getFocusedObject(); + S32 face = mFocusedObjectFace; + LLVector3 normal = mFocusedObjectNormal; + bool focus = true; + + if(!media_impl || !viewer_object) { - if(mFocus.notNull() || mMouseOverFlag || mMediaHUD.get()->isMouseOver()) + focus = false; + media_impl = getHoverMediaImpl(); + viewer_object = getHoverObject(); + face = mHoverObjectFace; + normal = mHoverObjectNormal; + } + + if(media_impl && viewer_object) + { + // We have an object and impl to point at. + + // Make sure the media HUD object exists. + if(! mMediaHUD.get()) { - // mMediaHUD.get()->setVisible(true); - mMediaHUD.get()->updateShape(); + LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(); + mMediaHUD = media_hud->getHandle(); + gHUDView->addChild(media_hud); } - else + mMediaHUD.get()->setMediaFace(viewer_object, face, media_impl, normal); + } + else + { + // The media HUD is no longer needed. + if(mMediaHUD.get()) { - mMediaHUD.get()->setVisible(false); + mMediaHUD.get()->setMediaFace(NULL, 0, NULL); } } } + + // This function calculates the aspect ratio and the world aligned components of a selection bounding box. F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth) { @@ -393,5 +416,31 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face) { - return objectp->getID() == mObjectID && face == mObjectFace; + return objectp->getID() == mFocusedObjectID && face == mFocusedObjectFace; +} + +bool LLViewerMediaFocus::isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face) +{ + return objectp->getID() == mHoverObjectID && face == mHoverObjectFace; +} + + +LLViewerMediaImpl* LLViewerMediaFocus::getFocusedMediaImpl() +{ + return LLViewerMedia::getMediaImplFromTextureID(mFocusedImplID); +} + +LLViewerObject* LLViewerMediaFocus::getFocusedObject() +{ + return gObjectList.findObject(mFocusedObjectID); +} + +LLViewerMediaImpl* LLViewerMediaFocus::getHoverMediaImpl() +{ + return LLViewerMedia::getMediaImplFromTextureID(mHoverImplID); +} + +LLViewerObject* LLViewerMediaFocus::getHoverObject() +{ + return gObjectList.findObject(mHoverObjectID); } diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index 2688a8b708..c77533ba5a 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -50,44 +50,55 @@ public: LLViewerMediaFocus(); ~LLViewerMediaFocus(); - static void cleanupClass(); - - void setFocusFace(BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl); - void clearFocus() { setFocusFace(false, NULL, 0, NULL); } + // Set/clear the face that has media focus (takes keyboard input and has the full set of controls) + void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero); + void clearFocus(); + + // Set/clear the face that has "media hover" (has the mimimal set of controls to zoom in or pop out into a media browser). + // If a media face has focus, the media hover will be ignored. + void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero); + void clearHover(); + /*virtual*/ bool getFocus(); - /*virtual*/ // void onNavigateComplete( const EventType& event_in ); - /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - LLUUID getSelectedUUID(); - LLObjectSelectionHandle getSelection() { return mFocus; } - void update(); + + static void setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor); + static F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth); - void setCameraZoom(F32 padding_factor); - void setMouseOverFlag(bool b, viewer_media_t media_impl = NULL); - bool getMouseOverFlag() { return mMouseOverFlag; } - void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; } - F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth); - - // TODO: figure out why selection mgr hates me bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face); + bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face); + + // These look up (by uuid) and return the values that were set with setFocusFace. They will return null if the objects have been destroyed. + LLViewerMediaImpl* getFocusedMediaImpl(); + LLViewerObject* getFocusedObject(); + S32 getFocusedFace() { return mFocusedObjectFace; } + + // These look up (by uuid) and return the values that were set with setHoverFace. They will return null if the objects have been destroyed. + LLViewerMediaImpl* getHoverMediaImpl(); + LLViewerObject* getHoverObject(); + S32 getHoverFace() { return mHoverObjectFace; } protected: /*virtual*/ void onFocusReceived(); /*virtual*/ void onFocusLost(); private: - LLObjectSelectionHandle mFocus; - std::string mLastURL; - bool mMouseOverFlag; - LLPickInfo mPickInfo; + LLHandle<LLPanelMediaHUD> mMediaHUD; - LLUUID mObjectID; - S32 mObjectFace; - viewer_media_t mMediaImpl; + + LLUUID mFocusedObjectID; + S32 mFocusedObjectFace; + LLUUID mFocusedImplID; + LLVector3 mFocusedObjectNormal; + + LLUUID mHoverObjectID; + S32 mHoverObjectFace; + LLUUID mHoverImplID; + LLVector3 mHoverObjectNormal; }; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index dc291d6c34..a1c15d9d0f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -206,6 +206,7 @@ #include "llwaterparammanager.h" #include "llfloaternotificationsconsole.h" #include "llfloatercamera.h" +#include "lluilistener.h" #include "lltexlayer.h" #include "llappearancemgr.h" @@ -413,6 +414,8 @@ public: static LLMenuParcelObserver* gMenuParcelObserver = NULL; +static LLUIListener sUIListener("UI"); + LLMenuParcelObserver::LLMenuParcelObserver() { LLViewerParcelMgr::getInstance()->addObserver(this); @@ -7064,7 +7067,7 @@ void force_error_bad_memory_access(void *) void force_error_infinite_loop(void *) { - LLAppViewer::instance()->forceErrorInifiniteLoop(); + LLAppViewer::instance()->forceErrorInfiniteLoop(); } void force_error_software_exception(void *) diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 918b15ef09..801c46035a 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -35,6 +35,8 @@ #include "llviewernetwork.h" #include "llviewercontrol.h" +#include "llevents.h" +#include "lllogin.h" struct LLGridData { @@ -155,6 +157,10 @@ LLViewerLogin::LLViewerLogin() : { } + LLViewerLogin::~LLViewerLogin() + { + } + void LLViewerLogin::setGridChoice(EGridInfo grid) { if(grid < 0 || grid >= GRID_INFO_COUNT) diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 4001ed05c1..edae6dc47b 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -34,7 +34,10 @@ #ifndef LL_LLVIEWERNETWORK_H #define LL_LLVIEWERNETWORK_H +#include <boost/scoped_ptr.hpp> + class LLHost; +class LLLogin; enum EGridInfo { @@ -74,6 +77,7 @@ class LLViewerLogin : public LLSingleton<LLViewerLogin> { public: LLViewerLogin(); + ~LLViewerLogin(); void setGridChoice(EGridInfo grid); void setGridChoice(const std::string& grid_name); diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index a3f9c839a0..6233a337a6 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -226,11 +226,13 @@ void LLViewerParcelMedia::play(LLParcel* parcel) media_height, media_auto_scale, media_loop); - sMediaImpl->navigateTo(media_url); + sMediaImpl->navigateTo(media_url, mime_type, true); } } else { + LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL; + // There is no media impl, make a new one sMediaImpl = LLViewerMedia::newMediaImpl( placeholder_texture_id, @@ -238,7 +240,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel) media_height, media_auto_scale, media_loop); - sMediaImpl->navigateTo(media_url); + sMediaImpl->navigateTo(media_url, mime_type, true); } LLFirstUse::useMedia(); @@ -544,6 +546,18 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL; }; break; + + case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_NAME_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; + }; + break; }; } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 7ca11d8364..77b023f6dd 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -56,6 +56,7 @@ #include "llparcelselection.h" #include "llresmgr.h" #include "llsdutil.h" +#include "llsdutil_math.h" #include "llstatusbar.h" #include "llui.h" #include "llviewertexture.h" @@ -1161,10 +1162,11 @@ void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info) msg->sendReliable(info->mHost); } -void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info) +void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo* *info) { - delete info; - info = NULL; + // Must be here because ParcelBuyInfo is local to this .cpp file + delete *info; + *info = NULL; } void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id) diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 3964a56bf6..1c8fe23dba 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -246,7 +246,7 @@ public: BOOL remove_contribution); // callers responsibility to call deleteParcelBuy() on return value void sendParcelBuy(ParcelBuyInfo*); - void deleteParcelBuy(ParcelBuyInfo*&); + void deleteParcelBuy(ParcelBuyInfo* *info); void sendParcelDeed(const LLUUID& group_id); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a0ab4cb1e6..e5c53c91c9 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -191,25 +191,25 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( const LLUUID &image_id, BOOL usemipmaps, - BOOL level_immediate, + S32 boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, LLHost request_from_host) { - return gTextureList.getImage(image_id, usemipmaps, level_immediate, texture_type, internal_format, primary_format, request_from_host) ; + return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( const std::string& filename, BOOL usemipmaps, - BOOL level_immediate, + S32 boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, const LLUUID& force_id) { - return gTextureList.getImageFromFile(filename, usemipmaps, level_immediate, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) @@ -2434,10 +2434,11 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) void LLViewerMediaTexture::stopPlaying() { - if(mMediaImplp) - { - mMediaImplp->stop() ; - } + // Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser). +// if(mMediaImplp) +// { +// mMediaImplp->stop() ; +// } mIsPlaying = FALSE ; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 596bfea670..480e1c1cbc 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -118,10 +118,10 @@ public: BOOST_SELECTED = 12, BOOST_HUD = 13, BOOST_AVATAR_BAKED_SELF = 14, - BOOST_UI = 15, - BOOST_PREVIEW = 16, - BOOST_MAP = 17, - BOOST_MAP_LAYER = 18, + BOOST_ICON = 15, + BOOST_UI = 16, + BOOST_PREVIEW = 17, + BOOST_MAP = 18, BOOST_AVATAR_SELF = 19, // needed for baking avatar BOOST_MAX_LEVEL }; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 4ad4c8e1ea..b5986c70f5 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -111,10 +111,10 @@ void LLViewerTextureList::doPreloadImages() LL_DEBUGS("ViewerImages") << "Preloading images..." << LL_ENDL; // Set the "missing asset" image - LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, IMMEDIATE_YES); + LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); // Set the "white" image - LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, IMMEDIATE_YES); + LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); LLUIImageList* image_list = LLUIImageList::getInstance(); @@ -131,31 +131,31 @@ void LLViewerTextureList::doPreloadImages() // prefetch specific UUIDs LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE); LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, IMMEDIATE_YES); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", MIPMAP_YES, IMMEDIATE_YES); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", MIPMAP_YES, IMMEDIATE_YES); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, IMMEDIATE_YES); + image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, IMMEDIATE_YES, LLViewerTexture::FETCHED_TEXTURE, + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903")); if (image) { @@ -315,7 +315,7 @@ void LLViewerTextureList::restoreGL() LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, BOOL usemipmaps, - BOOL level_immediate, + S32 boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, @@ -369,10 +369,14 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& addImage(imagep); - if (level_immediate) + if (boost_priority != 0) { - imagep->dontDiscard(); - imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI); + if (boost_priority == LLViewerFetchedTexture::BOOST_UI || + boost_priority == LLViewerFetchedTexture::BOOST_ICON) + { + imagep->dontDiscard(); + } + imagep->setBoostLevel(boost_priority); } } @@ -384,7 +388,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, BOOL usemipmaps, - BOOL level_immediate, + S32 boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, @@ -403,7 +407,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, if (imagep.isNull()) { - imagep = createImage(image_id, usemipmaps, level_immediate, texture_type, internal_format, primary_format, request_from_host) ; + imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } imagep->setGLTextureCreated(true); @@ -414,7 +418,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, //when this function is called, there is no such texture in the gTextureList with image_id. LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, BOOL usemipmaps, - BOOL level_immediate, + S32 boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, @@ -443,16 +447,20 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, addImage(imagep); - if (level_immediate) + if (boost_priority != 0) { - imagep->dontDiscard(); - imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI); + if (boost_priority == LLViewerFetchedTexture::BOOST_UI || + boost_priority == LLViewerFetchedTexture::BOOST_ICON) + { + imagep->dontDiscard(); + } + imagep->setBoostLevel(boost_priority); } else { //by default, the texure can not be removed from memory even if it is not used. //here turn this off - //if this texture should be set to NO_DELETE, either pass level_immediate == TRUE here, or call setNoDelete() afterwards. + //if this texture should be set to NO_DELETE, call setNoDelete() afterwards. imagep->forceActive() ; } @@ -1286,7 +1294,7 @@ void LLUIImageList::cleanUp() mUITextureList.clear() ; } -LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id) +LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority) { // use id as image name std::string image_name = image_id.asString(); @@ -1298,10 +1306,12 @@ LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id) return found_it->second; } - return loadUIImageByID(image_id); + const BOOL use_mips = FALSE; + const LLRect scale_rect = LLRect::null; + return loadUIImageByID(image_id, use_mips, scale_rect, priority); } -LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name) +LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priority) { // look for existing image uuid_ui_image_map_t::iterator found_it = mUIImages.find(image_name); @@ -1310,18 +1320,24 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name) return found_it->second; } - return loadUIImageByName(image_name, image_name); + const BOOL use_mips = FALSE; + const LLRect scale_rect = LLRect::null; + return loadUIImageByName(image_name, image_name, use_mips, scale_rect, priority); } -LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect) +LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, + BOOL use_mips, const LLRect& scale_rect, S32 boost_priority ) { - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, IMMEDIATE_YES); + if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI; + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority); return loadUIImage(imagep, name, use_mips, scale_rect); } -LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, BOOL use_mips, const LLRect& scale_rect) +LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, + BOOL use_mips, const LLRect& scale_rect, S32 boost_priority) { - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, IMMEDIATE_YES); + if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI; + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority); return loadUIImage(imagep, id.asString(), use_mips, scale_rect); } @@ -1332,11 +1348,11 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st imagep->setAddressMode(LLTexUnit::TAM_CLAMP); //all UI images are non-deletable - imagep->setNoDelete() ; + imagep->setNoDelete(); LLUIImagePtr new_imagep = new LLUIImage(name, imagep); mUIImages.insert(std::make_pair(name, new_imagep)); - mUITextureList.push_back(imagep) ; + mUITextureList.push_back(imagep); LLUIImageLoadData* datap = new LLUIImageLoadData; datap->mImageName = name; diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 11d1dd855f..fda57ce981 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -202,8 +202,8 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm { public: // LLImageProviderInterface - LLUIImagePtr getUIImageByID(const LLUUID& id); - LLUIImagePtr getUIImage(const std::string& name); + /*virtual*/ LLUIImagePtr getUIImageByID(const LLUUID& id, S32 priority); + /*virtual*/ LLUIImagePtr getUIImage(const std::string& name, S32 priority); void cleanUp(); bool initFromFile(); @@ -212,8 +212,10 @@ public: static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); private: - LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null); - LLUIImagePtr loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null); + LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename, + BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0); + LLUIImagePtr loadUIImageByID(const LLUUID& id, + BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0); LLUIImagePtr loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5f95e9ccf1..c659e58e47 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -32,6 +32,10 @@ #include "llviewerprecompiledheaders.h" +#if LL_WINDOWS +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + // system library includes #include <stdio.h> #include <iostream> @@ -195,6 +199,7 @@ #include "llfloaternotificationsconsole.h" #include "llnearbychat.h" +#include "llviewerwindowlistener.h" #if LL_WINDOWS #include <tchar.h> // For Unicode conversion methods @@ -1204,7 +1209,8 @@ LLViewerWindow::LLViewerWindow( mResDirty(false), mStatesDirty(false), mIsFullscreenChecked(false), - mCurrResolutionIndex(0) + mCurrResolutionIndex(0), + mViewerWindowListener(new LLViewerWindowListener("LLViewerWindow", this)) { LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); @@ -1627,7 +1633,11 @@ void LLViewerWindow::shutdownViews() { gMorphView->setVisible(FALSE); } - + + // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open + // will crump with LL_ERRS. + LLModalDialog::shutdownModals(); + // Delete all child views. delete mRootView; mRootView = NULL; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 231b857d1f..d7c403739e 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -53,6 +53,8 @@ #include <boost/function.hpp> #include <boost/signals2.hpp> +#include <boost/scoped_ptr.hpp> + class LLView; class LLViewerObject; @@ -65,6 +67,7 @@ class LLImageRaw; class LLHUDIcon; class LLWindow; class LLRootView; +class LLViewerWindowListener; #define PICK_HALF_WIDTH 5 #define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1) @@ -456,6 +459,8 @@ protected: bool mIsFullscreenChecked; // Did the user check the fullscreen checkbox in the display settings U32 mCurrResolutionIndex; + boost::scoped_ptr<LLViewerWindowListener> mViewerWindowListener; + protected: static std::string sSnapshotBaseName; static std::string sSnapshotDir; diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp new file mode 100644 index 0000000000..317e361c80 --- /dev/null +++ b/indra/newview/llviewerwindowlistener.cpp @@ -0,0 +1,87 @@ +/** + * @file llviewerwindowlistener.cpp + * @author Nat Goodspeed + * @date 2009-06-30 + * @brief Implementation for llviewerwindowlistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llviewerwindowlistener.h" +// STL headers +#include <map> +// std headers +// external library headers +// other Linden headers +#include "llviewerwindow.h" + +LLViewerWindowListener::LLViewerWindowListener(const std::string& pumpname, LLViewerWindow* llviewerwindow): + LLDispatchListener(pumpname, "op"), + mViewerWindow(llviewerwindow) +{ + // add() every method we want to be able to invoke via this event API. + LLSD saveSnapshotArgs; + saveSnapshotArgs["filename"] = LLSD::String(); + saveSnapshotArgs["reply"] = LLSD::String(); + // The following are optional, so don't build them into required prototype. +// saveSnapshotArgs["width"] = LLSD::Integer(); +// saveSnapshotArgs["height"] = LLSD::Integer(); +// saveSnapshotArgs["showui"] = LLSD::Boolean(); +// saveSnapshotArgs["rebuild"] = LLSD::Boolean(); +// saveSnapshotArgs["type"] = LLSD::String(); + add("saveSnapshot", &LLViewerWindowListener::saveSnapshot, saveSnapshotArgs); + add("requestReshape", &LLViewerWindowListener::requestReshape); +} + +void LLViewerWindowListener::saveSnapshot(const LLSD& event) const +{ + LLReqID reqid(event); + typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap; + TypeMap types; +#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name + tp(COLOR); + tp(DEPTH); + tp(OBJECT_ID); +#undef tp + // Our add() call should ensure that the incoming LLSD does in fact + // contain our required arguments. Deal with the optional ones. + S32 width (mViewerWindow->getWindowDisplayWidth()); + S32 height(mViewerWindow->getWindowDisplayHeight()); + if (event.has("width")) + width = event["width"].asInteger(); + if (event.has("height")) + height = event["height"].asInteger(); + // showui defaults to true, requiring special treatment + bool showui = true; + if (event.has("showui")) + showui = event["showui"].asBoolean(); + bool rebuild(event["rebuild"]); // defaults to false + LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR); + if (event.has("type")) + { + TypeMap::const_iterator found = types.find(event["type"]); + if (found == types.end()) + { + LL_ERRS("LLViewerWindowListener") << "LLViewerWindowListener::saveSnapshot(): " + << "unrecognized type " << event["type"] << LL_ENDL; + } + type = found->second; + } + bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, rebuild, type); + LLSD response(reqid.makeResponse()); + response["ok"] = ok; + LLEventPumps::instance().obtain(event["reply"]).post(response); +} + +void LLViewerWindowListener::requestReshape(LLSD const & event_data) const +{ + if(event_data.has("w") && event_data.has("h")) + { + mViewerWindow->reshape(event_data["w"].asInteger(), event_data["h"].asInteger()); + } +} diff --git a/indra/newview/llviewerwindowlistener.h b/indra/newview/llviewerwindowlistener.h new file mode 100644 index 0000000000..59c636ecec --- /dev/null +++ b/indra/newview/llviewerwindowlistener.h @@ -0,0 +1,35 @@ +/** + * @file llviewerwindowlistener.h + * @author Nat Goodspeed + * @date 2009-06-30 + * @brief Event API for subset of LLViewerWindow methods + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLVIEWERWINDOWLISTENER_H) +#define LL_LLVIEWERWINDOWLISTENER_H + +#include "lleventdispatcher.h" + +class LLViewerWindow; +class LLSD; + +/// Listen on an LLEventPump with specified name for LLViewerWindow request events. +class LLViewerWindowListener: public LLDispatchListener +{ +public: + /// Specify the pump name on which to listen, and bind the LLViewerWindow + /// instance to use (e.g. gViewerWindow). + LLViewerWindowListener(const std::string& pumpname, LLViewerWindow* llviewerwindow); + +private: + void saveSnapshot(const LLSD& event) const; + void requestReshape(LLSD const & event_data) const; + + LLViewerWindow* mViewerWindow; +}; + +#endif /* ! defined(LL_LLVIEWERWINDOWLISTENER_H) */ diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 469aef6209..a402aff8ab 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -30,6 +30,12 @@ * $/LicenseInfo$ */ +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif + #include "llviewerprecompiledheaders.h" #include "llvoavatar.h" @@ -87,7 +93,12 @@ #include "llvoiceclient.h" #include "llvoicevisualizer.h" // Ventrella -#include "boost/lexical_cast.hpp" +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +#include <boost/lexical_cast.hpp> using namespace LLVOAvatarDefines; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 964b16df04..4760d5a472 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -30,6 +30,12 @@ * $/LicenseInfo$ */ +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif + #include "llviewerprecompiledheaders.h" #include "llvoavatarself.h" @@ -84,7 +90,12 @@ #include "llvoicevisualizer.h" // Ventrella #include "llappearancemgr.h" -#include "boost/lexical_cast.hpp" +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +#include <boost/lexical_cast.hpp> using namespace LLVOAvatarDefines; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index ca028269fe..02f63a848b 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -6921,7 +6921,8 @@ void LLVoiceClient::notifyFriendObservers() void LLVoiceClient::lookupName(const LLUUID &id) { - gCacheName->get(id, FALSE, &LLVoiceClient::onAvatarNameLookup); + BOOL is_group = FALSE; + gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup); } //static diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 583246c23e..d896e1f7db 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -91,6 +91,57 @@ LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles"); static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes"); +// Implementation class of LLMediaDataClientObject. See llmediadataclient.h +class LLMediaDataClientObjectImpl : public LLMediaDataClientObject +{ +public: + LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {} + LLMediaDataClientObjectImpl() { mObject = NULL; } + + virtual U8 getMediaDataCount() const + { return mObject->getNumTEs(); } + + virtual LLSD getMediaDataLLSD(U8 index) const + { + LLSD result; + LLTextureEntry *te = mObject->getTE(index); + if (NULL != te) + { + llassert((te->getMediaData() != NULL) == te->hasMedia()); + if (te->getMediaData() != NULL) + { + result = te->getMediaData()->asLLSD(); + } + } + return result; + } + + virtual LLUUID getID() const + { return mObject->getID(); } + + virtual void mediaNavigateBounceBack(U8 index) + { mObject->mediaNavigateBounceBack(index); } + + virtual bool hasMedia() const + { return mObject->hasMedia(); } + + virtual void updateObjectMediaData(LLSD const &data) + { mObject->updateObjectMediaData(data); } + + virtual F64 getDistanceFromAvatar() const + { return mObject->getRenderPosition().length(); } + + virtual F64 getTotalMediaInterest() const + { return mObject->getTotalMediaInterest(); } + + virtual std::string getCapabilityUrl(const std::string &name) const + { return mObject->getRegion()->getCapability(name); } + +private: + LLPointer<LLVOVolume> mObject; +}; + + LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLViewerObject(id, pcode, regionp), mVolumeImpl(NULL) @@ -134,8 +185,12 @@ LLVOVolume::~LLVOVolume() // static void LLVOVolume::initClass() { - sObjectMediaClient = new LLObjectMediaDataClient(); - sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(); + // gSavedSettings better be around + const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); + sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries); } // static @@ -319,13 +374,23 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, } } } - if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) { - // If the media changed at all, request new media data - if(mMedia) + if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) + { + // If only the media URL changed, and it isn't a media version URL, + // ignore it + if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && + mMedia && ! mMedia->mMediaURL.empty() && + ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) { - llinfos << "Media URL: " << mMedia->mMediaURL << llendl; + // If the media changed at all, request new media data + LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << + ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; + requestMediaDataUpdate(); } - requestMediaDataUpdate(); + else { + LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << + ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; + } } // ...and clean up any media impls cleanUpMediaImpls(); @@ -1624,7 +1689,7 @@ bool LLVOVolume::hasMedia() const void LLVOVolume::requestMediaDataUpdate() { - sObjectMediaClient->fetchMedia(this); + sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this)); } void LLVOVolume::cleanUpMediaImpls() @@ -1703,6 +1768,119 @@ void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool m // << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; } +void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) +{ + // Find the media entry for this navigate + const LLMediaEntry* mep = NULL; + viewer_media_t impl = getMediaImpl(texture_index); + LLTextureEntry *te = getTE(texture_index); + if(te) + { + mep = te->getMediaData(); + } + + if (mep && impl) + { + std::string url = mep->getCurrentURL(); + if (url.empty()) + { + url = mep->getHomeURL(); + } + if (! url.empty()) + { + LL_INFOS("LLMediaDataClient") << "bouncing back to URL: " << url << LL_ENDL; + impl->navigateTo(url, "", false, true); + } + } +} + +bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type) +{ + // NOTE: This logic duplicates the logic in the server (in particular, in llmediaservice.cpp). + if (NULL == media_entry ) return false; // XXX should we assert here? + + // The agent has permissions to navigate if: + // - agent has edit permissions, or + // - world permissions are on, or + // - group permissions are on, and agent_id is in the group, or + // - agent permissions are on, and agent_id is the owner + + if (permModify()) + { + return true; + } + + U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); + + // World permissions + if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) + { + return true; + } + + // Group permissions + else if (0 != (media_perms & LLMediaEntry::PERM_GROUP) && permGroupOwner()) + { + return true; + } + + // Owner permissions + else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) + { + return true; + } + + return false; + +} + +void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) +{ + bool block_navigation = false; + // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed + // to deal with multiple face indices. + int face_index = getFaceIndexWithMediaImpl(impl, -1); + + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getTE(face_index); + if(te) + { + mep = te->getMediaData(); + } + + if(mep) + { + if(!mep->checkCandidateUrl(new_location)) + { + block_navigation = true; + } + if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) + { + block_navigation = true; + } + } + else + { + llwarns << "Couldn't find media entry!" << llendl; + } + + if(block_navigation) + { + llinfos << "blocking navigate to URI " << new_location << llendl; + + // "bounce back" to the current URL from the media entry + mediaNavigateBounceBack(face_index); + } + else + { + + llinfos << "broadcasting navigate with URI " << new_location << llendl; + + sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location); + } +} + void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) { switch(event) @@ -1714,49 +1892,8 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, { case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast. - - bool block_navigation = false; - // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed - // to deal with multiple face indices. - int face_index = getFaceIndexWithMediaImpl(impl, -1); - std::string new_location = plugin->getLocation(); - - // Find the media entry for this navigate - LLMediaEntry* mep = NULL; - LLTextureEntry *te = getTE(face_index); - if(te) - { - mep = te->getMediaData(); - } - - if(mep) - { - if(!mep->checkCandidateUrl(new_location)) - { - block_navigation = true; - } - } - else - { - llwarns << "Couldn't find media entry!" << llendl; - } - - if(block_navigation) - { - llinfos << "blocking navigate to URI " << new_location << llendl; - - // "bounce back" to the current URL from the media entry - // NOTE: the only way block_navigation can be true is if we found the media entry, so we're guaranteed here that mep is not NULL. - impl->navigateTo(mep->getCurrentURL()); - } - else - { - - llinfos << "broadcasting navigate with URI " << new_location << llendl; - - sObjectMediaNavigateClient->navigate(this, face_index, new_location); - } + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getLocation()); } break; @@ -1773,6 +1910,29 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, } break; + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getNavigateURI()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: + // This is the the navigate complete event from a server-directed nav. Don't broadcast it. + llinfos << " NOT broadcasting navigate (server-directed)" << llendl; + break; + + default: + // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. + break; + } + } + break; + default: break; } @@ -1781,7 +1941,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, void LLVOVolume::sendMediaDataUpdate() { - sObjectMediaClient->updateMedia(this); + sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this)); } void LLVOVolume::removeMediaImpl(S32 texture_index) @@ -1874,6 +2034,22 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const return NULL; } +F64 LLVOVolume::getTotalMediaInterest() const +{ + F64 interest = (F64)0.0; + int i = 0; + const int end = getNumTEs(); + for ( ; i < end; ++i) + { + const viewer_media_t &impl = getMediaImpl(i); + if (!impl.isNull()) + { + interest += impl->getInterest(); + } + } + return interest; +} + S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) { S32 end = (S32)mMediaImplList.size() ; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 250c3ed917..00810b22c4 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -233,7 +233,23 @@ public: BOOL canBeFlexible() const; BOOL setIsFlexible(BOOL is_flexible); - void updateObjectMediaData(const LLSD &media_data_duples); + // Functions that deal with media, or media navigation + + // Update this object's media data with the given media data array + // (typically this is only called upon a response from a server request) + void updateObjectMediaData(const LLSD &media_data_array); + + // Bounce back media at the given index to its current URL (or home URL, if current URL is empty) + void mediaNavigateBounceBack(U8 texture_index); + + // Returns whether or not this object has permission to navigate or control + // the given media entry + enum MediaPermType { + MEDIA_PERM_INTERACT, MEDIA_PERM_CONTROL + }; + bool hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type); + + void mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location); void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event); // Sync the given media data with the impl and the given te @@ -244,6 +260,7 @@ public: viewer_media_t getMediaImpl(U8 face_id) const; S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id); + F64 getTotalMediaInterest() const; bool hasMedia() const; diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 3bbf4c2c47..8f74ea29ac 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "llagentwearables.h" #include "llfloatercustomize.h" +#include "lllocaltextureobject.h" #include "llviewertexturelist.h" #include "llinventorymodel.h" #include "llviewerregion.h" diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 3aad5c7378..823db027ee 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -368,7 +368,7 @@ void LLWorldMapView::draw() continue; } - current_image->setBoostLevel(LLViewerTexture::BOOST_MAP_LAYER); + current_image->setBoostLevel(LLViewerTexture::BOOST_MAP); current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY])); if (!current_image->hasGLTexture()) diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp new file mode 100644 index 0000000000..af8cb6b9fb --- /dev/null +++ b/indra/newview/llxmlrpclistener.cpp @@ -0,0 +1,496 @@ +/** + * @file llxmlrpclistener.cpp + * @author Nat Goodspeed + * @date 2009-03-18 + * @brief Implementation for llxmlrpclistener. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llxmlrpclistener.h" +// STL headers +#include <map> +#include <set> +// std headers +// external library headers +#include <boost/scoped_ptr.hpp> +#include <boost/range.hpp> // boost::begin(), boost::end() +// other Linden headers +#include "llerror.h" +#include "stringize.h" +#include "llxmlrpctransaction.h" + +#include <xmlrpc-epi/xmlrpc.h> + +#if LL_WINDOWS +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + +template <typename STATUS> +class StatusMapperBase +{ + typedef std::map<STATUS, std::string> MapType; + +public: + StatusMapperBase(const std::string& desc): + mDesc(desc) + {} + + std::string lookup(STATUS status) const + { + typename MapType::const_iterator found = mMap.find(status); + if (found != mMap.end()) + { + return found->second; + } + return STRINGIZE("<unknown " << mDesc << " " << status << ">"); + } + +protected: + std::string mDesc; + MapType mMap; +}; + +class StatusMapper: public StatusMapperBase<LLXMLRPCTransaction::EStatus> +{ +public: + StatusMapper(): StatusMapperBase<LLXMLRPCTransaction::EStatus>("Status") + { + mMap[LLXMLRPCTransaction::StatusNotStarted] = "NotStarted"; + mMap[LLXMLRPCTransaction::StatusStarted] = "Started"; + mMap[LLXMLRPCTransaction::StatusDownloading] = "Downloading"; + mMap[LLXMLRPCTransaction::StatusComplete] = "Complete"; + mMap[LLXMLRPCTransaction::StatusCURLError] = "CURLError"; + mMap[LLXMLRPCTransaction::StatusXMLRPCError] = "XMLRPCError"; + mMap[LLXMLRPCTransaction::StatusOtherError] = "OtherError"; + } +}; + +static const StatusMapper sStatusMapper; + +class CURLcodeMapper: public StatusMapperBase<CURLcode> +{ +public: + CURLcodeMapper(): StatusMapperBase<CURLcode>("CURLcode") + { + // from curl.h +// skip the "CURLE_" prefix for each of these strings +#define def(sym) (mMap[sym] = #sym + 6) + def(CURLE_OK); + def(CURLE_UNSUPPORTED_PROTOCOL); /* 1 */ + def(CURLE_FAILED_INIT); /* 2 */ + def(CURLE_URL_MALFORMAT); /* 3 */ + def(CURLE_URL_MALFORMAT_USER); /* 4 - NOT USED */ + def(CURLE_COULDNT_RESOLVE_PROXY); /* 5 */ + def(CURLE_COULDNT_RESOLVE_HOST); /* 6 */ + def(CURLE_COULDNT_CONNECT); /* 7 */ + def(CURLE_FTP_WEIRD_SERVER_REPLY); /* 8 */ + def(CURLE_FTP_ACCESS_DENIED); /* 9 a service was denied by the FTP server + due to lack of access - when login fails + this is not returned. */ + def(CURLE_FTP_USER_PASSWORD_INCORRECT); /* 10 - NOT USED */ + def(CURLE_FTP_WEIRD_PASS_REPLY); /* 11 */ + def(CURLE_FTP_WEIRD_USER_REPLY); /* 12 */ + def(CURLE_FTP_WEIRD_PASV_REPLY); /* 13 */ + def(CURLE_FTP_WEIRD_227_FORMAT); /* 14 */ + def(CURLE_FTP_CANT_GET_HOST); /* 15 */ + def(CURLE_FTP_CANT_RECONNECT); /* 16 */ + def(CURLE_FTP_COULDNT_SET_BINARY); /* 17 */ + def(CURLE_PARTIAL_FILE); /* 18 */ + def(CURLE_FTP_COULDNT_RETR_FILE); /* 19 */ + def(CURLE_FTP_WRITE_ERROR); /* 20 */ + def(CURLE_FTP_QUOTE_ERROR); /* 21 */ + def(CURLE_HTTP_RETURNED_ERROR); /* 22 */ + def(CURLE_WRITE_ERROR); /* 23 */ + def(CURLE_MALFORMAT_USER); /* 24 - NOT USED */ + def(CURLE_UPLOAD_FAILED); /* 25 - failed upload "command" */ + def(CURLE_READ_ERROR); /* 26 - could open/read from file */ + def(CURLE_OUT_OF_MEMORY); /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + def(CURLE_OPERATION_TIMEOUTED); /* 28 - the timeout time was reached */ + def(CURLE_FTP_COULDNT_SET_ASCII); /* 29 - TYPE A failed */ + def(CURLE_FTP_PORT_FAILED); /* 30 - FTP PORT operation failed */ + def(CURLE_FTP_COULDNT_USE_REST); /* 31 - the REST command failed */ + def(CURLE_FTP_COULDNT_GET_SIZE); /* 32 - the SIZE command failed */ + def(CURLE_HTTP_RANGE_ERROR); /* 33 - RANGE "command" didn't work */ + def(CURLE_HTTP_POST_ERROR); /* 34 */ + def(CURLE_SSL_CONNECT_ERROR); /* 35 - wrong when connecting with SSL */ + def(CURLE_BAD_DOWNLOAD_RESUME); /* 36 - couldn't resume download */ + def(CURLE_FILE_COULDNT_READ_FILE); /* 37 */ + def(CURLE_LDAP_CANNOT_BIND); /* 38 */ + def(CURLE_LDAP_SEARCH_FAILED); /* 39 */ + def(CURLE_LIBRARY_NOT_FOUND); /* 40 */ + def(CURLE_FUNCTION_NOT_FOUND); /* 41 */ + def(CURLE_ABORTED_BY_CALLBACK); /* 42 */ + def(CURLE_BAD_FUNCTION_ARGUMENT); /* 43 */ + def(CURLE_BAD_CALLING_ORDER); /* 44 - NOT USED */ + def(CURLE_INTERFACE_FAILED); /* 45 - CURLOPT_INTERFACE failed */ + def(CURLE_BAD_PASSWORD_ENTERED); /* 46 - NOT USED */ + def(CURLE_TOO_MANY_REDIRECTS ); /* 47 - catch endless re-direct loops */ + def(CURLE_UNKNOWN_TELNET_OPTION); /* 48 - User specified an unknown option */ + def(CURLE_TELNET_OPTION_SYNTAX ); /* 49 - Malformed telnet option */ + def(CURLE_OBSOLETE); /* 50 - NOT USED */ + def(CURLE_SSL_PEER_CERTIFICATE); /* 51 - peer's certificate wasn't ok */ + def(CURLE_GOT_NOTHING); /* 52 - when this is a specific error */ + def(CURLE_SSL_ENGINE_NOTFOUND); /* 53 - SSL crypto engine not found */ + def(CURLE_SSL_ENGINE_SETFAILED); /* 54 - can not set SSL crypto engine as + default */ + def(CURLE_SEND_ERROR); /* 55 - failed sending network data */ + def(CURLE_RECV_ERROR); /* 56 - failure in receiving network data */ + def(CURLE_SHARE_IN_USE); /* 57 - share is in use */ + def(CURLE_SSL_CERTPROBLEM); /* 58 - problem with the local certificate */ + def(CURLE_SSL_CIPHER); /* 59 - couldn't use specified cipher */ + def(CURLE_SSL_CACERT); /* 60 - problem with the CA cert (path?) */ + def(CURLE_BAD_CONTENT_ENCODING); /* 61 - Unrecognized transfer encoding */ + def(CURLE_LDAP_INVALID_URL); /* 62 - Invalid LDAP URL */ + def(CURLE_FILESIZE_EXCEEDED); /* 63 - Maximum file size exceeded */ + def(CURLE_FTP_SSL_FAILED); /* 64 - Requested FTP SSL level failed */ + def(CURLE_SEND_FAIL_REWIND); /* 65 - Sending the data requires a rewind + that failed */ + def(CURLE_SSL_ENGINE_INITFAILED); /* 66 - failed to initialise ENGINE */ + def(CURLE_LOGIN_DENIED); /* 67 - user); password or similar was not + accepted and we failed to login */ + def(CURLE_TFTP_NOTFOUND); /* 68 - file not found on server */ + def(CURLE_TFTP_PERM); /* 69 - permission problem on server */ + def(CURLE_TFTP_DISKFULL); /* 70 - out of disk space on server */ + def(CURLE_TFTP_ILLEGAL); /* 71 - Illegal TFTP operation */ + def(CURLE_TFTP_UNKNOWNID); /* 72 - Unknown transfer ID */ + def(CURLE_TFTP_EXISTS); /* 73 - File already exists */ + def(CURLE_TFTP_NOSUCHUSER); /* 74 - No such user */ + def(CURLE_CONV_FAILED); /* 75 - conversion failed */ + def(CURLE_CONV_REQD); /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION); + CURLOPT_CONV_TO_NETWORK_FUNCTION); and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + def(CURLE_SSL_CACERT_BADFILE); /* 77 - could not load CACERT file); missing + or wrong format */ + def(CURLE_REMOTE_FILE_NOT_FOUND); /* 78 - remote file not found */ + def(CURLE_SSH); /* 79 - error from the SSH layer); somewhat + generic so the error message will be of + interest when this has happened */ + + def(CURLE_SSL_SHUTDOWN_FAILED); /* 80 - Failed to shut down the SSL + connection */ +#undef def + } +}; + +static const CURLcodeMapper sCURLcodeMapper; + +LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname): + mBoundListener(LLEventPumps::instance(). + obtain(pumpname). + listen("LLXMLRPCListener", boost::bind(&LLXMLRPCListener::process, this, _1))) +{ +} + +/** + * Capture an outstanding LLXMLRPCTransaction and poll it periodically until + * done. + * + * The sequence is: + * # Instantiate Poller, which instantiates, populates and initiates an + * LLXMLRPCTransaction. Poller self-registers on the LLEventPump named + * "mainloop". + * # "mainloop" is conventionally pumped once per frame. On each such call, + * Poller checks its LLXMLRPCTransaction for completion. + * # When the LLXMLRPCTransaction completes, Poller collects results (if any) + * and sends notification. + * # The tricky part: Poller frees itself (and thus its LLXMLRPCTransaction) + * when done. The only external reference to it is the connection to the + * "mainloop" LLEventPump. + */ +class Poller +{ +public: + /// Validate the passed request for required fields, then use it to + /// populate an XMLRPC_REQUEST and an associated LLXMLRPCTransaction. Send + /// the request. + Poller(const LLSD& command): + mReqID(command), + mUri(command["uri"]), + mMethod(command["method"]), + mReplyPump(command["reply"]) + { + // LL_ERRS if any of these are missing + const char* required[] = { "uri", "method", "reply" }; + // optional: "options" (array of string) + // Validate the request + std::set<std::string> missing; + for (const char** ri = boost::begin(required); ri != boost::end(required); ++ri) + { + // If the command does not contain this required entry, add it to 'missing'. + if (! command.has(*ri)) + { + missing.insert(*ri); + } + } + if (! missing.empty()) + { + LL_ERRS("LLXMLRPCListener") << mMethod << " request missing params: "; + const char* separator = ""; + for (std::set<std::string>::const_iterator mi(missing.begin()), mend(missing.end()); + mi != mend; ++mi) + { + LL_CONT << separator << *mi; + separator = ", "; + } + LL_CONT << LL_ENDL; + } + + // Build the XMLRPC request. + XMLRPC_REQUEST request = XMLRPC_RequestNew(); + XMLRPC_RequestSetMethodName(request, mMethod.c_str()); + XMLRPC_RequestSetRequestType(request, xmlrpc_request_call); + XMLRPC_VALUE xparams = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct); + LLSD params(command["params"]); + if (params.isMap()) + { + for (LLSD::map_const_iterator pi(params.beginMap()), pend(params.endMap()); + pi != pend; ++pi) + { + std::string name(pi->first); + LLSD param(pi->second); + if (param.isString()) + { + XMLRPC_VectorAppendString(xparams, name.c_str(), param.asString().c_str(), 0); + } + else if (param.isInteger() || param.isBoolean()) + { + XMLRPC_VectorAppendInt(xparams, name.c_str(), param.asInteger()); + } + else if (param.isReal()) + { + XMLRPC_VectorAppendDouble(xparams, name.c_str(), param.asReal()); + } + else + { + LL_ERRS("LLXMLRPCListener") << mMethod << " request param " + << name << " has unknown type: " << param << LL_ENDL; + } + } + } + LLSD options(command["options"]); + if (options.isArray()) + { + XMLRPC_VALUE xoptions = XMLRPC_CreateVector("options", xmlrpc_vector_array); + for (LLSD::array_const_iterator oi(options.beginArray()), oend(options.endArray()); + oi != oend; ++oi) + { + XMLRPC_VectorAppendString(xoptions, NULL, oi->asString().c_str(), 0); + } + XMLRPC_AddValueToVector(xparams, xoptions); + } + XMLRPC_RequestSetData(request, xparams); + + mTransaction.reset(new LLXMLRPCTransaction(mUri, request)); + mPreviousStatus = mTransaction->status(NULL); + + // Free the XMLRPC_REQUEST object and the attached data values. + XMLRPC_RequestFree(request, 1); + + // Now ensure that we get regular callbacks to poll for completion. + mBoundListener = + LLEventPumps::instance(). + obtain("mainloop"). + listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1)); + + LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL; + } + + /// called by "mainloop" LLEventPump + bool poll(const LLSD&) + { + bool done = mTransaction->process(); + + CURLcode curlcode; + LLXMLRPCTransaction::EStatus status; + { + // LLXMLRPCTransaction::status() is defined to accept int* rather + // than CURLcode*. I don't feel the urge to fix the signature, but + // we want a CURLcode rather than an int. So fetch it as a local + // int, but then assign to a CURLcode for the remainder of this + // method. + int curlint; + status = mTransaction->status(&curlint); + curlcode = CURLcode(curlint); + } + + LLSD data(mReqID.makeResponse()); + data["status"] = sStatusMapper.lookup(status); + data["errorcode"] = sCURLcodeMapper.lookup(curlcode); + data["error"] = ""; + data["transfer_rate"] = 0.0; + LLEventPump& replyPump(LLEventPumps::instance().obtain(mReplyPump)); + if (! done) + { + // Not done yet, carry on. + if (status == LLXMLRPCTransaction::StatusDownloading + && status != mPreviousStatus) + { + // If a response has been received, send the + // 'downloading' status if it hasn't been sent. + replyPump.post(data); + } + + mPreviousStatus = status; + return false; + } + + // Here the transaction is complete. Check status. + data["error"] = mTransaction->statusMessage(); + data["transfer_rate"] = mTransaction->transferRate(); + LL_INFOS("LLXMLRPCListener") << mMethod << " result from " << mUri << ": status " + << data["status"].asString() << ", errorcode " + << data["errorcode"].asString() + << " (" << data["error"].asString() << ")" + << LL_ENDL; + // In addition to CURLE_OK, LLUserAuth distinguishes different error + // values of 'curlcode': + // CURLE_COULDNT_RESOLVE_HOST, + // CURLE_SSL_PEER_CERTIFICATE, + // CURLE_SSL_CACERT, + // CURLE_SSL_CONNECT_ERROR. + // Given 'message', need we care? + if (status == LLXMLRPCTransaction::StatusComplete) + { + // Success! Parse data. + std::string status_string(data["status"]); + data["responses"] = parseResponse(status_string); + data["status"] = status_string; + } + + // whether successful or not, send reply on requested LLEventPump + replyPump.post(data); + + // Because mTransaction is a boost::scoped_ptr, deleting this object + // frees our LLXMLRPCTransaction object. + // Because mBoundListener is an LLTempBoundListener, deleting this + // object disconnects it from "mainloop". + // *** MUST BE LAST *** + delete this; + return false; + } + +private: + /// Derived from LLUserAuth::parseResponse() and parseOptionInto() + LLSD parseResponse(std::string& status_string) + { + // Extract every member into data["responses"] (a map of string + // values). + XMLRPC_REQUEST response = mTransaction->response(); + if (! response) + { + LL_DEBUGS("LLXMLRPCListener") << "No response" << LL_ENDL; + return LLSD(); + } + + XMLRPC_VALUE param = XMLRPC_RequestGetData(response); + if (! param) + { + LL_DEBUGS("LLXMLRPCListener") << "Response contains no data" << LL_ENDL; + return LLSD(); + } + + // Now, parse everything + return parseValues(status_string, "", param); + } + + /** + * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map. + * @param key_pfx Used to describe a given key in log messages. At top + * level, pass "". When parsing an options array, pass the top-level key + * name of the array plus the index of the array entry; to this we'll + * append the subkey of interest. + * @param param XMLRPC_VALUE iterator. At top level, pass + * XMLRPC_RequestGetData(XMLRPC_REQUEST). + */ + LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param) + { + LLSD responses; + for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current; + current = XMLRPC_VectorNext(param)) + { + std::string key(XMLRPC_GetValueID(current)); + LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL; + XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current); + if (xmlrpc_type_string == type) + { + LLSD::String val(XMLRPC_GetValueString(current)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; + responses.insert(key, val); + } + else if (xmlrpc_type_int == type) + { + LLSD::Integer val(XMLRPC_GetValueInt(current)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; + responses.insert(key, val); + } + else if (xmlrpc_type_double == type) + { + LLSD::Real val(XMLRPC_GetValueDouble(current)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; + responses.insert(key, val); + } + else if (xmlrpc_type_array == type) + { + // We expect this to be an array of submaps. Walk the array, + // recursively parsing each submap and collecting them. + LLSD array; + int i = 0; // for descriptive purposes + for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row; + row = XMLRPC_VectorNext(current), ++i) + { + // Recursive call. For the lower-level key_pfx, if 'key' + // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the + // nested call, a subkey "bar" will then be logged as + // "foo[0]:bar", and so forth. + // Parse the scalar subkey/value pairs from this array + // entry into a temp submap. Collect such submaps in 'array'. + array.append(parseValues(status_string, + STRINGIZE(key_pfx << key << '[' << i << "]:"), + row)); + } + // Having collected an 'array' of 'submap's, insert that whole + // 'array' as the value of this 'key'. + responses.insert(key, array); + } + else + { + // whoops - unrecognized type + LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key " + << key_pfx << key << LL_ENDL; + responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>')); + status_string = "BadType"; + } + } + return responses; + } + + const LLReqID mReqID; + const std::string mUri; + const std::string mMethod; + const std::string mReplyPump; + LLTempBoundListener mBoundListener; + boost::scoped_ptr<LLXMLRPCTransaction> mTransaction; + LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes. +}; + +bool LLXMLRPCListener::process(const LLSD& command) +{ + // Allocate a new heap Poller, but do not save a pointer to it. Poller + // will check its own status and free itself on completion of the request. + (new Poller(command)); + // conventional event listener return + return false; +} diff --git a/indra/newview/llxmlrpclistener.h b/indra/newview/llxmlrpclistener.h new file mode 100644 index 0000000000..120c2b329b --- /dev/null +++ b/indra/newview/llxmlrpclistener.h @@ -0,0 +1,35 @@ +/** + * @file llxmlrpclistener.h + * @author Nat Goodspeed + * @date 2009-03-18 + * @brief LLEventPump API for LLXMLRPCTransaction. This header doesn't + * actually define the API; the API is defined by the pump name on + * which this class listens, and by the expected content of LLSD it + * receives. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLXMLRPCLISTENER_H) +#define LL_LLXMLRPCLISTENER_H + +#include "llevents.h" + +/// Listen on an LLEventPump with specified name for LLXMLRPCTransaction +/// request events. +class LLXMLRPCListener +{ +public: + /// Specify the pump name on which to listen + LLXMLRPCListener(const std::string& pumpname); + + /// Handle request events on the event pump specified at construction time + bool process(const LLSD& command); + +private: + LLTempBoundListener mBoundListener; +}; + +#endif /* ! defined(LL_LLXMLRPCLISTENER_H) */ diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 58ff84a8a6..70859e8ea5 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llxmlrpctransaction.h" +#include "llxmlrpclistener.h" #include "llcurl.h" #include "llviewercontrol.h" @@ -42,6 +43,13 @@ #include "llappviewer.h" +// Static instance of LLXMLRPCListener declared here so that every time we +// bring in this code, we instantiate a listener. If we put the static +// instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would +// simply omit llxmlrpclistener.o, and shouting on the LLEventPump would do +// nothing. +static LLXMLRPCListener listener("LLXMLRPCTransaction"); + LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const { return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id)); @@ -213,6 +221,11 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri, XMLRPC_RequestSetData(request, params.getValue()); init(request, useGzip); + // DEV-28398: without this XMLRPC_RequestFree() call, it looks as though + // the 'request' object is simply leaked. It's less clear to me whether we + // should also ask to free request value data (second param 1), since the + // data come from 'params'. + XMLRPC_RequestFree(request, 1); } diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 38570e1a7e..433070ce34 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -134,8 +134,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,0 - PRODUCTVERSION 2,0,0,0 + FILEVERSION 2,0,0,3256 + PRODUCTVERSION 2,0,0,3256 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -152,12 +152,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.0.0.0" + VALUE "FileVersion", "2.0.0.3256" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.0.0.0" + VALUE "ProductVersion", "2.0.0.3256" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 4d7433233a..b194b533af 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -157,11 +157,13 @@ DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 20 expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). GL Copyright (C) 1999-2004 Brian Paul. +google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) jpeglib Copyright (C) 1991-1998, Thomas G. Lane. ogg/vorbis Copyright (C) 2001, Xiphophorus OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. +Pth Copyright (C) 1999-2006 Ralf S. Engelschall <rse@gnu.org> SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml index 6ba26f938d..b96573b32a 100644 --- a/indra/newview/skins/default/xui/en/floater_media_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml @@ -1,20 +1,74 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater bottom="-666" can_close="true" can_drag_on_left="false" can_minimize="true" - can_resize="false" can_tear_off="true" default_tab_group="1" enabled="true" - width="365" height="535" left="330" min_height="430" min_width="620" - mouse_opaque="true" name="Medis Settings" title="Media Settings"> - <button bottom="-525" enabled="true" follows="right|bottom" font="SansSerif" - halign="center" height="20" label="OK" label_selected="OK" left="75" - mouse_opaque="true" name="OK" scale_image="true" width="90" /> - <button bottom_delta="0" enabled="true" follows="right|bottom" font="SansSerif" - halign="center" height="20" label="Cancel" label_selected="Cancel" - left_delta="93" mouse_opaque="true" name="Cancel" scale_image="true" - width="90" /> - <button bottom_delta="0" enabled="true" follows="right|bottom" font="SansSerif" - halign="center" height="20" label="Apply" label_selected="Apply" - left_delta="93" mouse_opaque="true" name="Apply" scale_image="true" - width="90" /> - <tab_container bottom="-500" enabled="true" follows="left|top|right|bottom" height="485" - left="0" mouse_opaque="false" name="tab_container" tab_group="1" - tab_position="top" tab_width="80" width="365" /> +<floater + bottom="-666" + can_close="true" + can_drag_on_left="false" + can_minimize="true" + can_resize="false" + can_tear_off="true" + default_tab_group="1" + enabled="true" + width="365" + height="535" + left="330" + min_height="430" + min_width="620" + mouse_opaque="true" + name="Medis Settings" + help_topic = "media_settings" + title="Media Settings"> + <button + bottom="-525" + enabled="true" + follows="right|bottom" + font="SansSerif" + halign="center" + height="20" + label="OK" + label_selected="OK" + left="75" + mouse_opaque="true" + name="OK" + scale_image="true" + width="90" /> + <button + bottom_delta="0" + enabled="true" + follows="right|bottom" + font="SansSerif" + halign="center" + height="20" + label="Cancel" + label_selected="Cancel" + left_delta="93" + mouse_opaque="true" + name="Cancel" + scale_image="true" + width="90" /> + <button + bottom_delta="0" + enabled="true" + follows="right|bottom" + font="SansSerif" + halign="center" + height="20" + label="Apply" + label_selected="Apply" + left_delta="93" + mouse_opaque="true" + name="Apply" + scale_image="true" + width="90" /> + <tab_container + bottom="-500" + enabled="true" + follows="left|top|right|bottom" + height="485" + left="0" + mouse_opaque="false" + name="tab_container" + tab_group="1" + tab_position="top" + tab_width="80" + width="365" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 7829a4fa93..8cdcee6927 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -207,71 +207,71 @@ layout="topleft" name="move_radio_group"> <radio_item - top_pad="6" + top_pad="6" label="Move" layout="topleft" name="radio move" /> <radio_item - top_pad="6" + top_pad="6" label="Lift (Ctrl)" layout="topleft" name="radio lift" /> <radio_item - top_pad="6" + top_pad="6" label="Spin (Ctrl+Shift)" layout="topleft" name="radio spin" /> <radio_group.commit_callback - function="BuildTool.commitRadioMove"/> - </radio_group> - <radio_group + function="BuildTool.commitRadioMove"/> + </radio_group> + <radio_group follows="left|top" - left="10" - top="54" - height="70" + left="10" + top="54" + height="70" layout="topleft" - name="edit_radio_group"> + name="edit_radio_group"> <radio_item - label="Move" - layout="topleft" - name="radio position" /> + label="Move" + layout="topleft" + name="radio position" /> <radio_item - top_pad="6" + top_pad="6" label="Rotate (Ctrl)" layout="topleft" name="radio rotate" /> <radio_item - top_pad="6" + top_pad="6" label="Stretch (Ctrl+Shift)" layout="topleft" name="radio stretch" /> <radio_item - top_pad="6" - label="Select Texture" + top_pad="6" + label="Select Face" layout="topleft" name="radio select face" /> - <radio_group.commit_callback - function="BuildTool.commitRadioEdit"/> + <radio_group.commit_callback + function="BuildTool.commitRadioEdit"/> </radio_group> <check_box left="10" follows="left|top" height="16" - control_name="EditLinkedParts" + control_name="EditLinkedParts" label="Edit linked" layout="topleft" name="checkbox edit linked parts" > <check_box.commit_callback - function="BuildTool.selectComponent"/> + function="BuildTool.selectComponent"/> </check_box> - <check_box + <check_box control_name="ScaleUniform" height="19" label="Stretch Both Sides" layout="topleft" left="143" name="checkbox uniform" - top="50" + top="50" width="134" /> <check_box control_name="ScaleStretchTextures" @@ -312,7 +312,7 @@ <combo_box.commit_callback function="BuildTool.gridMode"/> </combo_box> - <button + <button left_pad="0" image_disabled="ForwardArrow_Disabled" image_selected="ForwardArrow_Press" @@ -754,24 +754,24 @@ tab_height="25" top="170" width="280"> - <panel - border="false" - follows="all" - label="General" - layout="topleft" - mouse_opaque="false" - help_topic="toolbox_general_tab" - name="General" - top="16" - width="280"> - <panel.string - name="text deed continued"> - Deed - </panel.string> - <panel.string - name="text deed"> - Deed - </panel.string> + <panel + border="false" + follows="all" + label="General" + layout="topleft" + mouse_opaque="false" + help_topic="toolbox_general_tab" + name="General" + top="16" + width="280"> + <panel.string + name="text deed continued"> + Deed + </panel.string> + <panel.string + name="text deed"> + Deed + </panel.string> <panel.string name="text modify info 1"> You can modify this object @@ -912,21 +912,21 @@ width="75"> Group: </text> - <button - follows="top|left" - height="10" - image_disabled="Activate_Checkmark" - image_selected="Activate_Checkmark" - image_unselected="Activate_Checkmark" - image_color="White_50" - layout="topleft" - left_pad="0" - top_delta="0" - name="button set group" - picture_style="true" - tab_stop="false" - tool_tip="Choose a group to share this object's permissions" - width="10" /> + <button + follows="top|left" + height="10" + image_disabled="Activate_Checkmark" + image_selected="Activate_Checkmark" + image_unselected="Activate_Checkmark" + image_color="White_50" + layout="topleft" + left_pad="0" + top_delta="0" + name="button set group" + picture_style="true" + tab_stop="false" + tool_tip="Choose a group to share this object's permissions" + width="10" /> <name_box follows="left|top" height="18" @@ -1046,15 +1046,15 @@ height="20" max_val="999999999" /> <check_box - height="15" - width="110" - top_pad="3" - label="Show in search" + height="15" + width="110" + top_pad="3" + label="Show in search" layout="topleft" - left="100" + left="100" name="search_check" tool_tip="Let people see this object in search results" /> -<panel + <panel border="false" follows="left|top" layout="topleft" @@ -2353,7 +2353,7 @@ left_delta="0" name="combobox texgen" top_pad="4" - width="87"> + width="60"> <combo_box.item label="Default" name="Default" @@ -2372,7 +2372,7 @@ name="label shininess" left_pad="5" top_pad="-36" - width="80"> + width="60"> Shininess </text> <combo_box @@ -2381,7 +2381,7 @@ left_delta="0" name="combobox shininess" top_pad="4" - width="80"> + width="60"> <combo_box.item label="None" name="None" @@ -2584,9 +2584,9 @@ height="19" increment="1" initial_value="0" - label="RotationËš" + label="RotationËš" layout="topleft" - label_width="100" + label_width="100" left="10" max_val="9999" min_val="-9999" @@ -2599,9 +2599,9 @@ follows="left|top" height="19" initial_value="1" - label="Repeats / Meter" + label="Repeats / Meter" layout="topleft" - label_width="100" + label_width="100" left="10" max_val="10" min_val="0.1" @@ -2654,7 +2654,7 @@ name="TexOffsetV" top_pad="1" width="160" /> - <panel + <panel border="false" follows="left|top" layout="topleft" @@ -2667,88 +2667,88 @@ height="75" width="278"> <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" - left="10" - top_pad="5" - name="media_tex" - width="260"> - Media URL - </text> - <line_editor - follows="left|top|right" - height="18" - layout="topleft" - left="10" - read_only="true" - name="media_info" - select_on_focus="true" - width="220" /> - <button - follows="top|left" - height="18" - image_selected="AddItem_Press" - image_unselected="AddItem_Off" - image_disabled="AddItem_Disabled" - layout="topleft" - left_pad="0" - name="add_media" - picture_style="true" - tab_stop="false" - top_delta="0" - tool_tip="Add media" - width="18"> - <button.commit_callback - function="BuildTool.AddMedia"/> - </button> - <button - follows="bottom|left" - height="18" - image_selected="TrashItem_Press" - image_unselected="TrashItem_Off" - layout="topleft" - left_pad="5" - name="delete_media" - picture_style="true" - right="-10" - tool_tip="Delete this media texture" - top_delta="0" - width="18"> - <button.commit_callback - function="BuildTool.DeleteMedia"/> - </button> - <button + type="string" + length="1" follows="left|top" - font="SansSerifSmall" - height="19" - label="Align" - label_selected="Align Media" + height="12" layout="topleft" left="10" - name="button align" top_pad="5" - width="100" /> - <button - follows="bottom|left" - tool_tip="Change sort and view of recent residents list" - height="18" - image_disabled="OptionsMenu_Disabled" - image_selected="OptionsMenu_Press" - image_unselected="OptionsMenu_Off" - layout="topleft" - left_pad="10" - name="edit_media" - picture_style="true" - top_delta="0" - width="18"> - <button.commit_callback - function="BuildTool.EditMedia"/> - </button> - </panel> - </panel> + name="media_tex" + width="260"> + Media URL + </text> + <line_editor + follows="left|top|right" + height="18" + layout="topleft" + left="10" + read_only="true" + name="media_info" + select_on_focus="true" + width="180" /> + <button + follows="top|left" + height="18" + image_selected="AddItem_Press" + image_unselected="AddItem_Off" + image_disabled="AddItem_Disabled" + layout="topleft" + left_pad="0" + name="add_media" + picture_style="true" + tab_stop="false" + top_delta="0" + tool_tip="Add Media" + width="18"> + <button.commit_callback + function="BuildTool.AddMedia"/> + </button> + <button + follows="top|left" + height="18" + image_selected="TrashItem_Press" + image_unselected="TrashItem_Off" + layout="topleft" + left_pad="5" + name="delete_media" + picture_style="true" + tool_tip="Delete this media texture" + top_delta="0" + width="18"> + <button.commit_callback + function="BuildTool.DeleteMedia"/> + </button> + <button + follows="top|left" + tool_tip="Edit this Media" + height="18" + image_disabled="OptionsMenu_Disabled" + image_selected="OptionsMenu_Press" + image_unselected="OptionsMenu_Off" + layout="topleft" + left_pad="10" + name="edit_media" + picture_style="true" + top_delta="0" + width="18"> + <button.commit_callback + function="BuildTool.EditMedia"/> + </button> + + <button + follows="left|top" + font="SansSerifSmall" + height="19" + label="Align" + label_selected="Align Media" + layout="topleft" + left="10" + name="button align" + top_pad="5" + width="100" /> + </panel> + </panel> <panel border="false" follows="all" @@ -2786,10 +2786,10 @@ name="contents_inventory" top="50" width="260" /> - </panel> + </panel> </tab_container> -<panel - follows="left|top" + <panel + follows="left|top" height="384" layout="topleft" left_delta="0" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 284594426c..34d0498180 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1091,6 +1091,14 @@ <menu_item_call.on_click function="Advanced.RebakeTextures" /> </menu_item_call> + <menu_item_call + label="Set UI Size to Default" + layout="topleft" + name="Set UI Size to Default"> + <menu_item_call.on_click + function="View.DefaultUISize" /> + </menu_item_call> + <menu_item_separator/> <menu_item_check label="Limit Select Distance" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d10bbe7569..7d2ef4923e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -675,6 +675,19 @@ To place the media on only one face, choose Select Texture and click on the desi <notification icon="alertmodal.tga" + name="WhiteListInvalidatesHomeUrl" + type="alertmodal"> +Adding this entry to the whitelist will invalidate the home URL you +specified for this instance of media. You are not allowed to do this +so the entry cannot be added to the whitelist. + <usetemplate + name="okbutton" + yestext="Ok"/> + </notification> + + + <notification + icon="alertmodal.tga" name="MustBeInParcel" type="alertmodal"> You must be standing inside the land parcel to set its Landing Point. diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml index a56f1cf8fe..f9e4b9e7c0 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml @@ -8,6 +8,7 @@ left="102" mouse_opaque="true" name="Media Settings General" + help_topic = "media_settings_general" width="365"> <text @@ -135,7 +136,8 @@ <check_box bottom_delta="-25" - enabled="true" + visible="false" + enabled="false" follows="left|top" font="SansSerifSmall" height="16" @@ -148,7 +150,7 @@ width="150" /> <check_box - bottom_delta="-25" + bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" @@ -168,20 +170,6 @@ font="SansSerifSmall" height="16" initial_value="false" - label="Use Default Alternative Image" - left="10" - mouse_opaque="true" - name="alt_image_enable" - radio_style="false" - width="150" /> - - <check_box - bottom_delta="-25" - enabled="true" - follows="left|top" - font="SansSerifSmall" - height="16" - initial_value="false" label="Auto Play Media" left="10" mouse_opaque="true" @@ -234,7 +222,7 @@ label="" label_width="0" left_delta="40" - max_val="2000" + max_val="2048" min_val="0" mouse_opaque="true" name="width_pixels" @@ -246,7 +234,7 @@ <spinner bottom_delta="0" decimal_digits="0" enabled="true" follows="left|top" height="16" increment="1" initial_val="256" label="" label_width="0" - left_delta="20" max_val="2000" min_val="0" mouse_opaque="true" + left_delta="20" max_val="2048" min_val="0" mouse_opaque="true" name="height_pixels" width="50" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml index 0cc1406d62..85f534c4a3 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml @@ -8,6 +8,7 @@ left="102" mouse_opaque="true" name="Media settings for controls" + help_topic = "media_settings_controls" width="365"> <text @@ -15,7 +16,6 @@ follows="top|left" height="15" left="10" - name="media_perms_label_owner" enabled="false"> Owner </text> @@ -53,9 +53,8 @@ follows="top|left" height="15" left="10" - name="media_perms_label_group" enabled="false"> - Group + Group: </text> <name_box @@ -101,7 +100,6 @@ follows="top|left" height="15" left="10" - name="media_perms_label_anyone" enabled="false"> Anyone </text> diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml index 695e956e41..a26f74844e 100644 --- a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml +++ b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml @@ -8,6 +8,7 @@ left="102" mouse_opaque="true" name="Media Settings Security" + help_topic = "media_settings_security" width="365"> <check_box bottom_delta="-40" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 1ea6e1149d..50108aa21f 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -1,17 +1,18 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - background_visible="true" +background_visible="true" follows="all" - height="400" + height="570" label="Places" layout="topleft" min_height="350" - min_width="240" name="places panel" + top="0" + left="0" width="333"> <string name="landmarks_tab_title" - value="Landmarks" /> + value="My Landmarks" /> <string name="teleport_history_tab_title" value="Teleport History" /> @@ -19,44 +20,47 @@ follows="left|top|right" font="SansSerif" height="23" - label="Filter" layout="topleft" left="15" + label="Filter" + max_length="300" name="Filter" top="3" - width="300" /> + width="303" /> <tab_container follows="all" - height="326" + height="500" layout="topleft" - left="9" + left="10" name="Places Tabs" + tab_min_width="70" + tab_height="30" tab_position="top" - top="30" + top_pad="10" width="313" /> <panel class="panel_place_info" filename="panel_place_info.xml" follows="all" - height="326" + height="533" layout="topleft" left="0" help_topic="places_info_tab" name="panel_place_info" - top="30" - visible="false" /> + top="5" + visible="false" + width="313" /> <panel - height="25" + height="19" layout="topleft" left="0" help_topic="places_button_tab" name="button_panel" - top_pad="10" width="313"> <button follows="bottom|left" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Teleport" layout="topleft" left="5" @@ -65,8 +69,8 @@ width="77" /> <button follows="bottom|left" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Map" layout="topleft" left_pad="5" @@ -76,8 +80,8 @@ <button enabled="false" follows="bottom|left" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Share" layout="topleft" left_pad="5" @@ -86,8 +90,8 @@ width="60" /> <button follows="bottom|left" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Edit" layout="topleft" left_pad="5" @@ -96,18 +100,21 @@ width="50" /> <button follows="bottom|right" - font="SansSerifSmallBold" - height="25" - label="â–¼" + font="SansSerifSmall" + height="19" + image_disabled="ForwardArrow_Disabled" + image_selected="ForwardArrow_Press" + image_unselected="ForwardArrow_Off" + picture_style="true" layout="topleft" name="overflow_btn" right="-10" top="0" - width="30" /> + width="18" /> <button follows="bottom|right" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Close" layout="topleft" name="close_btn" @@ -116,8 +123,8 @@ width="60" /> <button follows="bottom|right" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Cancel" layout="topleft" name="cancel_btn" @@ -126,8 +133,8 @@ width="60" /> <button follows="bottom|right" - font="SansSerifSmallBold" - height="25" + font="SansSerifSmall" + height="19" label="Save" layout="topleft" name="save_btn" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index c4dc8834db..ce7939c00f 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -77,10 +77,19 @@ name="cookies_enabled" top_pad="10" width="350" /> + <check_box + control_name="AutoPlayMedia" + height="16" + label="Allow Media Autoplay" + layout="topleft" + left="30" + name="autoplay_enabled" + top_pad="10" + width="350" /> <text - type="string" - length="1" - follows="left|top" + type="string" + length="1" + follows="left|top" height="10" layout="topleft" left="30" @@ -88,8 +97,9 @@ top_pad="10" width="350"> Logs: - </text> + </text> <check_box + enabled="false" control_name="LogInstantMessages" height="16" diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index a32be90a33..73a759a8ba 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -53,7 +53,7 @@ left="10" name="second_life_image_panel" top="0" - width="290"> + width="280"> <texture_picker allow_no_texture="true" default_image_name="None" @@ -75,13 +75,14 @@ text_color="white" top_delta="0" value="[SECOND_LIFE]:" - width="170" /> + width="165" /> <expandable_text follows="left|top|right" height="95" layout="topleft" left="107" name="sl_description_edit" + top_pad="-3" width="173" expanded_bg_visible="true" expanded_bg_color="DkGray"> @@ -95,7 +96,7 @@ top_pad="10" left="10" name="first_life_image_panel" - width="290"> + width="280"> <texture_picker allow_no_texture="true" default_image_name="None" @@ -116,13 +117,14 @@ text_color="white" top_delta="0" value="Real World:" - width="173" /> + width="165" /> <expandable_text follows="left|top|right" height="95" layout="topleft" left="107" name="fl_description_edit" + top_pad="-3" width="173" expanded_bg_visible="true" expanded_bg_color="DkGray"> @@ -151,7 +153,7 @@ name="homepage_edit" top_pad="0" value="http://librarianavengers.org" - width="290" + width="280" word_wrap="false" use_elipsis="true" /> @@ -205,7 +207,7 @@ name="acc_status_text" top_pad="0" value="Resident. No payment info on file." - width="295" + width="280" word_wrap="true" /> <text follows="left|top" @@ -215,7 +217,7 @@ left="10" name="title_partner_text" text_color="white" - top_pad="10" + top_pad="5" value="Partner:" width="280" /> <panel @@ -245,21 +247,21 @@ left="10" name="title_groups_text" text_color="white" - top_pad="10" + top_pad="8" value="Groups:" width="280" /> - <text + <expandable_text follows="left|top|bottom" - height="160" + height="60" layout="topleft" left="10" - name="sl_groups" - top_pad="0" - width="290" - word_wrap="true" - use_elipsis="true"> + name="sl_groups" + top_pad="0" + width="280" + expanded_bg_visible="true" + expanded_bg_color="DkGray"> Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. - </text> + </expandable_text> </panel> </scroll_container> <panel @@ -270,17 +272,17 @@ top_pad="2" bottom="10" height="19" - width="313"> + width="303"> <button follows="bottom|left" height="19" - label="Add" + label="Add Friend" layout="topleft" left="0" mouse_opaque="false" name="add_friend" top="5" - width="55" /> + width="75" /> <button follows="bottom|left" height="19" @@ -289,7 +291,7 @@ name="im" top="5" left_pad="5" - width="40" /> + width="45" /> <button enabled="false" follows="bottom|left" @@ -299,7 +301,7 @@ name="call" left_pad="5" top="5" - width="55" /> + width="45" /> <button enabled="false" follows="bottom|left" @@ -309,7 +311,7 @@ name="show_on_map_btn" top="5" left_pad="5" - width="50" /> + width="45" /> <button follows="bottom|left" height="19" @@ -318,7 +320,7 @@ name="teleport" left_pad="5" top="5" - width="90" /> + width="80" /> </panel> <panel follows="bottom|left" @@ -328,7 +330,7 @@ name="profile_me_buttons_panel" visible="false" height="19" - width="313"> + width="303"> <button follows="bottom|right" font="SansSerifSmall" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index 8a48574440..7a5781651d 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -52,8 +52,9 @@ height="535" layout="topleft" left="10" + min_width="333" name="tabs" - tab_min_width="95" + tab_min_width="80" tab_height="30" tab_position="top" top_pad="10" @@ -61,21 +62,21 @@ <panel class="panel_profile" filename="panel_profile.xml" - label="Profile" + label="PROFILE" layout="topleft" help_topic="profile_profile_tab" name="panel_profile" /> <panel class="panel_picks" filename="panel_picks.xml" - label="Picks" + label="PICKS" layout="topleft" help_topic="profile_picks_tab" name="panel_picks" /> <panel class="panel_notes" filename="panel_notes.xml" - label="Notes & Privacy" + label="NOTES & PRIVACY" layout="topleft" help_topic="profile_notes_tab" name="panel_notes" /> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 395b574425..3f64c9c633 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -18,6 +18,7 @@ tab_title="Home" description="Home." image="TabIcon_Open_Off" + image_selected="TabIcon_Close_Off" mouse_opaque="false" background_visible="true" > @@ -34,6 +35,7 @@ tab_title="People" description="Find your friends, contacts and people nearby." image="TabIcon_People_Off" + image_selected="TabIcon_People_Selected" mouse_opaque="false" background_visible="true" > @@ -76,6 +78,7 @@ label="Places" description="Find places to go and places you've visited before." image="TabIcon_Places_Off" + image_selected="TabIcon_Places_Selected" mouse_opaque="false" background_visible="true" > @@ -94,6 +97,7 @@ tab_title="Me" description="Edit your public profile and Picks." image="TabIcon_Me_Off" + image_selected="TabIcon_Me_Selected" mouse_opaque="false" background_visible="true" > @@ -111,6 +115,7 @@ tab_title="Appearance" description="Change your appearance and current look." image="TabIcon_Appearance_Off" + image_selected="TabIcon_Appearance_Selected" mouse_opaque="false" background_visible="true" > diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index a57c9cd97f..4c19b22ac5 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -1819,6 +1819,7 @@ this texture in your inventory <string name="broken_link" value=" (broken_link)" /> <string name="LoadingContents">Loading contents...</string> <string name="NoContents">No contents</string> + <string name="WornOnAttachmentPoint"> (worn on [ATTACHMENT_POINT])</string> <!-- Gestures labels --> <!-- use value="" because they have preceding spaces --> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml index 3ff0b3062a..dabcb1038b 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <accordion_tab - header_bg_color="0.68 0.68 0.68 1" - header_txt_color="0.68 0.68 0.68 1" + header_bg_color="DkGray2" + header_txt_color="LtGray" header_collapse_img="Accordion_ArrowClosed_Off" header_collapse_img_pressed="Accordion_ArrowClosed_Press" header_expand_img="Accordion_ArrowOpened_Off" header_expand_img_pressed="Accordion_ArrowOpened_Press" - header_image="Accordion_Off.png" + header_image="Accordion_Off" header_image_over="Accordion_Over" header_image_pressed="Accordion_Press" /> diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 42872d85fb..e08193f785 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -29,6 +29,8 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ + +#include "linden_common.h" #include "../test/lltut.h" #include "../llagentaccess.h" diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp index bd6ae90fab..4759c7dc91 100644 --- a/indra/newview/tests/llcapabilitylistener_test.cpp +++ b/indra/newview/tests/llcapabilitylistener_test.cpp @@ -47,9 +47,9 @@ #include "../test/lltut.h" #include "../llcapabilityprovider.h" #include "lluuid.h" -#include "llerrorcontrol.h" #include "tests/networkio.h" #include "tests/commtest.h" +#include "tests/wrapllerrs.h" #include "stringize.h" #if defined(LL_WINDOWS) @@ -127,28 +127,6 @@ namespace tut typedef llcapears_group::object llcapears_object; llcapears_group llsdmgr("llcapabilitylistener"); - struct CaptureError: public LLError::OverrideFatalFunction - { - CaptureError(): - LLError::OverrideFatalFunction(boost::bind(&CaptureError::operator(), this, _1)) - { - LLError::setPrintLocation(false); - } - - struct FatalException: public std::runtime_error - { - FatalException(const std::string& what): std::runtime_error(what) {} - }; - - void operator()(const std::string& message) - { - error = message; - throw FatalException(message); - } - - std::string error; - }; - template<> template<> void llcapears_object::test<1>() { @@ -160,10 +138,10 @@ namespace tut std::string threw; try { - CaptureError capture; + WrapLL_ERRS capture; regionPump.post(request); } - catch (const CaptureError::FatalException& e) + catch (const WrapLL_ERRS::FatalException& e) { threw = e.what(); } @@ -207,10 +185,10 @@ namespace tut std::string threw; try { - CaptureError capture; + WrapLL_ERRS capture; regionPump.post(request); } - catch (const CaptureError::FatalException& e) + catch (const WrapLL_ERRS::FatalException& e) { threw = e.what(); } @@ -269,10 +247,10 @@ namespace tut std::string threw; try { - CaptureError capture; + WrapLL_ERRS capture; regionPump.post(request); } - catch (const CaptureError::FatalException& e) + catch (const WrapLL_ERRS::FatalException& e) { threw = e.what(); } diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp index 30e39a3bcf..ed753b6ff7 100644 --- a/indra/newview/tests/lldateutil_test.cpp +++ b/indra/newview/tests/lldateutil_test.cpp @@ -28,6 +28,9 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ + +#include "linden_common.h" + #include "../test/lltut.h" #include "../lldateutil.h" diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp new file mode 100644 index 0000000000..009be35f64 --- /dev/null +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -0,0 +1,423 @@ +/**
+ * @file lllogininstance_test.cpp
+ * @brief Test for lllogininstance.cpp.
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// Own header
+#include "../lllogininstance.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "llevents.h"
+
+#if defined(LL_WINDOWS)
+#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
+#endif
+
+// Constants
+const std::string VIEWERLOGIN_URI("viewerlogin_uri");
+const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
+
+const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
+
+// Link seams.
+
+//-----------------------------------------------------------------------------
+static LLEventStream gTestPump("test_pump");
+
+#include "lllogin.h"
+static std::string gLoginURI;
+static LLSD gLoginCreds;
+static bool gDisconnectCalled = false;
+class LLLogin::Impl
+{
+};
+LLLogin::LLLogin() {}
+LLLogin::~LLLogin() {}
+LLEventPump& LLLogin::getEventPump() { return gTestPump; }
+void LLLogin::connect(const std::string& uri, const LLSD& credentials)
+{
+ gLoginURI = uri;
+ gLoginCreds = credentials;
+}
+
+void LLLogin::disconnect()
+{
+ gDisconnectCalled = true;
+}
+
+//-----------------------------------------------------------------------------
+#include "../llviewernetwork.h"
+unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; /* Flawfinder: ignore */
+
+LLViewerLogin::LLViewerLogin() {}
+LLViewerLogin::~LLViewerLogin() {}
+void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const
+{
+ uris.push_back(VIEWERLOGIN_URI);
+}
+std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; }
+
+//-----------------------------------------------------------------------------
+#include "../llviewercontrol.h"
+LLControlGroup gSavedSettings("Global");
+std::string gCurrentVersion = "invalid_version";
+
+LLControlGroup::LLControlGroup(const std::string& name) :
+ LLInstanceTracker<LLControlGroup, std::string>(name){}
+LLControlGroup::~LLControlGroup() {}
+void LLControlGroup::setBOOL(const std::string& name, BOOL val) {}
+BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
+U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
+void LLControlGroup::setString(const std::string& name, const std::string& val) {}
+std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
+BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+
+#include "lluicolortable.h"
+void LLUIColorTable::saveUserSettings(void)const {}
+
+//-----------------------------------------------------------------------------
+#include "../llurlsimstring.h"
+LLURLSimString LLURLSimString::sInstance;
+bool LLURLSimString::parse() { return true; }
+
+//-----------------------------------------------------------------------------
+#include "llnotifications.h"
+#include "llfloaterreg.h"
+static std::string gTOSType;
+static LLEventPump * gTOSReplyPump = NULL;
+
+//static
+LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
+{
+ gTOSType = name;
+ gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]);
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// LLNotifications
+class MockNotifications : public LLNotificationsInterface
+{
+ boost::function<void (const LLSD&, const LLSD&)> mResponder;
+ int mAddedCount;
+
+public:
+ MockNotifications() :
+ mResponder(0),
+ mAddedCount(0)
+ {
+ }
+
+ virtual ~MockNotifications() {}
+
+ /* virtual */ LLNotificationPtr add(
+ const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor)
+ {
+ mResponder = functor;
+ mAddedCount++;
+ return LLNotificationPtr((LLNotification*)NULL);
+ }
+
+ void sendYesResponse()
+ {
+ LLSD notification;
+ LLSD response;
+ response = 1;
+ mResponder(notification, response);
+ }
+
+ void sendNoResponse()
+ {
+ LLSD notification;
+ LLSD response;
+ response = 2;
+ mResponder(notification, response);
+ }
+
+ void sendBogusResponse()
+ {
+ LLSD notification;
+ LLSD response;
+ response = 666;
+ mResponder(notification, response);
+ }
+
+ int addedCount() { return mAddedCount; }
+};
+
+S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response)
+{
+ return response.asInteger();
+}
+
+// misc
+std::string xml_escape_string(const std::string& in)
+{
+ return in;
+}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct lllogininstance_data
+ {
+ lllogininstance_data() : logininstance(LLLoginInstance::getInstance())
+ {
+ // Global initialization
+ gLoginURI.clear();
+ gLoginCreds.clear();
+ gDisconnectCalled = false;
+
+ gTOSType = ""; // Set to invalid value.
+ gTOSReplyPump = 0; // clear the callback.
+
+
+ gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
+ gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
+ gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE);
+ gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
+ gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
+
+ credentials["first"] = "testfirst";
+ credentials["last"] = "testlast";
+ credentials["passwd"] = "testpass";
+
+ logininstance->setNotificationsInterface(¬ifications);
+ }
+
+ LLLoginInstance* logininstance;
+ LLSD credentials;
+ MockNotifications notifications;
+ };
+
+ typedef test_group<lllogininstance_data> lllogininstance_group;
+ typedef lllogininstance_group::object lllogininstance_object;
+ lllogininstance_group llsdmgr("lllogininstance");
+
+ template<> template<>
+ void lllogininstance_object::test<1>()
+ {
+ set_test_name("Test Simple Success And Disconnect");
+
+ // Test default connect.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Dummy success response.
+ LLSD response;
+ response["state"] = "online";
+ response["change"] = "connect";
+ response["progress"] = 1.0;
+ response["transfer_rate"] = 7;
+ response["data"] = "test_data";
+
+ gTestPump.post(response);
+
+ ensure("Success response", logininstance->authSuccess());
+ ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data");
+
+ logininstance->disconnect();
+
+ ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true);
+
+ response.clear();
+ response["state"] = "offline";
+ response["change"] = "disconnect";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 0;
+ response["data"] = "test_data";
+
+ gTestPump.post(response);
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<2>()
+ {
+ set_test_name("Test User TOS/Critical message Interaction");
+
+ const std::string test_uri = "testing-uri";
+
+ // Test default connect.
+ logininstance->connect(test_uri, credentials);
+
+ // connect should call LLLogin::connect to init gLoginURI and gLoginCreds.
+ ensure_equals("Default connect uri", gLoginURI, "testing-uri");
+ ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+ ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false);
+
+ // TOS failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "tos";
+ gTestPump.post(response);
+
+ ensure_equals("TOS Dialog type", gTOSType, "message_tos");
+ ensure("TOS callback given", gTOSReplyPump != 0);
+ gTOSReplyPump->post(false); // Call callback denying TOS.
+ ensure("No TOS, failed auth", logininstance->authFailure());
+
+ // Start again.
+ logininstance->connect(test_uri, credentials);
+ gTestPump.post(response); // Fail for tos again.
+ gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos.
+ ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true);
+ ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
+
+ // Fail connection, attempt connect again.
+ // The new request should have reset agree to tos to default.
+ response["data"]["reason"] = "key"; // bad creds.
+ gTestPump.post(response);
+ ensure("TOS auth failure", logininstance->authFailure());
+
+ logininstance->connect(test_uri, credentials);
+ ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+
+ // Critical Message failure response.
+ logininstance->connect(test_uri, credentials);
+ response["data"]["reason"] = "critical"; // Change response to "critical message"
+ gTestPump.post(response);
+
+ ensure_equals("TOS Dialog type", gTOSType, "message_critical");
+ ensure("TOS callback given", gTOSReplyPump != 0);
+ gTOSReplyPump->post(true);
+ ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true);
+ ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
+
+ // Fail then attempt new connection
+ response["data"]["reason"] = "key"; // bad creds.
+ gTestPump.post(response);
+ ensure("TOS auth failure", logininstance->authFailure());
+ logininstance->connect(test_uri, credentials);
+ ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false);
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<3>()
+ {
+ set_test_name("Test Mandatory Update User Accepts");
+
+ // Part 1 - Mandatory Update, with User accepts response.
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "update";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+
+ notifications.sendYesResponse();
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<4>()
+ {
+ set_test_name("Test Mandatory Update User Decline");
+
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "update";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+ notifications.sendNoResponse();
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<6>()
+ {
+ set_test_name("Test Optional Update User Accept");
+
+ // Part 3 - Mandatory Update, with bogus response.
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "optional";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+ notifications.sendYesResponse();
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<7>()
+ {
+ set_test_name("Test Optional Update User Denies");
+
+ // Part 3 - Mandatory Update, with bogus response.
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "optional";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+ notifications.sendNoResponse();
+
+ // User skips, should be reconnecting.
+ ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI);
+ ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true);
+ }
+}
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp new file mode 100644 index 0000000000..445ec7aa34 --- /dev/null +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -0,0 +1,501 @@ +/** + * @file llmediadataclient_test.cpp + * @brief LLMediaDatClient tests + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "../llviewerprecompiledheaders.h" + +#include <iostream> +#include "../test/lltut.h" + +#include "llsdserialize.h" +#include "llsdutil.h" +#include "llerrorcontrol.h" +#include "llhttpstatuscodes.h" + +#include "../llmediadataclient.h" +#include "../llvovolume.h" + +#include "../../llprimitive/llmediaentry.cpp" +#include "../../llprimitive/lltextureentry.cpp" +#include "../../llmessage/tests/llcurl_stub.cpp" + +#if LL_WINDOWS +#pragma warning (push) +#pragma warning (disable : 4702) // boost::lexical_cast generates this warning +#endif +#include <boost/lexical_cast.hpp> +#if LL_WINDOWS +#pragma warning (pop) +#endif + +#define VALID_OBJECT_ID "3607d5c4-644b-4a8a-871a-8b78471af2a2" +#define VALID_OBJECT_ID_1 "11111111-1111-1111-1111-111111111111" +#define VALID_OBJECT_ID_2 "22222222-2222-2222-2222-222222222222" +#define VALID_OBJECT_ID_3 "33333333-3333-3333-3333-333333333333" +#define VALID_OBJECT_ID_4 "44444444-4444-4444-4444-444444444444" + +#define FAKE_OBJECT_MEDIA_CAP_URL "foo_ObjectMedia" +#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL "foo_ObjectMediaNavigate" +#define FAKE_OBJECT_MEDIA_CAP_URL_503 "foo_ObjectMedia_503" +#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR "foo_ObjectMediaNavigate_ERROR" + +#define MEDIA_DATA "\ +<array> \ +<string>foo</string> \ +<string>bar</string> \ +<string>baz</string> \ +</array>" + +#define _DATA_URLS(ID,DIST,INT,URL1,URL2) " \ +<llsd> \ + <map> \ + <key>uuid</key> \ + <string>" ID "</string> \ + <key>distance</key> \ + <real>" DIST "</real> \ + <key>interest</key> \ + <real>" INT "</real> \ + <key>cap_urls</key> \ + <map> \ + <key>ObjectMedia</key> \ + <string>" URL1 "</string> \ + <key>ObjectMediaNavigate</key> \ + <string>" URL2 "</string> \ + </map> \ + <key>media_data</key> \ + " MEDIA_DATA " \ + </map> \ +</llsd>" + +#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL) + +const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0"); + +#define STR(I) boost::lexical_cast<std::string>(I) + +#define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" << \ +"================================================================================\n" << \ +"===================================== TEST " #N " ===================================\n" << \ +"================================================================================\n" << LL_ENDL; + +LLSD *gPostRecords = NULL; + +// stubs: +void LLHTTPClient::post( + const std::string& url, + const LLSD& body, + LLHTTPClient::ResponderPtr responder, + const LLSD& headers, + const F32 timeout) +{ + LLSD record; + record["url"] = url; + record["body"] = body; + record["headers"] = headers; + record["timeout"] = timeout; + gPostRecords->append(record); + + // Magic URL that triggers a 503: + if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 ) + { + responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason"); + } + else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) + { + LLSD result; + LLSD error; + error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE; + result["error"] = error; + responder->result(result); + } + else { + responder->result(LLSD()); + } +} + +const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; + +class LLMediaDataClientObjectTest : public LLMediaDataClientObject +{ +public: + LLMediaDataClientObjectTest(const char *data) + { + std::istringstream d(data); + LLSDSerialize::fromXML(mRep, d); + mNumBounceBacks = 0; + + // std::cout << ll_pretty_print_sd(mRep) << std::endl; + // std::cout << "ID: " << getID() << std::endl; + } + LLMediaDataClientObjectTest(const LLSD &rep) + : mRep(rep), mNumBounceBacks(0) {} + ~LLMediaDataClientObjectTest() + { LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; } + + virtual U8 getMediaDataCount() const + { return mRep["media_data"].size(); } + virtual LLSD getMediaDataLLSD(U8 index) const + { return mRep["media_data"][(LLSD::Integer)index]; } + virtual LLUUID getID() const + { return mRep["uuid"]; } + virtual void mediaNavigateBounceBack(U8 index) + { + mNumBounceBacks++; + } + + virtual bool hasMedia() const + { return mRep.has("media_data"); } + + virtual void updateObjectMediaData(LLSD const &media_data_array) + { mRep["media_data"] = media_data_array; } + + virtual F64 getDistanceFromAvatar() const + { return (LLSD::Real)mRep["distance"]; } + + virtual F64 getTotalMediaInterest() const + { return (LLSD::Real)mRep["interest"]; } + + virtual std::string getCapabilityUrl(const std::string &name) const + { return mRep["cap_urls"][name]; } + + int getNumBounceBacks() const + { return mNumBounceBacks; } + +private: + LLSD mRep; + int mNumBounceBacks; +}; + +// This special timer delay should ensure that the timer will fire on the very +// next pump, no matter what (though this does make an assumption about the +// implementation of LLEventTimer::updateClass()): +const F32 NO_PERIOD = -1000.0f; + +static void pump_timers() +{ + LLEventTimer::updateClass(); +} + +namespace tut +{ + struct mediadataclient + { + mediadataclient() { + gPostRecords = &mLLSD; + + //LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + //LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG); + //LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG); + } + LLSD mLLSD; + }; + + typedef test_group<mediadataclient> mediadataclient_t; + typedef mediadataclient_t::object mediadataclient_object_t; + tut::mediadataclient_t tut_mediadataclient("mediadataclient"); + + void ensure(const std::string &msg, int value, int expected) + { + std::string m = msg; + m += " value: " + STR(value); + m += ", expected: " + STR(expected); + ensure(m, value == expected); + } + + void ensure(const std::string &msg, const std::string & value, const std::string & expected) + { + std::string m = msg; + m += " value: " + value; + m += ", expected: " + expected; + ensure(m, value == expected); + } + + void ensure(const std::string &msg, const LLUUID & value, const LLUUID & expected) + { + std::string m = msg; + m += " value: " + value.asString(); + m += ", expected: " + expected.asString(); + ensure(m, value == expected); + } + + void ensure_llsd(const std::string &msg, const LLSD & value, const char *expected) + { + LLSD expected_llsd; + std::istringstream e(expected); + LLSDSerialize::fromXML(expected_llsd, e); + + std::string value_str = ll_pretty_print_sd(value); + std::string expected_str = ll_pretty_print_sd(expected_llsd); + std::string m = msg; + m += " value: " + value_str; + m += ", expected: " + expected_str; + ensure(m, value_str == expected_str); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + template<> template<> + void mediadataclient_object_t::test<1>() + { + // + // Test fetchMedia() + // + LOG_TEST(1); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); + int num_refs_start = o->getNumRefs(); + { + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + mdc->fetchMedia(o); + + // Make sure no posts happened yet... + ensure("post records", gPostRecords->size(), 0); + + ::pump_timers(); + + ensure("post records", gPostRecords->size(), 1); + ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL); + ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET"); + ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); + ensure("queue empty", mdc->isEmpty()); + } + + // Make sure everyone's destroyed properly + ensure("REF COUNT", o->getNumRefs(), num_refs_start); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + template<> template<> + void mediadataclient_object_t::test<2>() + { + // + // Test updateMedia() + // + LOG_TEST(2); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); + { + // queue time w/ no delay ensures that ::pump_timers() will hit the tick() + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + mdc->updateMedia(o); + ensure("post records", gPostRecords->size(), 0); + ::pump_timers(); + + ensure("post records", gPostRecords->size(), 1); + ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL); + ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE"); + ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); + ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY], + "<llsd>" MEDIA_DATA "</llsd>"); + ensure("queue empty", mdc->isEmpty()); + } + + ensure("REF COUNT", o->getNumRefs(), 1); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + template<> template<> + void mediadataclient_object_t::test<3>() + { + // + // Test navigate() + // + LOG_TEST(3); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA); + { + LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD); + const char *TEST_URL = "http://example.com"; + mdc->navigate(o, 0, TEST_URL); + ensure("post records", gPostRecords->size(), 0); + ::pump_timers(); + + // ensure no bounce back + ensure("bounce back", dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), 0); + + ensure("post records", gPostRecords->size(), 1); + ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL); + ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); + ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0); + ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL); + ensure("queue empty", mdc->isEmpty()); + } + ensure("REF COUNT", o->getNumRefs(), 1); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + template<> template<> + void mediadataclient_object_t::test<4>() + { + // + // Test queue ordering + // + LOG_TEST(4); + + LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest( + _DATA(VALID_OBJECT_ID_1,"3.0","1.0")); + LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest( + _DATA(VALID_OBJECT_ID_2,"1.0","1.0")); + LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest( + _DATA(VALID_OBJECT_ID_3,"2.0","1.0")); + { + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD); + const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 }; + mdc->fetchMedia(o1); + mdc->fetchMedia(o2); + mdc->fetchMedia(o3); + + // Make sure no posts happened yet... + ensure("post records", gPostRecords->size(), 0); + + // tick 3 times... + ::pump_timers(); + ensure("post records", gPostRecords->size(), 1); + ::pump_timers(); + ensure("post records", gPostRecords->size(), 2); + ::pump_timers(); + ensure("post records", gPostRecords->size(), 3); + + for( int i=0; i < 3; i++ ) + { + ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL); + ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET"); + ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), + LLUUID(ORDERED_OBJECT_IDS[i])); + } + + ensure("queue empty", mdc->isEmpty()); + } + ensure("refcount of o1", o1->getNumRefs(), 1); + ensure("refcount of o2", o2->getNumRefs(), 1); + ensure("refcount of o3", o3->getNumRefs(), 1); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + template<> template<> + void mediadataclient_object_t::test<5>() + { + // + // Test fetchMedia() getting a 503 error + // + LOG_TEST(5); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest( + _DATA_URLS(VALID_OBJECT_ID, + "1.0", + "1.0", + FAKE_OBJECT_MEDIA_CAP_URL_503, + FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)); + int num_refs_start = o->getNumRefs(); + { + const int NUM_RETRIES = 5; + LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD,NUM_RETRIES); + + // This should generate a retry + mdc->fetchMedia(o); + + // Make sure no posts happened yet... + ensure("post records before", gPostRecords->size(), 0); + + // Once, causes retry + // Second, fires retry timer + // Third, fires queue timer again + for (int i=0; i<NUM_RETRIES; ++i) + { + ::pump_timers(); // Should pump (fire) the queue timer, causing a retry timer to be scheduled + // XXX This ensure is not guaranteed, because scheduling a timer might actually get it pumped in the same loop + //ensure("post records " + STR(i), gPostRecords->size(), i+1); + ::pump_timers(); // Should pump (fire) the retry timer, scheduling the queue timer + } + + // Do some extra pumps to make sure no other timer work occurs. + ::pump_timers(); + ::pump_timers(); + ::pump_timers(); + + // Make sure there were 2 posts + ensure("post records after", gPostRecords->size(), NUM_RETRIES); + for (int i=0; i<NUM_RETRIES; ++i) + { + ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503); + ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET"); + ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); + } + ensure("queue empty", mdc->isEmpty()); + } + + // Make sure everyone's destroyed properly + ensure("REF COUNT", o->getNumRefs(), num_refs_start); + } + + template<> template<> + void mediadataclient_object_t::test<6>() + { + // + // Test navigate() with a bounce back + // + LOG_TEST(6); + + LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest( + _DATA_URLS(VALID_OBJECT_ID, + "1.0", + "1.0", + FAKE_OBJECT_MEDIA_CAP_URL, + FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)); + { + LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD); + const char *TEST_URL = "http://example.com"; + mdc->navigate(o, 0, TEST_URL); + ensure("post records", gPostRecords->size(), 0); + ::pump_timers(); + + // ensure bounce back + ensure("bounce back", + dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), + 1); + + ensure("post records", gPostRecords->size(), 1); + ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR); + ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID)); + ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0); + ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL); + ensure("queue empty", mdc->isEmpty()); + } + ensure("REF COUNT", o->getNumRefs(), 1); + } + + +} diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 40f7d532bc..988d28c301 100644 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -30,6 +30,9 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ +// Precompiled header +#include "../llviewerprecompiledheaders.h" + #include "../test/lltut.h" #include "../llviewerhelputil.h" diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp new file mode 100644 index 0000000000..c94ba0a3e8 --- /dev/null +++ b/indra/newview/tests/llxmlrpclistener_test.cpp @@ -0,0 +1,230 @@ +/* + * @file llxmlrpclistener_test.cpp + * @author Nat Goodspeed + * @date 2009-03-20 + * @brief Test for llxmlrpclistener. + * + * $LicenseInfo:firstyear=2009&license=internal$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "../llviewerprecompiledheaders.h" +// associated header +#include "../llxmlrpclistener.h" +// STL headers +#include <iomanip> +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "../llxmlrpctransaction.h" +#include "llevents.h" +#include "lleventfilter.h" +#include "llsd.h" +#include "llcontrol.h" +#include "tests/wrapllerrs.h" + +LLControlGroup gSavedSettings("Global"); + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct data + { + data(): + pumps(LLEventPumps::instance()), + uri("http://127.0.0.1:8000") + { + // These variables are required by machinery used by + // LLXMLRPCTransaction. The values reflect reality for this test + // executable; hopefully these values are correct. + gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist + gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist + } + + // LLEventPump listener signature + bool captureReply(const LLSD& r) + { + reply = r; + return false; + } + + LLSD reply; + LLEventPumps& pumps; + std::string uri; + }; + typedef test_group<data> llxmlrpclistener_group; + typedef llxmlrpclistener_group::object object; + llxmlrpclistener_group llxmlrpclistenergrp("llxmlrpclistener"); + + template<> template<> + void object::test<1>() + { + set_test_name("request validation"); + WrapLL_ERRS capture; + LLSD request; + request["uri"] = uri; + std::string threw; + try + { + pumps.obtain("LLXMLRPCTransaction").post(request); + } + catch (const WrapLL_ERRS::FatalException& e) + { + threw = e.what(); + } + ensure_contains("threw exception", threw, "missing params"); + ensure_contains("identified missing", threw, "method"); + ensure_contains("identified missing", threw, "reply"); + } + + template<> template<> + void object::test<2>() + { + set_test_name("param types validation"); + WrapLL_ERRS capture; + LLSD request; + request["uri"] = uri; + request["method"] = "hello"; + request["reply"] = "reply"; + LLSD& params(request["params"]); + params["who"]["specifically"] = "world"; // LLXMLRPCListener only handles scalar params + std::string threw; + try + { + pumps.obtain("LLXMLRPCTransaction").post(request); + } + catch (const WrapLL_ERRS::FatalException& e) + { + threw = e.what(); + } + ensure_contains("threw exception", threw, "unknown type"); + } + + template<> template<> + void object::test<3>() + { + set_test_name("success case"); + LLSD request; + request["uri"] = uri; + request["method"] = "hello"; + request["reply"] = "reply"; + LLSD& params(request["params"]); + params["who"] = "world"; + // Set up a timeout filter so we don't spin forever waiting. + LLEventTimeout watchdog; + // Connect the timeout filter to the reply pump. + LLTempBoundListener temp( + pumps.obtain("reply"). + listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1))); + // Now connect our target listener to the timeout filter. + watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1)); + // Kick off the request... + reply.clear(); + pumps.obtain("LLXMLRPCTransaction").post(request); + // Set the timer + F32 timeout(10); + watchdog.eventAfter(timeout, LLSD().insert("timeout", 0)); + // and pump "mainloop" until we get something, whether from + // LLXMLRPCListener or from the watchdog filter. + LLTimer timer; + F32 start = timer.getElapsedTimeF32(); + LLEventPump& mainloop(pumps.obtain("mainloop")); + while (reply.isUndefined()) + { + mainloop.post(LLSD()); + } + ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1)); + ensure_equals(reply["responses"]["hi_there"].asString(), "Hello, world!"); + } + + template<> template<> + void object::test<4>() + { + set_test_name("bogus method"); + LLSD request; + request["uri"] = uri; + request["method"] = "goodbye"; + request["reply"] = "reply"; + LLSD& params(request["params"]); + params["who"] = "world"; + // Set up a timeout filter so we don't spin forever waiting. + LLEventTimeout watchdog; + // Connect the timeout filter to the reply pump. + LLTempBoundListener temp( + pumps.obtain("reply"). + listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1))); + // Now connect our target listener to the timeout filter. + watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1)); + // Kick off the request... + reply.clear(); + pumps.obtain("LLXMLRPCTransaction").post(request); + // Set the timer + F32 timeout(10); + watchdog.eventAfter(timeout, LLSD().insert("timeout", 0)); + // and pump "mainloop" until we get something, whether from + // LLXMLRPCListener or from the watchdog filter. + LLTimer timer; + F32 start = timer.getElapsedTimeF32(); + LLEventPump& mainloop(pumps.obtain("mainloop")); + while (reply.isUndefined()) + { + mainloop.post(LLSD()); + } + ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1)); + ensure_equals("XMLRPC error", reply["status"].asString(), "XMLRPCError"); + } + + template<> template<> + void object::test<5>() + { + set_test_name("bad type"); + LLSD request; + request["uri"] = uri; + request["method"] = "getdict"; + request["reply"] = "reply"; + (void)request["params"]; + // Set up a timeout filter so we don't spin forever waiting. + LLEventTimeout watchdog; + // Connect the timeout filter to the reply pump. + LLTempBoundListener temp( + pumps.obtain("reply"). + listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1))); + // Now connect our target listener to the timeout filter. + watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1)); + // Kick off the request... + reply.clear(); + pumps.obtain("LLXMLRPCTransaction").post(request); + // Set the timer + F32 timeout(10); + watchdog.eventAfter(timeout, LLSD().insert("timeout", 0)); + // and pump "mainloop" until we get something, whether from + // LLXMLRPCListener or from the watchdog filter. + LLTimer timer; + F32 start = timer.getElapsedTimeF32(); + LLEventPump& mainloop(pumps.obtain("mainloop")); + while (reply.isUndefined()) + { + mainloop.post(LLSD()); + } + ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1)); + ensure_equals(reply["status"].asString(), "BadType"); + ensure_contains("bad type", reply["responses"]["nested_dict"].asString(), "bad XMLRPC type"); + } +} // namespace tut + +/***************************************************************************** +* Resolve link errors: use real machinery here, since we intend to exchange +* actual XML with a peer process. +*****************************************************************************/ +// Including llxmlrpctransaction.cpp drags in the static LLXMLRPCListener +// instantiated there. That's why it works to post requests to the LLEventPump +// named "LLXMLRPCTransaction". +#include "../llxmlrpctransaction.cpp" +#include "llcontrol.cpp" +#include "llxmltree.cpp" +#include "llxmlparser.cpp" diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py new file mode 100644 index 0000000000..cb8f7d26c4 --- /dev/null +++ b/indra/newview/tests/test_llxmlrpc_peer.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +"""\ +@file test_llxmlrpc_peer.py +@author Nat Goodspeed +@date 2008-10-09 +@brief This script asynchronously runs the executable (with args) specified on + the command line, returning its result code. While that executable is + running, we provide dummy local services for use by C++ tests. + +$LicenseInfo:firstyear=2008&license=viewergpl$ +Copyright (c) 2008, Linden Research, Inc. +$/LicenseInfo$ +""" + +import os +import sys +from threading import Thread +from SimpleXMLRPCServer import SimpleXMLRPCServer + +mydir = os.path.dirname(__file__) # expected to be .../indra/newview/tests/ +sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) +sys.path.insert(1, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) +from testrunner import run, debug + +class TestServer(SimpleXMLRPCServer): + def _dispatch(self, method, params): + try: + func = getattr(self, method) + except AttributeError: + raise Exception('method "%s" is not supported' % method) + else: + # LLXMLRPCListener constructs XMLRPC parameters that arrive as a + # 1-tuple containing a dict. + return func(**(params[0])) + + def hello(self, who): + # LLXMLRPCListener expects a dict return. + return {"hi_there": "Hello, %s!" % who} + + def getdict(self): + return dict(nested_dict=dict(a=17, b=5)) + + def log_request(self, code, size=None): + # For present purposes, we don't want the request splattered onto + # stderr, as it would upset devs watching the test run + pass + + def log_error(self, format, *args): + # Suppress error output as well + pass + +class ServerRunner(Thread): + def run(self): + server = TestServer(('127.0.0.1', 8000)) + debug("Starting XMLRPC server...\n") + server.serve_forever() + +if __name__ == "__main__": + sys.exit(run(server=ServerRunner(name="xmlrpc"), *sys.argv[1:])) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 045990811b..b85d31d1ac 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -164,28 +164,103 @@ class WindowsManifest(ViewerManifest): return ''.join(self.channel().split()) + '.exe' + def test_msvcrt_and_copy_action(self, src, dst): + # This is used to test a dll manifest. + # It is used as a temporary override during the construct method + from test_win32_manifest import test_assembly_binding + if src and (os.path.exists(src) or os.path.islink(src)): + # ensure that destination path exists + self.cmakedirs(os.path.dirname(dst)) + self.created_paths.append(dst) + if not os.path.isdir(src): + if(self.args['configuration'].lower() == 'debug'): + test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "8.0.50727.4053") + else: + test_assembly_binding(src, "Microsoft.VC80.CRT", "8.0.50727.4053") + self.ccopy(src,dst) + else: + raise Exception("Directories are not supported by test_CRT_and_copy_action()") + else: + print "Doesn't exist:", src + + def test_for_no_msvcrt_manifest_and_copy_action(self, src, dst): + # This is used to test that no manifest for the msvcrt exists. + # It is used as a temporary override during the construct method + from test_win32_manifest import test_assembly_binding + from test_win32_manifest import NoManifestException, NoMatchingAssemblyException + if src and (os.path.exists(src) or os.path.islink(src)): + # ensure that destination path exists + self.cmakedirs(os.path.dirname(dst)) + self.created_paths.append(dst) + if not os.path.isdir(src): + try: + if(self.args['configuration'].lower() == 'debug'): + test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "") + else: + test_assembly_binding(src, "Microsoft.VC80.CRT", "") + raise Exception("Unknown condition") + except NoManifestException, err: + pass + except NoMatchingAssemblyException, err: + pass + + self.ccopy(src,dst) + else: + raise Exception("Directories are not supported by test_CRT_and_copy_action()") + else: + print "Doesn't exist:", src + + def enable_crt_manifest_check(self): + WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action + + def enable_no_crt_manifest_check(self): + WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action + + def disable_manifest_check(self): + del WindowsManifest.copy_action + def construct(self): super(WindowsManifest, self).construct() - # the final exe is complicated because we're not sure where it's coming from, - # nor do we have a fixed name for the executable - self.path(self.find_existing_file('debug/secondlife-bin.exe', 'release/secondlife-bin.exe', 'relwithdebinfo/secondlife-bin.exe'), dst=self.final_exe()) + # 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()) + + self.enable_crt_manifest_check() # Plugin host application self.path(os.path.join(os.pardir, 'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"), "slplugin.exe") - - # need to get the kdu dll from any of the build directories as well + + # need to get the llcommon.dll from the build directory as well + if self.prefix(src=self.args['configuration'], dst=""): + try: + self.path('llcommon.dll') + self.path('libapr-1.dll') + self.path('libaprutil-1.dll') + self.path('libapriconv-1.dll') + except RuntimeError, err: + print err.message + print "Skipping llcommon.dll (assuming llcommon was linked statically)" + + self.end_prefix() + + # need to get the kdu dll from the build directory as well try: - self.path(self.find_existing_file('../llkdu/%s/llkdu.dll' % self.args['configuration'], - '../../libraries/i686-win32/lib/release/llkdu.dll'), - dst='llkdu.dll') - pass - except: + self.path('%s/llkdu.dll' % self.args['configuration'], dst='llkdu.dll') + except RuntimeError: print "Skipping llkdu.dll" - pass - self.path(src="licenses-win32.txt", dst="licenses.txt") + self.disable_manifest_check() + + # For textures + if self.prefix(src=self.args['configuration'], dst=""): + if(self.args['configuration'].lower() == 'debug'): + self.path("openjpegd.dll") + else: + self.path("openjpeg.dll") + self.end_prefix() + + self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") # For use in crash reporting (generates minidumps) @@ -194,11 +269,7 @@ class WindowsManifest(ViewerManifest): # For using FMOD for sound... DJS self.path("fmod.dll") - # For textures - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("openjpeg.dll") - self.end_prefix() - + 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") @@ -209,7 +280,6 @@ class WindowsManifest(ViewerManifest): self.path("media_plugin_webkit.dll") self.end_prefix() - # For WebKit/Qt plugin runtimes if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): self.path("libeay32.dll") self.path("qtcore4.dll") @@ -230,6 +300,8 @@ class WindowsManifest(ViewerManifest): self.path("qtiff4.dll") self.end_prefix() + self.disable_manifest_check() + # These need to be installed as a SxS assembly, currently a 'private' assembly. # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx if self.prefix(src=self.args['configuration'], dst=""): @@ -243,11 +315,8 @@ class WindowsManifest(ViewerManifest): self.path("Microsoft.VC80.CRT.manifest") self.end_prefix() - # The config file name needs to match the exe's name. - self.path(src="%s/secondlife-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config") - # Vivox runtimes - if self.prefix(src="vivox-runtime/i686-win32", dst=""): + if self.prefix(src=self.args['configuration'], dst=""): self.path("SLVoice.exe") self.path("alut.dll") self.path("vivoxsdk.dll") @@ -256,22 +325,22 @@ class WindowsManifest(ViewerManifest): self.end_prefix() # pull in the crash logger and updater from other projects - self.path(src=self.find_existing_file( # tag:"crash-logger" here as a cue to the exporter - "../win_crash_logger/debug/windows-crash-logger.exe", - "../win_crash_logger/release/windows-crash-logger.exe", - "../win_crash_logger/relwithdebinfo/windows-crash-logger.exe"), + # 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") - self.path(src=self.find_existing_file( - "../win_updater/debug/windows-updater.exe", - "../win_updater/release/windows-updater.exe", - "../win_updater/relwithdebinfo/windows-updater.exe"), + self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'], dst="updater.exe") # For google-perftools tcmalloc allocator. - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("libtcmalloc_minimal.dll") - self.end_prefix() - + if self.prefix(src=self.args['configuration'], dst=""): + try: + if self.args['configuration'] == 'Debug': + self.path('libtcmalloc_minimal-debug.dll') + else: + self.path('libtcmalloc_minimal.dll') + except: + print "Skipping libtcmalloc_minimal.dll" + self.end_prefix() def nsi_file_commands(self, install=True): def wpath(path): @@ -392,7 +461,11 @@ class WindowsManifest(ViewerManifest): # We use the Unicode version of NSIS, available from # http://www.scratchpaper.com/ - NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe' + # Check two paths, one for Program Files, and one for Program Files (x86). + # Yay 64bit windows. + NSIS_path = os.path.expandvars('${ProgramFiles}\\NSIS\\Unicode\\makensis.exe') + if not os.path.exists(NSIS_path): + NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe') self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) # self.remove(self.dst_path_of(tempfile)) # If we're on a build machine, sign the code using our Authenticode certificate. JC @@ -468,16 +541,31 @@ class DarwinManifest(ViewerManifest): self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") + libdir = "../../libraries/universal-darwin/lib_release" + dylibs = {} + # need to get the kdu dll from any of the build directories as well - try: - self.path(self.find_existing_file('../llkdu/%s/libllkdu.dylib' % self.args['configuration'], - "../../libraries/universal-darwin/lib_release/libllkdu.dylib"), - dst='libllkdu.dylib') - pass - except: - print "Skipping libllkdu.dylib" - pass - + for lib in "llkdu", "llcommon": + libfile = "lib%s.dylib" % lib + try: + self.path(self.find_existing_file(os.path.join(os.pardir, + lib, + self.args['configuration'], + libfile), + os.path.join(libdir, libfile)), + dst=libfile) + except RuntimeError: + print "Skipping %s" % libfile + dylibs[lib] = False + else: + dylibs[lib] = True + + if dylibs["llcommon"]: + for libfile in ("libapr-1.0.3.7.dylib", + "libaprutil-1.0.3.8.dylib", + "libexpat.0.5.0.dylib"): + self.path(os.path.join(libdir, libfile), libfile) + #libfmodwrapper.dylib self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib") @@ -485,6 +573,24 @@ class DarwinManifest(ViewerManifest): self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + # our apps dependencies on shared libs + if dylibs["llcommon"]: + mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources") + mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources") + for libfile in ("libllcommon.dylib", + "libapr-1.0.3.7.dylib", + "libaprutil-1.0.3.8.dylib", + "libexpat.0.5.0.dylib"): + target_lib = os.path.join('../../..', libfile) + self.run_command("ln -sf %(target)r %(link)r" % + {'target': target_lib, + 'link' : os.path.join(mac_crash_logger_res_path, libfile)} + ) + self.run_command("ln -sf %(target)r %(link)r" % + {'target': target_lib, + 'link' : os.path.join(mac_updater_res_path, libfile)} + ) + # plugin launcher self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") @@ -509,7 +615,7 @@ class DarwinManifest(ViewerManifest): # This may be desirable for the final release. Or not. if ("package" in self.args['actions'] or "unpacked" in self.args['actions']): - self.run_command('strip -S "%(viewer_binary)s"' % + self.run_command('strip -S %(viewer_binary)r' % { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')}) @@ -538,12 +644,12 @@ class DarwinManifest(ViewerManifest): # make sure we don't have stale files laying about self.remove(sparsename, finalname) - self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % { + self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % { 'sparse':sparsename, 'vol':volname}) # mount the image and get the name of the mount point and device node - hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"') + hdi_output = self.run_command('hdiutil attach -private %r' % sparsename) devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip() volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() @@ -577,24 +683,25 @@ class DarwinManifest(ViewerManifest): self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit) - self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"') - self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"') - self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"') + for f in ".VolumeIcon.icns", "background.jpg", ".DS_Store": + self.run_command('SetFile -a V %r' % os.path.join(volpath, f)) # Create the alias file (which is a resource file) from the .r - self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"') + self.run_command('rez %r -o %r' % + (self.src_path_of("installers/darwin/release-dmg/Applications-alias.r"), + os.path.join(volpath, "Applications"))) # Set the alias file's alias and custom icon bits - self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"') + self.run_command('SetFile -a AC %r' % os.path.join(volpath, "Applications")) # Set the disk image root's custom icon bit - self.run_command('SetFile -a C "' + volpath + '"') + self.run_command('SetFile -a C %r' % volpath) # Unmount the image - self.run_command('hdiutil detach -force "' + devfile + '"') + self.run_command('hdiutil detach -force %r' % devfile) print "Converting temp disk image to final disk image" - self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname}) + self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname}) # get rid of the temp file self.package_file = finalname self.remove(sparsename) @@ -667,15 +774,17 @@ class Linux_i686Manifest(LinuxManifest): # install either the libllkdu we just built, or a prebuilt one, in # decreasing order of preference. for linux package, this goes to bin/ - try: - self.path(self.find_existing_file('../llkdu/libllkdu.so', - '../../libraries/i686-linux/lib_release_client/libllkdu.so'), - dst='bin/libllkdu.so') - # keep this one to preserve syntax, open source mangling removes previous lines - pass - except: - print "Skipping libllkdu.so - not found" - pass + for lib, destdir in ("llkdu", "bin"), ("llcommon", "lib"): + libfile = "lib%s.so" % lib + try: + self.path(self.find_existing_file(os.path.join(os.pardir, lib, libfile), + '../../libraries/i686-linux/lib_release_client/%s' % libfile), + dst=os.path.join(destdir, libfile)) + # keep this one to preserve syntax, open source mangling removes previous lines + pass + except RuntimeError: + print "Skipping %s - not found" % libfile + pass self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin") self.path("../linux_crash_logger/linux-crash-logger-stripped","bin/linux-crash-logger.bin") |