summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt191
-rw-r--r--indra/newview/English.lproj/InfoPlist.strings4
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/app_settings/settings.xml24
-rw-r--r--indra/newview/build_win32_appConfig.py28
-rw-r--r--indra/newview/character/avatar_eye.llmbin0 -> 16011 bytes
-rw-r--r--indra/newview/character/avatar_eye_1.llmbin0 -> 5591 bytes
-rw-r--r--indra/newview/character/avatar_eyelashes.llmbin0 -> 65637 bytes
-rw-r--r--indra/newview/character/avatar_hair.llmbin0 -> 690581 bytes
-rw-r--r--indra/newview/character/avatar_hair_1.llmbin0 -> 5031 bytes
-rw-r--r--indra/newview/character/avatar_hair_2.llmbin0 -> 3261 bytes
-rw-r--r--indra/newview/character/avatar_hair_3.llmbin0 -> 1845 bytes
-rw-r--r--indra/newview/character/avatar_hair_4.llmbin0 -> 927 bytes
-rw-r--r--indra/newview/character/avatar_hair_5.llmbin0 -> 927 bytes
-rw-r--r--indra/newview/character/avatar_head.llmbin0 -> 1665493 bytes
-rw-r--r--indra/newview/character/avatar_head_1.llmbin0 -> 7875 bytes
-rw-r--r--indra/newview/character/avatar_head_2.llmbin0 -> 3675 bytes
-rw-r--r--indra/newview/character/avatar_head_3.llmbin0 -> 1797 bytes
-rw-r--r--indra/newview/character/avatar_head_4.llmbin0 -> 1239 bytes
-rw-r--r--indra/newview/character/avatar_lower_body.llmbin0 -> 337125 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_1.llmbin0 -> 7083 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_2.llmbin0 -> 4107 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_3.llmbin0 -> 2115 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_4.llmbin0 -> 1629 bytes
-rw-r--r--indra/newview/character/avatar_skirt.llmbin0 -> 72497 bytes
-rw-r--r--indra/newview/character/avatar_skirt_1.llmbin0 -> 1899 bytes
-rw-r--r--indra/newview/character/avatar_skirt_2.llmbin0 -> 1551 bytes
-rw-r--r--indra/newview/character/avatar_skirt_3.llmbin0 -> 1191 bytes
-rw-r--r--indra/newview/character/avatar_skirt_4.llmbin0 -> 843 bytes
-rw-r--r--indra/newview/character/avatar_upper_body.llmbin0 -> 929297 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_1.llmbin0 -> 15627 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_2.llmbin0 -> 8991 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_3.llmbin0 -> 4557 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_4.llmbin0 -> 3453 bytes
-rw-r--r--indra/newview/character/blush_alpha.tgabin0 -> 17352 bytes
-rw-r--r--indra/newview/character/body_skingrain.tgabin0 -> 262188 bytes
-rw-r--r--indra/newview/character/bodyfreckles_alpha.tgabin0 -> 257249 bytes
-rw-r--r--indra/newview/character/bump_face_wrinkles.tgabin0 -> 25243 bytes
-rw-r--r--indra/newview/character/bump_head_base.tgabin0 -> 105525 bytes
-rw-r--r--indra/newview/character/bump_lowerbody_base.tgabin0 -> 112782 bytes
-rw-r--r--indra/newview/character/bump_pants_wrinkles.tgabin0 -> 83183 bytes
-rw-r--r--indra/newview/character/bump_shirt_wrinkles.tgabin0 -> 81501 bytes
-rw-r--r--indra/newview/character/bump_upperbody_base.tgabin0 -> 147581 bytes
-rw-r--r--indra/newview/character/eyebrows_alpha.tgabin0 -> 9469 bytes
-rw-r--r--indra/newview/character/eyeliner_alpha.tgabin0 -> 4720 bytes
-rw-r--r--indra/newview/character/eyeshadow_inner_alpha.tgabin0 -> 5466 bytes
-rw-r--r--indra/newview/character/eyeshadow_outer_alpha.tgabin0 -> 7382 bytes
-rw-r--r--indra/newview/character/eyewhite.tgabin0 -> 42353 bytes
-rw-r--r--indra/newview/character/facehair_chincurtains_alpha.tgabin0 -> 34610 bytes
-rw-r--r--indra/newview/character/facehair_moustache_alpha.tgabin0 -> 14017 bytes
-rw-r--r--indra/newview/character/facehair_sideburns_alpha.tgabin0 -> 27328 bytes
-rw-r--r--indra/newview/character/facehair_soulpatch_alpha.tgabin0 -> 11277 bytes
-rw-r--r--indra/newview/character/freckles_alpha.tgabin0 -> 140558 bytes
-rw-r--r--indra/newview/character/glove_length_alpha.tgabin0 -> 49745 bytes
-rw-r--r--indra/newview/character/gloves_fingers_alpha.tgabin0 -> 39616 bytes
-rw-r--r--indra/newview/character/head_alpha.tgabin0 -> 6066 bytes
-rw-r--r--indra/newview/character/head_color.tgabin0 -> 70715 bytes
-rw-r--r--indra/newview/character/head_hair.tgabin0 -> 75600 bytes
-rw-r--r--indra/newview/character/head_highlights_alpha.tgabin0 -> 20503 bytes
-rw-r--r--indra/newview/character/head_shading_alpha.tgabin0 -> 35304 bytes
-rw-r--r--indra/newview/character/head_skingrain.tgabin0 -> 262376 bytes
-rw-r--r--indra/newview/character/jacket_length_lower_alpha.tgabin0 -> 9768 bytes
-rw-r--r--indra/newview/character/jacket_length_upper_alpha.tgabin0 -> 14617 bytes
-rw-r--r--indra/newview/character/jacket_open_lower_alpha.tgabin0 -> 19732 bytes
-rw-r--r--indra/newview/character/jacket_open_upper_alpha.tgabin0 -> 41606 bytes
-rw-r--r--indra/newview/character/lipgloss_alpha.tgabin0 -> 4738 bytes
-rw-r--r--indra/newview/character/lips_mask.tgabin0 -> 6110 bytes
-rw-r--r--indra/newview/character/lipstick_alpha.tgabin0 -> 7966 bytes
-rw-r--r--indra/newview/character/lowerbody_color.tgabin0 -> 135395 bytes
-rw-r--r--indra/newview/character/lowerbody_highlights_alpha.tgabin0 -> 8695 bytes
-rw-r--r--indra/newview/character/lowerbody_shading_alpha.tgabin0 -> 41766 bytes
-rw-r--r--indra/newview/character/nailpolish_alpha.tgabin0 -> 4656 bytes
-rw-r--r--indra/newview/character/pants_length_alpha.tgabin0 -> 26843 bytes
-rw-r--r--indra/newview/character/pants_waist_alpha.tgabin0 -> 10487 bytes
-rw-r--r--indra/newview/character/rosyface_alpha.tgabin0 -> 44382 bytes
-rw-r--r--indra/newview/character/rouge_alpha.tgabin0 -> 44382 bytes
-rw-r--r--indra/newview/character/shirt_bottom_alpha.tgabin0 -> 32242 bytes
-rw-r--r--indra/newview/character/shirt_collar_alpha.tgabin0 -> 14417 bytes
-rw-r--r--indra/newview/character/shirt_collar_back_alpha.tgabin0 -> 12789 bytes
-rw-r--r--indra/newview/character/shirt_sleeve_alpha.tgabin0 -> 72196 bytes
-rw-r--r--indra/newview/character/shoe_height_alpha.tgabin0 -> 24461 bytes
-rw-r--r--indra/newview/character/skirt_length_alpha.tgabin0 -> 4114 bytes
-rw-r--r--indra/newview/character/skirt_slit_back_alpha.tgabin0 -> 90350 bytes
-rw-r--r--indra/newview/character/skirt_slit_front_alpha.tgabin0 -> 90350 bytes
-rw-r--r--indra/newview/character/skirt_slit_left_alpha.tgabin0 -> 82006 bytes
-rw-r--r--indra/newview/character/skirt_slit_right_alpha.tgabin0 -> 91410 bytes
-rw-r--r--indra/newview/character/underpants_trial_female.tgabin0 -> 48063 bytes
-rw-r--r--indra/newview/character/underpants_trial_male.tgabin0 -> 144983 bytes
-rw-r--r--indra/newview/character/undershirt_trial_female.tgabin0 -> 81390 bytes
-rw-r--r--indra/newview/character/upperbody_color.tgabin0 -> 23348 bytes
-rw-r--r--indra/newview/character/upperbody_highlights_alpha.tgabin0 -> 6509 bytes
-rw-r--r--indra/newview/character/upperbody_shading_alpha.tgabin0 -> 25297 bytes
-rw-r--r--indra/newview/character/upperbodyfreckles_alpha.tgabin0 -> 180104 bytes
-rw-r--r--indra/newview/licenses-mac.txt509
-rw-r--r--indra/newview/llagent.cpp6
-rw-r--r--indra/newview/llagent.h4
-rw-r--r--indra/newview/llagentlistener.cpp78
-rw-r--r--indra/newview/llagentlistener.h36
-rw-r--r--indra/newview/llappviewer.cpp257
-rw-r--r--indra/newview/llappviewer.h14
-rw-r--r--indra/newview/llappviewerlistener.cpp40
-rw-r--r--indra/newview/llappviewerlistener.h37
-rw-r--r--indra/newview/llcapabilitylistener.cpp1
-rw-r--r--indra/newview/llclassifiedinfo.cpp36
-rw-r--r--indra/newview/llclassifiedinfo.h3
-rw-r--r--indra/newview/lleventinfo.cpp36
-rw-r--r--indra/newview/lleventinfo.h3
-rw-r--r--indra/newview/lleventnotifier.cpp79
-rw-r--r--indra/newview/lleventnotifier.h5
-rw-r--r--indra/newview/llfasttimerview.cpp8
-rw-r--r--indra/newview/llfeaturemanager.cpp6
-rw-r--r--indra/newview/llfloaterabout.cpp585
-rw-r--r--indra/newview/llfloaterauction.cpp1
-rw-r--r--indra/newview/llfloaterbuyland.cpp16
-rw-r--r--indra/newview/llfloaterfriends.h3
-rw-r--r--indra/newview/llfloatermediasettings.cpp26
-rw-r--r--indra/newview/llfloatermediasettings.h2
-rw-r--r--indra/newview/llfloatertools.cpp16
-rw-r--r--indra/newview/llfloatertos.cpp37
-rw-r--r--indra/newview/llfloatertos.h4
-rw-r--r--indra/newview/llfolderviewitem.cpp4
-rw-r--r--indra/newview/llimview.cpp2
-rw-r--r--indra/newview/llinspect.h1
-rw-r--r--indra/newview/llinventoryactions.h47
-rw-r--r--indra/newview/llinventorymodel.cpp216
-rw-r--r--indra/newview/llinventorymodel.h6
-rw-r--r--indra/newview/lllocaltextureobject.cpp2
-rw-r--r--indra/newview/lllocaltextureobject.h5
-rw-r--r--indra/newview/lllogininstance.cpp475
-rw-r--r--indra/newview/lllogininstance.h114
-rw-r--r--indra/newview/llmediactrl.cpp48
-rwxr-xr-xindra/newview/llmediadataclient.cpp376
-rwxr-xr-xindra/newview/llmediadataclient.h88
-rw-r--r--indra/newview/llmenucommands.cpp1
-rw-r--r--indra/newview/llpanellandmarks.cpp1
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.cpp897
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.h3
-rw-r--r--indra/newview/llpanelmediasettingssecurity.cpp584
-rw-r--r--indra/newview/llpanelmediasettingssecurity.h7
-rw-r--r--indra/newview/llpanelplace.cpp1
-rw-r--r--indra/newview/llpanelplaceinfo.cpp1
-rw-r--r--indra/newview/llselectmgr.cpp20
-rw-r--r--indra/newview/llstartup.cpp1441
-rw-r--r--indra/newview/llstartup.h6
-rw-r--r--indra/newview/lltoolpie.cpp72
-rw-r--r--indra/newview/lluilistener.cpp50
-rw-r--r--indra/newview/lluilistener.h29
-rw-r--r--indra/newview/llviewercontrollistener.cpp102
-rw-r--r--indra/newview/llviewercontrollistener.h33
-rw-r--r--indra/newview/llviewermedia.cpp195
-rw-r--r--indra/newview/llviewermedia.h21
-rw-r--r--indra/newview/llviewermediafocus.cpp327
-rw-r--r--indra/newview/llviewermediafocus.h57
-rw-r--r--indra/newview/llviewermenu.cpp5
-rw-r--r--indra/newview/llviewernetwork.cpp6
-rw-r--r--indra/newview/llviewernetwork.h4
-rw-r--r--indra/newview/llviewerparcelmedia.cpp18
-rw-r--r--indra/newview/llviewerparcelmgr.cpp8
-rw-r--r--indra/newview/llviewerparcelmgr.h2
-rw-r--r--indra/newview/llviewertexture.cpp9
-rw-r--r--indra/newview/llviewerwindow.cpp14
-rw-r--r--indra/newview/llviewerwindow.h5
-rw-r--r--indra/newview/llviewerwindowlistener.cpp87
-rw-r--r--indra/newview/llviewerwindowlistener.h35
-rw-r--r--indra/newview/llvoavatar.cpp13
-rw-r--r--indra/newview/llvoavatarself.cpp13
-rw-r--r--indra/newview/llvoiceclient.cpp3
-rw-r--r--indra/newview/llvovolume.cpp280
-rw-r--r--indra/newview/llvovolume.h19
-rw-r--r--indra/newview/llwearable.cpp1
-rw-r--r--indra/newview/llxmlrpclistener.cpp496
-rw-r--r--indra/newview/llxmlrpclistener.h35
-rw-r--r--indra/newview/llxmlrpctransaction.cpp13
-rw-r--r--indra/newview/res/viewerRes.rc8
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml302
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml8
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml13
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_general.xml4
-rw-r--r--indra/newview/tests/llagentaccess_test.cpp2
-rw-r--r--indra/newview/tests/llcapabilitylistener_test.cpp36
-rw-r--r--indra/newview/tests/lldateutil_test.cpp3
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp423
-rw-r--r--indra/newview/tests/llmediadataclient_test.cpp501
-rw-r--r--indra/newview/tests/llviewerhelputil_test.cpp3
-rw-r--r--indra/newview/tests/llxmlrpclistener_test.cpp230
-rw-r--r--indra/newview/tests/test_llxmlrpc_peer.py59
-rwxr-xr-xindra/newview/viewer_manifest.py214
188 files changed, 7168 insertions, 3035 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 26170d1713..5fdf13b078 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,24 @@ 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 llkdu)
+ endif(WINDOWS)
if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
@@ -1374,8 +1415,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 +1474,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${WINDOWS_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
${ELFIO_LIBRARIES}
+ ${LLLOGIN_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
@@ -1545,7 +1608,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 +1627,7 @@ set(test_libs
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(llcapabilitylistener
@@ -1576,6 +1642,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 +1687,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
new file mode 100644
index 0000000000..8c6e74e1de
--- /dev/null
+++ b/indra/newview/character/avatar_eye.llm
Binary files differ
diff --git a/indra/newview/character/avatar_eye_1.llm b/indra/newview/character/avatar_eye_1.llm
new file mode 100644
index 0000000000..7a3b0d6f28
--- /dev/null
+++ b/indra/newview/character/avatar_eye_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_eyelashes.llm b/indra/newview/character/avatar_eyelashes.llm
new file mode 100644
index 0000000000..99995b5758
--- /dev/null
+++ b/indra/newview/character/avatar_eyelashes.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair.llm b/indra/newview/character/avatar_hair.llm
new file mode 100644
index 0000000000..df99de8db7
--- /dev/null
+++ b/indra/newview/character/avatar_hair.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_1.llm b/indra/newview/character/avatar_hair_1.llm
new file mode 100644
index 0000000000..6de31fdc23
--- /dev/null
+++ b/indra/newview/character/avatar_hair_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_2.llm b/indra/newview/character/avatar_hair_2.llm
new file mode 100644
index 0000000000..47d02ba9ce
--- /dev/null
+++ b/indra/newview/character/avatar_hair_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_3.llm b/indra/newview/character/avatar_hair_3.llm
new file mode 100644
index 0000000000..107f9e2a53
--- /dev/null
+++ b/indra/newview/character/avatar_hair_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_4.llm b/indra/newview/character/avatar_hair_4.llm
new file mode 100644
index 0000000000..1b9a12a0ca
--- /dev/null
+++ b/indra/newview/character/avatar_hair_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_5.llm b/indra/newview/character/avatar_hair_5.llm
new file mode 100644
index 0000000000..1b9a12a0ca
--- /dev/null
+++ b/indra/newview/character/avatar_hair_5.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head.llm b/indra/newview/character/avatar_head.llm
new file mode 100644
index 0000000000..8d8b5e0442
--- /dev/null
+++ b/indra/newview/character/avatar_head.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_1.llm b/indra/newview/character/avatar_head_1.llm
new file mode 100644
index 0000000000..26291e6584
--- /dev/null
+++ b/indra/newview/character/avatar_head_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_2.llm b/indra/newview/character/avatar_head_2.llm
new file mode 100644
index 0000000000..c2b808b1a6
--- /dev/null
+++ b/indra/newview/character/avatar_head_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_3.llm b/indra/newview/character/avatar_head_3.llm
new file mode 100644
index 0000000000..a0676b1f1c
--- /dev/null
+++ b/indra/newview/character/avatar_head_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_4.llm b/indra/newview/character/avatar_head_4.llm
new file mode 100644
index 0000000000..5035585770
--- /dev/null
+++ b/indra/newview/character/avatar_head_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body.llm b/indra/newview/character/avatar_lower_body.llm
new file mode 100644
index 0000000000..0420899739
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_1.llm b/indra/newview/character/avatar_lower_body_1.llm
new file mode 100644
index 0000000000..1394eb848b
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_2.llm b/indra/newview/character/avatar_lower_body_2.llm
new file mode 100644
index 0000000000..0da9c1249e
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_3.llm b/indra/newview/character/avatar_lower_body_3.llm
new file mode 100644
index 0000000000..f3c49a1568
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_4.llm b/indra/newview/character/avatar_lower_body_4.llm
new file mode 100644
index 0000000000..e71721063e
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt.llm b/indra/newview/character/avatar_skirt.llm
new file mode 100644
index 0000000000..08ce3d1700
--- /dev/null
+++ b/indra/newview/character/avatar_skirt.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_1.llm b/indra/newview/character/avatar_skirt_1.llm
new file mode 100644
index 0000000000..88076c321f
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_2.llm b/indra/newview/character/avatar_skirt_2.llm
new file mode 100644
index 0000000000..73b3effbc6
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_3.llm b/indra/newview/character/avatar_skirt_3.llm
new file mode 100644
index 0000000000..ded546fdea
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_4.llm b/indra/newview/character/avatar_skirt_4.llm
new file mode 100644
index 0000000000..b9d5cb945e
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body.llm b/indra/newview/character/avatar_upper_body.llm
new file mode 100644
index 0000000000..da7d990540
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_1.llm b/indra/newview/character/avatar_upper_body_1.llm
new file mode 100644
index 0000000000..31e104cc20
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_2.llm b/indra/newview/character/avatar_upper_body_2.llm
new file mode 100644
index 0000000000..c1f4199b9c
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_3.llm b/indra/newview/character/avatar_upper_body_3.llm
new file mode 100644
index 0000000000..9e89ed8b3e
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_4.llm b/indra/newview/character/avatar_upper_body_4.llm
new file mode 100644
index 0000000000..ec836d1dc3
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_4.llm
Binary files differ
diff --git a/indra/newview/character/blush_alpha.tga b/indra/newview/character/blush_alpha.tga
new file mode 100644
index 0000000000..05be7e7e3d
--- /dev/null
+++ b/indra/newview/character/blush_alpha.tga
Binary files differ
diff --git a/indra/newview/character/body_skingrain.tga b/indra/newview/character/body_skingrain.tga
new file mode 100644
index 0000000000..7264baac14
--- /dev/null
+++ b/indra/newview/character/body_skingrain.tga
Binary files differ
diff --git a/indra/newview/character/bodyfreckles_alpha.tga b/indra/newview/character/bodyfreckles_alpha.tga
new file mode 100644
index 0000000000..d30ab3d122
--- /dev/null
+++ b/indra/newview/character/bodyfreckles_alpha.tga
Binary files differ
diff --git a/indra/newview/character/bump_face_wrinkles.tga b/indra/newview/character/bump_face_wrinkles.tga
new file mode 100644
index 0000000000..54bf7a55be
--- /dev/null
+++ b/indra/newview/character/bump_face_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_head_base.tga b/indra/newview/character/bump_head_base.tga
new file mode 100644
index 0000000000..fa3568573a
--- /dev/null
+++ b/indra/newview/character/bump_head_base.tga
Binary files differ
diff --git a/indra/newview/character/bump_lowerbody_base.tga b/indra/newview/character/bump_lowerbody_base.tga
new file mode 100644
index 0000000000..498ea3c721
--- /dev/null
+++ b/indra/newview/character/bump_lowerbody_base.tga
Binary files differ
diff --git a/indra/newview/character/bump_pants_wrinkles.tga b/indra/newview/character/bump_pants_wrinkles.tga
new file mode 100644
index 0000000000..cca72415e8
--- /dev/null
+++ b/indra/newview/character/bump_pants_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_shirt_wrinkles.tga b/indra/newview/character/bump_shirt_wrinkles.tga
new file mode 100644
index 0000000000..9e0d757a48
--- /dev/null
+++ b/indra/newview/character/bump_shirt_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_upperbody_base.tga b/indra/newview/character/bump_upperbody_base.tga
new file mode 100644
index 0000000000..e57d6352e6
--- /dev/null
+++ b/indra/newview/character/bump_upperbody_base.tga
Binary files differ
diff --git a/indra/newview/character/eyebrows_alpha.tga b/indra/newview/character/eyebrows_alpha.tga
new file mode 100644
index 0000000000..c363e482e1
--- /dev/null
+++ b/indra/newview/character/eyebrows_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeliner_alpha.tga b/indra/newview/character/eyeliner_alpha.tga
new file mode 100644
index 0000000000..1611eb3355
--- /dev/null
+++ b/indra/newview/character/eyeliner_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeshadow_inner_alpha.tga b/indra/newview/character/eyeshadow_inner_alpha.tga
new file mode 100644
index 0000000000..37d7919395
--- /dev/null
+++ b/indra/newview/character/eyeshadow_inner_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeshadow_outer_alpha.tga b/indra/newview/character/eyeshadow_outer_alpha.tga
new file mode 100644
index 0000000000..00eef9d9f7
--- /dev/null
+++ b/indra/newview/character/eyeshadow_outer_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyewhite.tga b/indra/newview/character/eyewhite.tga
new file mode 100644
index 0000000000..a720496988
--- /dev/null
+++ b/indra/newview/character/eyewhite.tga
Binary files differ
diff --git a/indra/newview/character/facehair_chincurtains_alpha.tga b/indra/newview/character/facehair_chincurtains_alpha.tga
new file mode 100644
index 0000000000..b10397063c
--- /dev/null
+++ b/indra/newview/character/facehair_chincurtains_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_moustache_alpha.tga b/indra/newview/character/facehair_moustache_alpha.tga
new file mode 100644
index 0000000000..4068c4f2b1
--- /dev/null
+++ b/indra/newview/character/facehair_moustache_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_sideburns_alpha.tga b/indra/newview/character/facehair_sideburns_alpha.tga
new file mode 100644
index 0000000000..acddc2d9bd
--- /dev/null
+++ b/indra/newview/character/facehair_sideburns_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_soulpatch_alpha.tga b/indra/newview/character/facehair_soulpatch_alpha.tga
new file mode 100644
index 0000000000..687091a29f
--- /dev/null
+++ b/indra/newview/character/facehair_soulpatch_alpha.tga
Binary files differ
diff --git a/indra/newview/character/freckles_alpha.tga b/indra/newview/character/freckles_alpha.tga
new file mode 100644
index 0000000000..a9a4ec0735
--- /dev/null
+++ b/indra/newview/character/freckles_alpha.tga
Binary files differ
diff --git a/indra/newview/character/glove_length_alpha.tga b/indra/newview/character/glove_length_alpha.tga
new file mode 100644
index 0000000000..db89ad57e7
--- /dev/null
+++ b/indra/newview/character/glove_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/gloves_fingers_alpha.tga b/indra/newview/character/gloves_fingers_alpha.tga
new file mode 100644
index 0000000000..dba2eec277
--- /dev/null
+++ b/indra/newview/character/gloves_fingers_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_alpha.tga b/indra/newview/character/head_alpha.tga
new file mode 100644
index 0000000000..8164525353
--- /dev/null
+++ b/indra/newview/character/head_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_color.tga b/indra/newview/character/head_color.tga
new file mode 100644
index 0000000000..74b1b3078b
--- /dev/null
+++ b/indra/newview/character/head_color.tga
Binary files differ
diff --git a/indra/newview/character/head_hair.tga b/indra/newview/character/head_hair.tga
new file mode 100644
index 0000000000..5321f35204
--- /dev/null
+++ b/indra/newview/character/head_hair.tga
Binary files differ
diff --git a/indra/newview/character/head_highlights_alpha.tga b/indra/newview/character/head_highlights_alpha.tga
new file mode 100644
index 0000000000..8dc5239f97
--- /dev/null
+++ b/indra/newview/character/head_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_shading_alpha.tga b/indra/newview/character/head_shading_alpha.tga
new file mode 100644
index 0000000000..e8ea490109
--- /dev/null
+++ b/indra/newview/character/head_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_skingrain.tga b/indra/newview/character/head_skingrain.tga
new file mode 100644
index 0000000000..b42dee0809
--- /dev/null
+++ b/indra/newview/character/head_skingrain.tga
Binary files differ
diff --git a/indra/newview/character/jacket_length_lower_alpha.tga b/indra/newview/character/jacket_length_lower_alpha.tga
new file mode 100644
index 0000000000..722bc192a8
--- /dev/null
+++ b/indra/newview/character/jacket_length_lower_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_length_upper_alpha.tga b/indra/newview/character/jacket_length_upper_alpha.tga
new file mode 100644
index 0000000000..e9db7e7b1f
--- /dev/null
+++ b/indra/newview/character/jacket_length_upper_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_open_lower_alpha.tga b/indra/newview/character/jacket_open_lower_alpha.tga
new file mode 100644
index 0000000000..db0c2fb0e3
--- /dev/null
+++ b/indra/newview/character/jacket_open_lower_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_open_upper_alpha.tga b/indra/newview/character/jacket_open_upper_alpha.tga
new file mode 100644
index 0000000000..71b8a0b805
--- /dev/null
+++ b/indra/newview/character/jacket_open_upper_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lipgloss_alpha.tga b/indra/newview/character/lipgloss_alpha.tga
new file mode 100644
index 0000000000..78ceecaf85
--- /dev/null
+++ b/indra/newview/character/lipgloss_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lips_mask.tga b/indra/newview/character/lips_mask.tga
new file mode 100644
index 0000000000..ae1401c006
--- /dev/null
+++ b/indra/newview/character/lips_mask.tga
Binary files differ
diff --git a/indra/newview/character/lipstick_alpha.tga b/indra/newview/character/lipstick_alpha.tga
new file mode 100644
index 0000000000..2795f1bd40
--- /dev/null
+++ b/indra/newview/character/lipstick_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_color.tga b/indra/newview/character/lowerbody_color.tga
new file mode 100644
index 0000000000..a63aa12fca
--- /dev/null
+++ b/indra/newview/character/lowerbody_color.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_highlights_alpha.tga b/indra/newview/character/lowerbody_highlights_alpha.tga
new file mode 100644
index 0000000000..ae3413ac8b
--- /dev/null
+++ b/indra/newview/character/lowerbody_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_shading_alpha.tga b/indra/newview/character/lowerbody_shading_alpha.tga
new file mode 100644
index 0000000000..0242663a7d
--- /dev/null
+++ b/indra/newview/character/lowerbody_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/nailpolish_alpha.tga b/indra/newview/character/nailpolish_alpha.tga
new file mode 100644
index 0000000000..91af762902
--- /dev/null
+++ b/indra/newview/character/nailpolish_alpha.tga
Binary files differ
diff --git a/indra/newview/character/pants_length_alpha.tga b/indra/newview/character/pants_length_alpha.tga
new file mode 100644
index 0000000000..3c4f21c0f2
--- /dev/null
+++ b/indra/newview/character/pants_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/pants_waist_alpha.tga b/indra/newview/character/pants_waist_alpha.tga
new file mode 100644
index 0000000000..35658c0896
--- /dev/null
+++ b/indra/newview/character/pants_waist_alpha.tga
Binary files differ
diff --git a/indra/newview/character/rosyface_alpha.tga b/indra/newview/character/rosyface_alpha.tga
new file mode 100644
index 0000000000..a0c8513da2
--- /dev/null
+++ b/indra/newview/character/rosyface_alpha.tga
Binary files differ
diff --git a/indra/newview/character/rouge_alpha.tga b/indra/newview/character/rouge_alpha.tga
new file mode 100644
index 0000000000..a0c8513da2
--- /dev/null
+++ b/indra/newview/character/rouge_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_bottom_alpha.tga b/indra/newview/character/shirt_bottom_alpha.tga
new file mode 100644
index 0000000000..7cce03dbe0
--- /dev/null
+++ b/indra/newview/character/shirt_bottom_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_collar_alpha.tga b/indra/newview/character/shirt_collar_alpha.tga
new file mode 100644
index 0000000000..f55f635473
--- /dev/null
+++ b/indra/newview/character/shirt_collar_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_collar_back_alpha.tga b/indra/newview/character/shirt_collar_back_alpha.tga
new file mode 100644
index 0000000000..43a6453107
--- /dev/null
+++ b/indra/newview/character/shirt_collar_back_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_sleeve_alpha.tga b/indra/newview/character/shirt_sleeve_alpha.tga
new file mode 100644
index 0000000000..e3b18f4fc6
--- /dev/null
+++ b/indra/newview/character/shirt_sleeve_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shoe_height_alpha.tga b/indra/newview/character/shoe_height_alpha.tga
new file mode 100644
index 0000000000..d08dd750f3
--- /dev/null
+++ b/indra/newview/character/shoe_height_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_length_alpha.tga b/indra/newview/character/skirt_length_alpha.tga
new file mode 100644
index 0000000000..c86799469d
--- /dev/null
+++ b/indra/newview/character/skirt_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_back_alpha.tga b/indra/newview/character/skirt_slit_back_alpha.tga
new file mode 100644
index 0000000000..0e49688b14
--- /dev/null
+++ b/indra/newview/character/skirt_slit_back_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_front_alpha.tga b/indra/newview/character/skirt_slit_front_alpha.tga
new file mode 100644
index 0000000000..888bbf71a1
--- /dev/null
+++ b/indra/newview/character/skirt_slit_front_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_left_alpha.tga b/indra/newview/character/skirt_slit_left_alpha.tga
new file mode 100644
index 0000000000..210feac1ea
--- /dev/null
+++ b/indra/newview/character/skirt_slit_left_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_right_alpha.tga b/indra/newview/character/skirt_slit_right_alpha.tga
new file mode 100644
index 0000000000..ce11c64bf6
--- /dev/null
+++ b/indra/newview/character/skirt_slit_right_alpha.tga
Binary files differ
diff --git a/indra/newview/character/underpants_trial_female.tga b/indra/newview/character/underpants_trial_female.tga
new file mode 100644
index 0000000000..96bf732351
--- /dev/null
+++ b/indra/newview/character/underpants_trial_female.tga
Binary files differ
diff --git a/indra/newview/character/underpants_trial_male.tga b/indra/newview/character/underpants_trial_male.tga
new file mode 100644
index 0000000000..095695ca1c
--- /dev/null
+++ b/indra/newview/character/underpants_trial_male.tga
Binary files differ
diff --git a/indra/newview/character/undershirt_trial_female.tga b/indra/newview/character/undershirt_trial_female.tga
new file mode 100644
index 0000000000..e17a309531
--- /dev/null
+++ b/indra/newview/character/undershirt_trial_female.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_color.tga b/indra/newview/character/upperbody_color.tga
new file mode 100644
index 0000000000..85fcc41142
--- /dev/null
+++ b/indra/newview/character/upperbody_color.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_highlights_alpha.tga b/indra/newview/character/upperbody_highlights_alpha.tga
new file mode 100644
index 0000000000..2d8102b583
--- /dev/null
+++ b/indra/newview/character/upperbody_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_shading_alpha.tga b/indra/newview/character/upperbody_shading_alpha.tga
new file mode 100644
index 0000000000..b420506b3e
--- /dev/null
+++ b/indra/newview/character/upperbody_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/upperbodyfreckles_alpha.tga b/indra/newview/character/upperbodyfreckles_alpha.tga
new file mode 100644
index 0000000000..76c7ce8849
--- /dev/null
+++ b/indra/newview/character/upperbodyfreckles_alpha.tga
Binary files differ
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/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 c6b04cbcc8..9486698c89 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/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 2f3171a868..9a8647aba4 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1985,63 +1985,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.
@@ -2216,85 +2209,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 91a1906fab..e7f9db9221 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -329,10 +329,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 665ce9f59c..d81cbb3e5d 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..ab5d8601d0 100644
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -1,440 +1,457 @@
-/**
- * @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 ),
+ 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();
+
+ 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->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;
+
+ // 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::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();
+ 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..5eb42ffaf4 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;
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/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 4ee0986046..01d45d0d49 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 1ec72df53c..0dcd164d83 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"
@@ -86,7 +92,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 77ead951cc..de2c30f1a1 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 631f128ffa..b219081cb8 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 &lt;rse@gnu.org&gt;
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_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 7829a4fa93..b898fd7c93 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"
+ top_pad="6"
label="Select Texture"
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 c4597cbe4c..cbc94e5e74 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 d4b6dd04e0..7c5925550a 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..c725334fc0 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
@@ -234,7 +234,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 +246,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/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(&notifications);
+ }
+
+ 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..231a8e21a5 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)s '%(link)s'" %
+ {'target': target_lib,
+ 'link' : os.path.join(mac_crash_logger_res_path, libfile)}
+ )
+ self.run_command("ln -sf %(target)s '%(link)s'" %
+ {'target': target_lib,
+ 'link' : os.path.join(mac_updater_res_path, libfile)}
+ )
+
# plugin launcher
self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin")
@@ -667,15 +773,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")