diff options
Diffstat (limited to 'indra/newview')
200 files changed, 7482 insertions, 3345 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..fd0e05e7e2 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5316,6 +5316,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 +5415,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 +10036,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/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/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 bc1a3cd0af..83f1013889 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..22c3779050 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,7 +334,6 @@ LLSideTrayTab* LLSideTray::getTab(const std::string& name)  } -  void LLSideTray::toggleTabButton	(LLSideTrayTab* tab)  {  	if(tab == NULL) @@ -393,25 +435,30 @@ 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; -		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) @@ -514,25 +561,33 @@ void LLSideTray::arrange			()  	}  } -void LLSideTray::collapseSideBar	() +void LLSideTray::collapseSideBar()  {  	mCollapsed = true; -	mCollapseButton->setLabel(COLLAPSED_NAME); +	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() diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 6ea6bafac9..845eb86bc1 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,14 +62,7 @@ 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		(); @@ -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..5967b68e51 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -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..95459a7116 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -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/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 d05e55a501..2b2ac81487 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/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_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 395b574425..6abcbc40d2 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"    > 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")  | 
