summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgignore2
-rwxr-xr-x.hgtags3
-rwxr-xr-xBuildParams5
-rw-r--r--README.md2
-rw-r--r--[-rwxr-xr-x]autobuild.xml1712
-rwxr-xr-xbuild.sh5
-rwxr-xr-xdoc/contributions.txt12
-rw-r--r--indra/cmake/00-Common.cmake54
-rw-r--r--indra/cmake/BuildPackagesInfo.cmake2
-rw-r--r--indra/cmake/CMakeLists.txt7
-rw-r--r--indra/cmake/ConfigurePkgConfig.cmake6
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake46
-rw-r--r--indra/cmake/GLEXT.cmake2
-rw-r--r--indra/cmake/GLH.cmake2
-rw-r--r--indra/cmake/Glui.cmake28
-rw-r--r--indra/cmake/Glut.cmake19
-rw-r--r--indra/cmake/GooglePerfTools.cmake61
-rw-r--r--indra/cmake/LLCommon.cmake3
-rw-r--r--indra/cmake/LLWindow.cmake2
-rw-r--r--indra/cmake/LibVLCPlugin.cmake27
-rw-r--r--indra/cmake/QuickTimePlugin.cmake48
-rw-r--r--indra/cmake/UI.cmake4
-rw-r--r--indra/cmake/Variables.cmake72
-rw-r--r--indra/edit-me-to-trigger-new-build.txt1
-rwxr-xr-xindra/lib/python/indra/base/__init__.py27
-rwxr-xr-xindra/lib/python/indra/base/cllsd_test.py73
-rwxr-xr-xindra/lib/python/indra/base/config.py266
-rwxr-xr-xindra/lib/python/indra/base/llsd.py1052
-rwxr-xr-xindra/lib/python/indra/base/lluuid.py319
-rwxr-xr-xindra/lib/python/indra/base/metrics.py121
-rwxr-xr-xindra/lib/python/indra/ipc/httputil.py30
-rwxr-xr-xindra/lib/python/indra/ipc/llsdhttp.py100
-rwxr-xr-xindra/lib/python/indra/ipc/mysql_pool.py81
-rwxr-xr-xindra/lib/python/indra/ipc/russ.py165
-rwxr-xr-xindra/lib/python/indra/ipc/servicebuilder.py134
-rwxr-xr-xindra/lib/python/indra/ipc/siesta.py468
-rwxr-xr-xindra/lib/python/indra/ipc/siesta_test.py235
-rwxr-xr-xindra/lib/python/indra/ipc/webdav.py597
-rwxr-xr-xindra/lib/python/indra/ipc/xml_rpc.py273
-rwxr-xr-xindra/lib/python/indra/util/fastest_elementtree.py64
-rwxr-xr-xindra/lib/python/indra/util/helpformatter.py52
-rwxr-xr-xindra/lib/python/indra/util/iterators.py63
-rwxr-xr-xindra/lib/python/indra/util/iterators_test.py72
-rwxr-xr-xindra/lib/python/indra/util/llperformance.py182
-rwxr-xr-xindra/lib/python/indra/util/llsubprocess.py117
-rwxr-xr-xindra/lib/python/indra/util/named_query.py592
-rwxr-xr-xindra/lib/python/indra/util/shutil2.py84
-rwxr-xr-xindra/lib/python/indra/util/simperf_host_xml_parser.py338
-rwxr-xr-xindra/lib/python/indra/util/simperf_oprof_interface.py167
-rwxr-xr-xindra/lib/python/indra/util/simperf_proc_interface.py191
-rwxr-xr-xindra/lib/python/indra/util/term.py222
-rwxr-xr-xindra/lib/python/uuid.py508
-rw-r--r--indra/linux_crash_logger/linux_crash_logger.cpp2
-rw-r--r--indra/linux_crash_logger/llcrashloggerlinux.cpp2
-rw-r--r--indra/linux_crash_logger/llcrashloggerlinux.h2
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp2
-rw-r--r--indra/llcommon/CMakeLists.txt20
-rw-r--r--indra/llcommon/llallocator.cpp43
-rw-r--r--indra/llcommon/llapp.h8
-rw-r--r--indra/llcommon/llapr.cpp2
-rw-r--r--indra/llcommon/llcoros.cpp33
-rw-r--r--indra/llcommon/lldependencies.cpp3
-rw-r--r--indra/llcommon/lldependencies.h12
-rw-r--r--indra/llcommon/llerror.cpp13
-rw-r--r--indra/llcommon/llerror.h87
-rw-r--r--indra/llcommon/lleventcoro.cpp3
-rw-r--r--indra/llcommon/lleventcoro.h6
-rw-r--r--indra/llcommon/llevents.cpp270
-rw-r--r--indra/llcommon/llevents.h54
-rw-r--r--indra/llcommon/llexception.cpp55
-rw-r--r--indra/llcommon/llexception.h85
-rw-r--r--indra/llcommon/llfasttimer.h49
-rw-r--r--indra/llcommon/llfile.h2
-rw-r--r--indra/llcommon/llhandle.h81
-rw-r--r--indra/llcommon/llleap.cpp5
-rw-r--r--indra/llcommon/llleap.h6
-rw-r--r--indra/llcommon/llmake.h10
-rw-r--r--indra/llcommon/llmemory.cpp24
-rw-r--r--indra/llcommon/llmemory.h22
-rw-r--r--indra/llcommon/llpreprocessor.h6
-rw-r--r--indra/llcommon/llprocess.cpp21
-rw-r--r--indra/llcommon/llprocess.h6
-rw-r--r--indra/llcommon/llprocessor.cpp2
-rw-r--r--indra/llcommon/llthread.cpp2
-rw-r--r--indra/llcommon/llthreadsafequeue.cpp13
-rw-r--r--indra/llcommon/llthreadsafequeue.h7
-rw-r--r--indra/llcommon/lluriparser.cpp4
-rw-r--r--indra/llcommon/lluriparser.h2
-rw-r--r--indra/llcommon/lluuid.cpp2
-rw-r--r--indra/llcommon/tests/llerror_test.cpp21
-rw-r--r--indra/llcommon/tests/llexception_test.cpp308
-rw-r--r--indra/llcommon/tests/llleap_test.cpp5
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp5
-rw-r--r--indra/llcommon/tests/wrapllerrs.h8
-rw-r--r--indra/llcorehttp/CMakeLists.txt2
-rwxr-xr-xindra/llcorehttp/tests/test_llcorehttp_peer.py11
-rwxr-xr-xindra/llcorehttp/tests/testrunner.py265
-rw-r--r--indra/llcrashlogger/llcrashlogger.h2
-rw-r--r--indra/llimage/llimage.cpp156
-rw-r--r--indra/llimage/llimage.h3
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp2
-rw-r--r--indra/llimage/llpngwrapper.cpp29
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp4
-rw-r--r--indra/llkdu/CMakeLists.txt8
-rw-r--r--indra/llkdu/include_kdu_xxxx.h40
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp193
-rw-r--r--indra/llkdu/llimagej2ckdu.h21
-rw-r--r--indra/llkdu/llkdumem.cpp3
-rw-r--r--indra/llkdu/llkdumem.h36
-rw-r--r--indra/llkdu/tests/llimagej2ckdu_test.cpp27
-rw-r--r--indra/llmath/llmath.h4
-rw-r--r--indra/llmath/llsimdmath.h2
-rw-r--r--indra/llmath/llvolume.cpp27
-rw-r--r--indra/llmath/v4coloru.h32
-rw-r--r--indra/llmessage/llavatarnamecache.cpp11
-rw-r--r--indra/llmessage/llcoproceduremanager.cpp14
-rw-r--r--indra/llmessage/llcorehttputil.cpp2
-rw-r--r--indra/llmessage/llhttpnode.cpp12
-rw-r--r--indra/llmessage/llxfer.cpp2
-rw-r--r--indra/llmessage/llxfermanager.cpp40
-rw-r--r--indra/llmessage/llxfermanager.h3
-rw-r--r--indra/llmessage/message.cpp2
-rw-r--r--indra/llmessage/tests/commtest.h8
-rw-r--r--indra/llmessage/tests/networkio.h5
-rwxr-xr-xindra/llmessage/tests/test_llsdmessage_peer.py6
-rwxr-xr-xindra/llmessage/tests/testrunner.py5
-rw-r--r--indra/llplugin/CMakeLists.txt6
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp5
-rw-r--r--indra/llplugin/llpluginclassmedia.h8
-rw-r--r--indra/llprimitive/lldaeloader.cpp2
-rw-r--r--indra/llrender/llfontgl.cpp7
-rw-r--r--indra/llrender/llglslshader.cpp4
-rw-r--r--indra/llrender/llimagegl.cpp19
-rw-r--r--indra/llrender/llimagegl.h2
-rw-r--r--indra/llrender/llrender.cpp3
-rw-r--r--indra/llrender/llshadermgr.cpp2
-rw-r--r--indra/llui/llclipboard.cpp10
-rw-r--r--indra/llui/llfloater.cpp3
-rw-r--r--indra/llui/llfocusmgr.cpp1
-rw-r--r--indra/llui/llfolderview.cpp7
-rw-r--r--indra/llui/llfolderviewitem.cpp23
-rw-r--r--indra/llui/llfolderviewitem.h8
-rw-r--r--indra/llui/llfolderviewmodel.h1
-rw-r--r--indra/llui/lllineeditor.cpp15
-rw-r--r--indra/llui/lllineeditor.h4
-rw-r--r--indra/llui/lltextbase.cpp76
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/lltextvalidate.cpp9
-rw-r--r--indra/llui/lltextvalidate.h1
-rw-r--r--indra/llui/llui.cpp2
-rw-r--r--indra/llui/llurlentry.cpp17
-rw-r--r--indra/llui/llview.cpp24
-rw-r--r--indra/llvfs/lldir.cpp7
-rw-r--r--indra/llwindow/llappdelegate-objc.h2
-rw-r--r--indra/llwindow/lldragdropwin32.cpp8
-rw-r--r--indra/llwindow/llwindow.h2
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp5
-rw-r--r--indra/llwindow/llwindowcallbacks.h1
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp150
-rw-r--r--indra/llwindow/llwindowwin32.h4
-rw-r--r--indra/mac_crash_logger/llcrashloggermac.cpp2
-rw-r--r--indra/mac_crash_logger/llcrashloggermac.h2
-rw-r--r--indra/mac_crash_logger/mac_crash_logger.cpp2
-rw-r--r--indra/media_plugins/CMakeLists.txt10
-rw-r--r--indra/media_plugins/base/CMakeLists.txt6
-rw-r--r--indra/media_plugins/cef/CMakeLists.txt6
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp67
-rw-r--r--indra/media_plugins/example/CMakeLists.txt6
-rw-r--r--indra/media_plugins/gstreamer010/CMakeLists.txt6
-rw-r--r--indra/media_plugins/libvlc/CMakeLists.txt86
-rw-r--r--indra/media_plugins/libvlc/media_plugin_libvlc.cpp618
-rw-r--r--indra/media_plugins/quicktime/CMakeLists.txt90
-rw-r--r--indra/media_plugins/quicktime/media_plugin_quicktime.cpp1084
-rw-r--r--indra/media_plugins/winmmshim/forwarding_api.cpp2
-rw-r--r--indra/newview/CMakeLists.txt25
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/settings.xml183
-rw-r--r--indra/newview/llaccountingcostmanager.cpp10
-rw-r--r--indra/newview/llagent.cpp24
-rw-r--r--indra/newview/llagent.h2
-rw-r--r--indra/newview/llagentwearables.cpp68
-rw-r--r--indra/newview/llagentwearables.h2
-rw-r--r--indra/newview/llappcorehttp.cpp7
-rw-r--r--indra/newview/llappdelegate-objc.mm24
-rw-r--r--indra/newview/llappearancemgr.cpp75
-rw-r--r--indra/newview/llappearancemgr.h12
-rw-r--r--indra/newview/llappviewer.cpp542
-rw-r--r--indra/newview/llappviewer.h6
-rw-r--r--indra/newview/llappviewerlinux.cpp6
-rw-r--r--indra/newview/llappviewermacosx.cpp9
-rw-r--r--indra/newview/llappviewerwin32.cpp56
-rw-r--r--indra/newview/llavataractions.cpp11
-rw-r--r--indra/newview/llavatarrendernotifier.cpp223
-rw-r--r--indra/newview/llavatarrendernotifier.h62
-rw-r--r--indra/newview/llchatbar.cpp5
-rw-r--r--indra/newview/llcommandlineparser.cpp24
-rw-r--r--indra/newview/llcompilequeue.cpp323
-rw-r--r--indra/newview/llconversationlog.cpp7
-rw-r--r--indra/newview/llface.cpp4
-rw-r--r--indra/newview/llfloaterabout.cpp74
-rw-r--r--indra/newview/llfloateravatarpicker.cpp7
-rw-r--r--indra/newview/llfloaterbuycurrency.cpp2
-rw-r--r--indra/newview/llfloaterfacebook.cpp1072
-rw-r--r--indra/newview/llfloaterflickr.cpp4
-rw-r--r--indra/newview/llfloatergesture.cpp3
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp48
-rw-r--r--indra/newview/llfloateroutfitsnapshot.cpp377
-rw-r--r--indra/newview/llfloateroutfitsnapshot.h123
-rw-r--r--indra/newview/llfloaterpay.cpp141
-rw-r--r--indra/newview/llfloaterpreference.cpp10
-rw-r--r--indra/newview/llfloaterreporter.cpp30
-rw-r--r--indra/newview/llfloaterscriptlimits.cpp10
-rw-r--r--indra/newview/llfloaterscriptlimits.h1
-rw-r--r--indra/newview/llfloatersellland.cpp3
-rw-r--r--indra/newview/llfloatersnapshot.cpp740
-rw-r--r--indra/newview/llfloatersnapshot.h182
-rw-r--r--indra/newview/llfloatertwitter.cpp4
-rw-r--r--indra/newview/llfloaterwebcontent.cpp45
-rw-r--r--indra/newview/llfloaterwebcontent.h5
-rw-r--r--indra/newview/llgroupiconctrl.cpp20
-rw-r--r--indra/newview/llgroupiconctrl.h8
-rw-r--r--indra/newview/llgrouplist.cpp5
-rw-r--r--indra/newview/llhudtext.cpp17
-rw-r--r--indra/newview/llinspectgroup.cpp3
-rw-r--r--indra/newview/llinventorybridge.cpp50
-rw-r--r--indra/newview/llinventorybridge.h1
-rw-r--r--indra/newview/llinventoryfilter.cpp17
-rw-r--r--indra/newview/llinventorymodel.cpp23
-rw-r--r--indra/newview/lllocalbitmaps.cpp5
-rw-r--r--indra/newview/lllocationinputctrl.cpp2
-rw-r--r--indra/newview/lllogchat.cpp5
-rw-r--r--indra/newview/llmanip.h4
-rw-r--r--indra/newview/llmaniptranslate.cpp7
-rw-r--r--indra/newview/llmarketplacefunctions.cpp4
-rw-r--r--indra/newview/llmediactrl.cpp6
-rw-r--r--indra/newview/llmeshrepository.cpp37
-rw-r--r--indra/newview/llmoveview.cpp12
-rw-r--r--indra/newview/llmoveview.h2
-rw-r--r--indra/newview/llnetmap.cpp6
-rw-r--r--indra/newview/llnotificationofferhandler.cpp26
-rw-r--r--indra/newview/lloutfitgallery.cpp1288
-rw-r--r--indra/newview/lloutfitgallery.h284
-rw-r--r--indra/newview/lloutfitslist.cpp1206
-rw-r--r--indra/newview/lloutfitslist.h214
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp2
-rw-r--r--indra/newview/llpanelmaininventory.cpp39
-rw-r--r--indra/newview/llpanelmaininventory.h2
-rw-r--r--indra/newview/llpaneloutfitedit.cpp3
-rw-r--r--indra/newview/llpaneloutfitedit.h1
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp51
-rw-r--r--indra/newview/llpaneloutfitsinventory.h6
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp46
-rw-r--r--indra/newview/llpanelprimmediacontrols.h8
-rw-r--r--indra/newview/llpanelprofile.cpp14
-rw-r--r--indra/newview/llpanelsnapshot.cpp59
-rw-r--r--indra/newview/llpanelsnapshot.h15
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp107
-rw-r--r--indra/newview/llpanelsnapshotlocal.cpp29
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp5
-rw-r--r--indra/newview/llpanelsnapshotpostcard.cpp36
-rw-r--r--indra/newview/llpanelsnapshotprofile.cpp6
-rw-r--r--indra/newview/llpanelwearing.cpp251
-rw-r--r--indra/newview/llpanelwearing.h33
-rw-r--r--indra/newview/llpathfindinglinksetlist.cpp7
-rw-r--r--indra/newview/llpresetsmanager.cpp3
-rw-r--r--indra/newview/llpreviewnotecard.cpp19
-rw-r--r--indra/newview/llpreviewnotecard.h1
-rw-r--r--indra/newview/llpreviewscript.cpp18
-rw-r--r--indra/newview/llpreviewscript.h4
-rw-r--r--indra/newview/llsecapi.cpp13
-rw-r--r--indra/newview/llsecapi.h34
-rw-r--r--indra/newview/llsechandler_basic.cpp90
-rw-r--r--indra/newview/llsidepanelappearance.cpp2
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp50
-rw-r--r--indra/newview/llsnapshotlivepreview.h28
-rw-r--r--indra/newview/llsnapshotmodel.h55
-rw-r--r--indra/newview/llstartup.cpp6
-rw-r--r--indra/newview/llsurfacepatch.cpp4
-rw-r--r--indra/newview/lltexturecache.cpp6
-rw-r--r--indra/newview/lltexturectrl.cpp212
-rw-r--r--indra/newview/lltexturectrl.h146
-rw-r--r--indra/newview/lltoolfocus.cpp1
-rw-r--r--indra/newview/lltoolmgr.cpp2
-rw-r--r--indra/newview/llversioninfo.cpp8
-rw-r--r--indra/newview/llviewchildren.cpp5
-rw-r--r--indra/newview/llviewerassetupload.cpp17
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/llviewerinventory.cpp38
-rw-r--r--indra/newview/llviewermedia.cpp9
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermedia_streamingaudio.cpp3
-rw-r--r--indra/newview/llviewermenu.cpp12
-rw-r--r--indra/newview/llviewermenu.h3
-rw-r--r--indra/newview/llviewermenufile.cpp22
-rw-r--r--indra/newview/llviewermessage.cpp11
-rw-r--r--indra/newview/llviewernetwork.cpp30
-rw-r--r--indra/newview/llviewernetwork.h8
-rw-r--r--indra/newview/llviewerobject.cpp79
-rw-r--r--indra/newview/llviewerobject.h17
-rw-r--r--indra/newview/llviewertexture.cpp4
-rw-r--r--indra/newview/llviewerwearable.cpp7
-rw-r--r--indra/newview/llviewerwearable.h2
-rw-r--r--indra/newview/llviewerwindow.cpp75
-rw-r--r--indra/newview/llviewerwindow.h22
-rw-r--r--indra/newview/llviewerwindowlistener.cpp6
-rw-r--r--indra/newview/llvoavatar.cpp90
-rw-r--r--indra/newview/llvosky.cpp2
-rw-r--r--indra/newview/llvosky.h4
-rw-r--r--indra/newview/llvovolume.cpp2
-rw-r--r--indra/newview/llweb.cpp4
-rw-r--r--indra/newview/llweb.h2
-rw-r--r--indra/newview/llworld.cpp8
-rw-r--r--indra/newview/llxmlrpclistener.cpp2
-rw-r--r--indra/newview/skins/default/colors.xml9
-rw-r--r--indra/newview/skins/default/textures/icons/Default_Outfit_Photo.pngbin0 -> 19459 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Video_URL_Off.pngbin0 -> 282 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml9
-rw-r--r--indra/newview/skins/default/textures/windows/first_login_image_left.pngbin311306 -> 384997 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/first_login_image_right.pngbin329170 -> 340188 bytes
-rw-r--r--indra/newview/skins/default/xui/de/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml351
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_web_content.xml130
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml1
-rw-r--r--indra/newview/skins/default/xui/en/inspect_group.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml255
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml42
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml25
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_tab.xml7
-rw-r--r--indra/newview/skins/default/xui/en/mime_types.xml56
-rw-r--r--indra/newview/skins/default/xui/en/mime_types_linux.xml30
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml239
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery.xml135
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml71
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml79
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_wearing.xml41
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml27
-rw-r--r--indra/newview/skins/default/xui/es/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/it/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/panel_status_bar.xml2
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp1
-rw-r--r--indra/newview/tests/llversioninfo_test.cpp11
-rwxr-xr-xindra/newview/viewer_manifest.py61
-rw-r--r--indra/test/CMakeLists.txt1
-rw-r--r--indra/test/llapp_tut.cpp2
-rw-r--r--indra/test_apps/llplugintest/CMakeLists.txt336
-rw-r--r--indra/test_apps/llplugintest/README.Linden21
-rw-r--r--indra/test_apps/llplugintest/bookmarks.txt37
-rw-r--r--indra/viewer_components/login/lllogin.cpp102
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.cpp16
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.cpp12
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp9
-rw-r--r--indra/viewer_components/updater/llupdaterservice.h5
-rw-r--r--indra/win_crash_logger/llcrashloggerwindows.cpp8
-rw-r--r--indra/win_crash_logger/llcrashloggerwindows.h2
-rw-r--r--indra/win_crash_logger/win_crash_logger.cpp2
-rwxr-xr-xscripts/packages-formatter.py12
369 files changed, 12544 insertions, 12866 deletions
diff --git a/.hgignore b/.hgignore
index 1b7a9019a2..0d672e6ebc 100755
--- a/.hgignore
+++ b/.hgignore
@@ -17,6 +17,8 @@ build-darwin-*
build-vc80/
build-vc100/
build-vc120/
+build-vc120-32/
+build-vc120-64/
indra/build-vc[0-9]*
indra/CMakeFiles
indra/lib/mono/1.0/*.dll
diff --git a/.hgtags b/.hgtags
index cee1281f2b..c9870bfb0f 100755
--- a/.hgtags
+++ b/.hgtags
@@ -518,3 +518,6 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
450de775fff66a011be1a001acd117cc623c445d 4.0.5-release
4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release
33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
+45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release
+b280a1c797a3891e68dbc237e73de9cf19f426e9 4.1.1-release
+bfbba2244320dc2ae47758cd7edd8fa3b67dc756 4.1.2-release
diff --git a/BuildParams b/BuildParams
index 264f6f8a53..5adf249269 100755
--- a/BuildParams
+++ b/BuildParams
@@ -34,6 +34,10 @@ Linux.distcc_version =
Linux.gcc_version = /usr/bin/gcc-4.6
Linux.cxx_version = /usr/bin/g++-4.6
+# Need viewer-build-variables as well as other shared repositories
+buildscripts_shared_more_NAMEs="build_variables"
+build_variables_repostory_url = "https://bitbucket.org/lindenlab/viewer-build-variables"
+
################################################################
#### Examples of how to set the viewer_channel ####
#
@@ -90,4 +94,3 @@ EDU_viewer_channel_suffix = "edu"
# environment variable 'email' to a space-separated list of email addresses
-
diff --git a/README.md b/README.md
index ad040fb077..6eddb9aa9e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
Second Life Viewer
====================
-
+
This project manages the source code for the
[Second Life](https://www.secondlife.com) Viewer.
diff --git a/autobuild.xml b/autobuild.xml
index 072dfa678a..251e9b6468 100755..100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -29,6 +29,18 @@
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7ea2df03bfc35c06acf23dd9e734adac</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1103/2554/SDL-1.2.15-linux64-501092.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
</map>
<key>version</key>
<string>1.2.15</string>
@@ -59,33 +71,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ae733dd8f2c83055030ea6e08c623306</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/745/1534/apr_suite-1.4.5.500735-darwin64-500735.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>402552cf158e2fe953b7224f4615a957</string>
+ <string>1aa2e5355bb9df09f9196d14a72b6705</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/apr_3p-update-apr/rev/297252/arch/Linux/installer/apr_suite-1.4.5.297252-linux-297252.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-apr/rev/314241/arch/Linux/installer/apr_suite-1.4.5.314241-linux-314241.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>bc8855c8253b8293c7e61af7b1ed0f05</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/744/1545/apr_suite-1.4.5.500735-linux64-500735.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>8f865b509bb5011caf3dd95a22a4589d</string>
+ <string>7d97a3788ea4f89eccb7789e4f015bb3</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/apr_3p-update-apr/rev/297252/arch/CYGWIN/installer/apr_suite-1.4.5.297252-windows-297252.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/747/1540/apr_suite-1.4.5.500735-windows-500735.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>8820c4df1079a9af53f52485f50ff179</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/746/1537/apr_suite-1.4.5.500735-windows64-500735.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.4.5.297252</string>
+ <string>1.4.5.500735</string>
</map>
<key>boost</key>
<map>
@@ -113,30 +161,66 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>d318c25353e41215f1f523d58cacfd44</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/893/1984/boost-1.57-darwin64-500883.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>fb1537f7ad0b490fcb4f096c15dce9cd</string>
+ <string>f1fdb548fd6c09a083c86f3a23d7f041</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/boost_3p-update-boost/rev/297445/arch/Linux/installer/boost-1.57-linux-297445.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-boost/rev/317807/arch/Linux/installer/boost-1.57-linux-317807.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>8e7ee97c3083f44385b09420655ebd04</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/892/1989/boost-1.57-linux64-500883.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>76a607d8a625062b9a63a88b62819894</string>
+ <string>80b1963d635e883cb5ed223e94406adb</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/boost_3p-update-boost/rev/297445/arch/CYGWIN/installer/boost-1.57-windows-297445.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/894/1976/boost-1.57-windows-500883.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>3d6a6373ed0daa490cdb4f92db45de52</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/895/1979/boost-1.57-windows64-500883.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
<string>1.57</string>
@@ -165,33 +249,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>fa93a9a10fa379091e3e7b85665690d9</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/913/2026/colladadom-2.3.500902-darwin64-500902.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>d627c2a679f3afb8d3e090d42f53cd2e</string>
+ <string>78b9a6506fb7d53da166f7a65f2278f4</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/colladadom_3p-update-colladadom/rev/297450/arch/Linux/installer/colladadom-2.3.297450-linux-297450.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-colladadom/rev/317826/arch/Linux/installer/colladadom-2.3.317826-linux-317826.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>868127582794d6fd32fa69c9be4e83e4</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/912/2031/colladadom-2.3.500902-linux64-500902.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>220897a1893a188aa9d31efb48909878</string>
+ <string>5bd7875e16e7f88e21f4c44fe7c6433f</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/colladadom_3p-update-colladadom/rev/297450/arch/CYGWIN/installer/colladadom-2.3.297450-windows-297450.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/915/2035/colladadom-2.3.500902-windows-500902.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>8a647129a0a0a31594557785ea85f840</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/914/2034/colladadom-2.3.500902-windows64-500902.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>2.3.297450</string>
+ <string>2.3.500902</string>
</map>
<key>curl</key>
<map>
@@ -219,35 +339,71 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>99fbc15f514be77c36280f300d257d5a</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1077/2495/curl-7.47.0.501064-darwin64-501064.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>f49d4ed203b03852a3f6b01b18319f7a</string>
+ <string>9430c08954c00736117099046694e1b1</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-curl/rev/312763/arch/Linux/installer/curl-7.47.0.312763-linux-312763.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-curl/rev/314230/arch/Linux/installer/curl-7.47.0.314230-linux-314230.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>e5d1b0439235f5f3829662a45e566743</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1075/2484/curl-7.47.0.501064-linux64-501064.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>5e0d4f4a5a5bbcba610aafbb91c30b2b</string>
+ <string>bda9f237d3e8238440bc5bedc2657547</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-curl/rev/312763/arch/CYGWIN/installer/curl-7.47.0.312763-windows-312763.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1078/2487/curl-7.47.0.501064-windows-501064.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>f7fa42c7157cd5007283ae7a5d97393d</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1079/2490/curl-7.47.0.501064-windows64-501064.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>7.47.0.312763</string>
+ <string>7.47.0.501064</string>
</map>
<key>db</key>
<map>
@@ -298,13 +454,25 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>c11ff7e2e0bd59e6e59628f24902bbcd</string>
+ <string>6d676abd9ad8d2883b855dbe397d9034</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/dbus-glib_3p-update-dbus-glib/rev/297768/arch/Linux/installer/dbus_glib-0.76-linux-297768.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-dbus-glib/rev/314266/arch/Linux/installer/dbus_glib-0.76-linux-314266.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7ee7b9aed3c0c8c09e7bf26bba7af8e1</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-dbus-glib/rev/314266/arch/Linux/installer/dbus_glib-0.76-linux64-314266.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
</map>
<key>version</key>
<string>0.76</string>
@@ -328,16 +496,16 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>a62723a6deea8187702a2f926e98a35f</string>
+ <string>2fa9e9e89a81ed2ed686a170681f6bbc</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/dictionaries_3p-update-dictionaries/rev/297347/arch/Linux/installer/dictionaries-1.297347-common-297347.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/571/1225/dictionaries-1.500564-common-500564.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
- <string>1.297347</string>
+ <string>1.500564</string>
</map>
<key>elfio</key>
<map>
@@ -389,33 +557,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>fd182ab5bed66c94899dec3035310945</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/384/954/expat-2.1.1.500375-darwin64-500375.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>f546615d76bc0f9e8bc2b9ef89f0ca86</string>
+ <string>387c90b9bb5ec412587fbe7a56261dd1</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/expat_3p-update-expat/rev/297014/arch/Linux/installer/expat-2.0.1.297014-linux-297014.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-expat/rev/314211/arch/Linux/installer/expat-2.1.1.314211-linux-314211.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>5e1f025d1cebd12db542080aa755257f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/380/943/expat-2.1.1.500375-linux64-500375.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>c70c72a8a0a1e508691a9b35739b373f</string>
+ <string>09ece3f04ec0bd21dd0d401235aa20f7</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/expat_3p-update-expat/rev/297014/arch/CYGWIN/installer/expat-2.0.1.297014-windows-297014.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/383/949/expat-2.1.1.500375-windows-500375.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>5c82a3482799fe22b3c8fcb317f87bbb</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/382/946/expat-2.1.1.500375-windows64-500375.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>2.0.1.297014</string>
+ <string>2.1.1.500375</string>
</map>
<key>fmodex</key>
<map>
@@ -441,33 +645,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>5fe125f2341501bc64848645d31b58ef</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/356/893/fmodex-4.44.61.500350-darwin64-500350.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>dd0135d53706a4040d65974f7e804d6f</string>
+ <string>b847ec838da1ad1dd646df9d74e9b395</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/fmodex_3p-update-fmodex/rev/297261/arch/Linux/installer/fmodex-4.44.31.297261-linux-297261.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_3p-fmodex/rev/314207/arch/Linux/installer/fmodex-4.44.61.314207-linux-314207.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>270c3eddbe2960d5edb8d316db063d07</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/355/888/fmodex-4.44.61.500350-linux64-500350.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>5aa7b826e7c1cf95e9cd3ef77e314f35</string>
+ <string>23876d471ef04d28b73a931057758872</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/fmodex_3p-update-fmodex/rev/297261/arch/CYGWIN/installer/fmodex-4.44.31.297261-windows-297261.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/358/899/fmodex-4.44.61.500350-windows-500350.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>f87fd527e1cca5b1b64090c5afb04cdb</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/357/896/fmodex-4.44.61.500350-windows64-500350.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>4.44.31.297261</string>
+ <string>4.44.61.500350</string>
</map>
<key>fontconfig</key>
<map>
@@ -488,46 +728,28 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>864f9361661748ecf0e2cec7110d70b3</string>
+ <string>a20a3d0ab7fc3401bc2ca81e9309f630</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/fontconfig_3p-update-fontconfig/rev/297551/arch/Linux/installer/fontconfig-2.11.0-linux-297551.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-fontconfig/rev/314281/arch/Linux/installer/fontconfig-2.11.0-linux-314281.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
- </map>
- <key>version</key>
- <string>2.11.0</string>
- </map>
- <key>freeglut</key>
- <map>
- <key>copyright</key>
- <string>Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.</string>
- <key>description</key>
- <string>freeglut is a completely OpenSourced alternative to the OpenGL Utility Toolkit (GLUT) library.</string>
- <key>license</key>
- <string>freeglut</string>
- <key>license_file</key>
- <string>LICENSES/freeglut.txt</string>
- <key>name</key>
- <string>freeglut</string>
- <key>platforms</key>
- <map>
- <key>windows</key>
+ <key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>58e328a8b2f3788f932c57ad77e3e117</string>
+ <string>e2419d56960c160670051fbb055fb729</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/freeglut_3p-update-freeglut/rev/295926/arch/CYGWIN/installer/freeglut-2.6.0.295926-windows-295926.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-fontconfig/rev/314281/arch/Linux/installer/fontconfig-2.11.0-linux64-314281.tar.bz2</string>
</map>
<key>name</key>
- <string>windows</string>
+ <string>linux64</string>
</map>
</map>
<key>version</key>
- <string>2.6.0.295926</string>
+ <string>2.11.0</string>
</map>
<key>freetype</key>
<map>
@@ -555,33 +777,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>3f0698d53acf14b3f0a11dba889d67f3</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/875/1919/freetype-2.4.4.500865-darwin64-500865.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>1ac3152b440287c58509d8af0a50326d</string>
+ <string>1b401394106cedc86926bd488f5aa45e</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/freetype_3p-update-freetype/rev/297053/arch/Linux/installer/freetype-2.4.4.297053-linux-297053.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-freetype/rev/314215/arch/Linux/installer/freetype-2.4.4.314215-linux-314215.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>94cf61dfdbc86aae5bbaf0b5cb8a366c</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/874/1914/freetype-2.4.4.500865-linux64-500865.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>207aa1a29bfe4ba63edbca38170970a1</string>
+ <string>b7a8df22cfc910180c66bb1c1ed89cd4</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/freetype_3p-update-freetype/rev/297053/arch/CYGWIN/installer/freetype-2.4.4.297053-windows-297053.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/876/1922/freetype-2.4.4.500865-windows-500865.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ff72a895012ed603935083496b0a7bc9</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/877/1925/freetype-2.4.4.500865-windows64-500865.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>2.4.4.297053</string>
+ <string>2.4.4.500865</string>
</map>
<key>glext</key>
<map>
@@ -602,30 +860,54 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>4bf4f9e65168138eebbc769e9e12230b</string>
+ <string>baf1fd13e1fe6aef586200fc87a70f53</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glext_3p-update-glext/rev/296893/arch/Linux/installer/glext-68-linux-296893.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/Linux/installer/glext-68-linux-314200.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>5f3c9d61b620f949b199ebd8885218ed</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/Linux/installer/glext-68-linux64-314200.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>6eb51c6f17e717a5617b112858d41c80</string>
+ <string>731d4adecfcbd9f7d20c4bbd2c183962</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glext_3p-update-glext/rev/296893/arch/CYGWIN/installer/glext-68-windows-296893.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/CYGWIN/installer/glext-68-windows-314200.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>9635e7e6fded468dfc0874a2ead54123</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/CYGWIN/installer/glext-68-windows64-314200.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
<string>68</string>
</map>
- <key>glh-linear</key>
+ <key>glh_linear</key>
<map>
<key>copyright</key>
<string>Copyright (c) 2000 Cass Everitt</string>
@@ -636,7 +918,7 @@
<key>license_file</key>
<string>LICENSES/glh-linear.txt</string>
<key>name</key>
- <string>glh-linear</string>
+ <string>glh_linear</string>
<key>platforms</key>
<map>
<key>common</key>
@@ -644,9 +926,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>44c596c659d32a86972ac9c6f206cb68</string>
+ <string>fa41756977ad8b9fd2d1465dadd4f956</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glh-linear_3p-glh-linear/rev/303446/arch/Linux/installer/glh_linear-0.0.0-common-303446.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/529/1139/glh_linear-0.0.0-common-500522.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
@@ -681,91 +963,73 @@
<key>name</key>
<string>darwin</string>
</map>
- <key>linux</key>
+ <key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>fffd130f17cbbe2b93cc241b27262647</string>
- <key>hash_algorithm</key>
- <string>md5</string>
+ <string>047ce52d5fe3e9ac70763de0098cf530</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glod_3p-update-glod/rev/296895/arch/Linux/installer/glod-1.0pre4.296895-linux-296895.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/719/1462/glod-1.0pre3.500710-darwin64-500710.tar.bz2</string>
</map>
<key>name</key>
- <string>linux</string>
+ <string>darwin64</string>
</map>
- <key>windows</key>
+ <key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>b0b32155319c6441997c034bdae28a22</string>
+ <string>58113bcbbacbaeb2d278f745867ae6f0</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glod_3p-update-glod/rev/296895/arch/CYGWIN/installer/glod-1.0pre4.296895-windows-296895.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glod/rev/314201/arch/Linux/installer/glod-1.0pre4.314201-linux-314201.tar.bz2</string>
</map>
<key>name</key>
- <string>windows</string>
+ <string>linux</string>
</map>
- </map>
- <key>version</key>
- <string>1.0pre4.296895</string>
- </map>
- <key>glui</key>
- <map>
- <key>copyright</key>
- <string>Copyright 2006 Paul Rademacher</string>
- <key>description</key>
- <string>GLUI is a GLUT-based C++ user interface library which provides controls such as buttons, checkboxes, radio buttons, and spinners to OpenGL applications.</string>
- <key>license</key>
- <string>ZLIB</string>
- <key>license_file</key>
- <string>LICENSES/glui.txt</string>
- <key>name</key>
- <string>glui</string>
- <key>platforms</key>
- <map>
- <key>darwin</key>
+ <key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>9b7e2ab9b208b3001803294f83d2b610</string>
+ <string>8cb665230ec24048aa3b733f2b1c3b00</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glui_3p-update-glui/rev/297273/arch/Darwin/installer/glui-2.36.297273-darwin-297273.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glod/rev/314201/arch/Linux/installer/glod-1.0pre4.314201-linux64-314201.tar.bz2</string>
</map>
<key>name</key>
- <string>darwin</string>
+ <string>linux64</string>
</map>
- <key>linux</key>
+ <key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>f330b3acd03526d827030eefeeb06240</string>
+ <string>511d066e35bbc14dd512c831b53a2fad</string>
+ <key>hash_algorithm</key>
+ <string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glui_3p-update-glui/rev/297273/arch/Linux/installer/glui-2.36.297273-linux-297273.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/720/1465/glod-1.0pre3.500710-windows-500710.tar.bz2</string>
</map>
<key>name</key>
- <string>linux</string>
+ <string>windows</string>
</map>
- <key>windows</key>
+ <key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>75b16a5a606c78aaeb2f8e6046310a58</string>
+ <string>7fa6f187fc5e4175a13d3e0d4b6658a4</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glui_3p-update-glui/rev/297273/arch/CYGWIN/installer/glui-2.36.297273-windows-297273.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/721/1468/glod-1.0pre3.500710-windows64-500710.tar.bz2</string>
</map>
<key>name</key>
- <string>windows</string>
+ <string>windows64</string>
</map>
</map>
<key>version</key>
- <string>2.36.297273</string>
+ <string>1.0pre3.500710</string>
</map>
<key>google_breakpad</key>
<map>
@@ -793,33 +1057,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>0b76c9551ae3ef1ede9a9abee865f55b</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/568/1209/google_breakpad-1413.500560-darwin64-500560.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>0bf69fbc829d964820b798a0494278c9</string>
+ <string>352e673897e8f36f8470150b8ace6ce9</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/google-breakpad_3p-update-google-breakpad/rev/298033/arch/Linux/installer/google_breakpad-1413.298033-linux-298033.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-google-breakpad/rev/314225/arch/Linux/installer/google_breakpad-1413.314225-linux-314225.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>066ce05521a0e1cff2da8aeecfefd7f1</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/567/1217/google_breakpad-1413.500560-linux64-500560.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>c73a7c9aa53a4e266df2d5230a650fbf</string>
+ <string>c6a4497fbf3af4e06f74d529f4f084b0</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/google-breakpad_3p-update-google-breakpad/rev/298127/arch/CYGWIN/installer/google_breakpad-1413.298127-windows-298127.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/570/1220/google_breakpad-1413.500560-windows-500560.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>46409efe7425f637a7757c3a578e7baa</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/569/1212/google_breakpad-1413.500560-windows64-500560.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1413.298127</string>
+ <string>1413.500560</string>
</map>
<key>googlemock</key>
<map>
@@ -847,87 +1147,69 @@
<key>name</key>
<string>darwin</string>
</map>
- <key>linux</key>
+ <key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e08b0e9e269b80b549f6044c4e608fb5</string>
+ <string>1a8081953bdf1bbbc9b8a8e6e062c02d</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/googlemock_3p-update-googlemock/rev/297460/arch/Linux/installer/googlemock-1.7.0.297460-linux-297460.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/919/2048/googlemock-1.7.0.500908-darwin64-500908.tar.bz2</string>
</map>
<key>name</key>
- <string>linux</string>
+ <string>darwin64</string>
</map>
- <key>windows</key>
+ <key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>f30de5bf36e8ca8681883fe8fd8e0092</string>
+ <string>ad51f68702f25ba245fff312c50c8876</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/googlemock_3p-update-googlemock/rev/297460/arch/CYGWIN/installer/googlemock-1.7.0.297460-windows-297460.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-googlemock/rev/317828/arch/Linux/installer/googlemock-1.7.0.317828-linux-317828.tar.bz2</string>
</map>
<key>name</key>
- <string>windows</string>
+ <string>linux</string>
</map>
- </map>
- <key>version</key>
- <string>1.7.0.297460</string>
- </map>
- <key>gperftools</key>
- <map>
- <key>copyright</key>
- <string>Copyright (c) 2005, Google Inc.</string>
- <key>description</key>
- <string>Fast, multi-threaded malloc() and nifty performance analysis tools</string>
- <key>license</key>
- <string>BSD</string>
- <key>license_file</key>
- <string>LICENSES/gperftools.txt</string>
- <key>name</key>
- <string>gperftools</string>
- <key>platforms</key>
- <map>
- <key>darwin</key>
+ <key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>0137e450bf24cff7e78634bb9a1c85e4</string>
+ <string>0f606bf01f933f00edeb9bf9a2530930</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/google-perftools_3p-update-google-perftools/rev/297263/arch/Darwin/installer/gperftools-2.0.297263-darwin-297263.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/918/2056/googlemock-1.7.0.500908-linux64-500908.tar.bz2</string>
</map>
<key>name</key>
- <string>darwin</string>
+ <string>linux64</string>
</map>
- <key>linux</key>
+ <key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>0c252bcaa1cb852f5c4e46a13ed459c5</string>
+ <string>d01c9b12be6c5bb0749441495d45cba3</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/google-perftools_3p-update-google-perftools/rev/297263/arch/Linux/installer/gperftools-2.0.297263-linux-297263.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/920/2051/googlemock-1.7.0.500908-windows-500908.tar.bz2</string>
</map>
<key>name</key>
- <string>linux</string>
+ <string>windows</string>
</map>
- <key>windows</key>
+ <key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>2946f9bbf227dee8881af43856ebb3a1</string>
+ <string>e508a2ac7900853cc551666d0cf06541</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/google-perftools_3p-update-google-perftools/rev/297263/arch/CYGWIN/installer/gperftools-2.0.297263-windows-297263.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/921/2059/googlemock-1.7.0.500908-windows64-500908.tar.bz2</string>
</map>
<key>name</key>
- <string>windows</string>
+ <string>windows64</string>
</map>
</map>
<key>version</key>
- <string>2.0.297263</string>
+ <string>1.7.0.500908</string>
</map>
<key>gstreamer</key>
<map>
@@ -946,16 +1228,28 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>fb1479533a7699b44d34e3a550037eb7</string>
+ <string>5017b3e95d2c6f47bb111c3f9c075522</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/gstreamer_3p-update-gstreamer/rev/294903/arch/Linux/installer/gstreamer-0.10.6.294903-linux-294903.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gstreamer/rev/314267/arch/Linux/installer/gstreamer-0.10.6.314267-linux-314267.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7c9d7cc88add7831a6afeedc20cad2fe</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gstreamer/rev/314267/arch/Linux/installer/gstreamer-0.10.6.314267-linux64-314267.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
</map>
<key>version</key>
- <string>0.10.6.294903</string>
+ <string>0.10.6.314267</string>
</map>
<key>gtk-atk-pango-glib</key>
<map>
@@ -974,16 +1268,28 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>15af375116f5c943ea6f4190bc764224</string>
+ <string>a6431df705526501684d9050e04bfa5b</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/gtk_3p-gtk-atk-pango-glib/rev/294804/arch/Linux/installer/gtk_atk_pango_glib-0.1-linux-294804.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gtk-atk-pango-glib/rev/314220/arch/Linux/installer/gtk_atk_pango_glib-0.1-linux-314220.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>de7bba8fd2275a11b077b124413065d0</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gtk-atk-pango-glib/rev/314220/arch/Linux/installer/gtk_atk_pango_glib-0.1-linux64-314220.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
</map>
<key>version</key>
- <string>0.0</string>
+ <string>0.1</string>
</map>
<key>havok-source</key>
<map>
@@ -1011,33 +1317,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>cbaa7619050123c3fd2a88959f88bd47</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/749/1553/havok_source-2012.1-2-darwin64-500739.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>6b0f41ddddfa60d8424d8a2e0bc2077d</string>
+ <string>03c1c5f7c3e93e905f635ca22b607494</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/havok-source_3p-update-havok-source/rev/296959/arch/Linux/installer/havok_source-2012.1-linux-296959.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_3p-havok-source/rev/314226/arch/Linux/installer/havok_source-2012.1-2-linux-314226.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>00d0333936a67059a43a6ec8ac38d564</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/748/1563/havok_source-2012.1-2-linux64-500739.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>ab30ae74a665950d73ea559f019ff358</string>
+ <string>96b6b1a0ae2c2ac9dfa44b444f71117a</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/havok-source_3p-update-havok-source/rev/297566/arch/CYGWIN/installer/havok_source-2012.1-windows-297566.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/752/1566/havok_source-2012.1-2-windows-500739.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>5db6f7f8a86fa2297f2c7c86d7491042</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/751/1558/havok_source-2012.1-2-windows64-500739.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>2012.1</string>
+ <string>2012.1-2</string>
</map>
<key>jpeglib</key>
<map>
@@ -1065,33 +1407,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>2a33d85c5afa07612e8c4f314ab29545</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/478/1016/jpeglib-8c.500387-darwin64-500387.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>0a6641f030e173a7bc0dc8a3087b6c7d</string>
+ <string>32560d3200da72fea2922371fcef25f5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/jpeglib_3p-update-jpeglib/rev/296854/arch/Linux/installer/jpeglib-8c.296854-linux-296854.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-jpeglib/rev/314202/arch/Linux/installer/jpeglib-8c.314202-linux-314202.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7d699142394f54a334b4fd203b4c9eea</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/457/970/jpeglib-8c.500387-linux64-500387.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>98d3dc8d107d04b572fe47bd43a56e74</string>
+ <string>543e25c3819399f37e0453db5eea558a</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/jpeglib_3p-update-jpeglib/rev/296854/arch/CYGWIN/installer/jpeglib-8c.296854-windows-296854.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/497/1062/jpeglib-8c.500387-windows-500387.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>dbc2baf28f83d1646d7e2f66ead2a1a4</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/494/1049/jpeglib-8c.500387-windows64-500387.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>8c.296854</string>
+ <string>8c.500387</string>
</map>
<key>jsoncpp</key>
<map>
@@ -1119,33 +1497,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ba30bc3d67ef22700b534b15505bf976</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/606/1275/jsoncpp-0.5.0.500597-darwin64-500597.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>5b3b5dbf0c82c1046482a74ce9e11c38</string>
+ <string>9d5d9fec28cbbb1651b95728173f8af7</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/jsoncpp_3p-update-jsoncpp/rev/297281/arch/Linux/installer/jsoncpp-0.5.0.297281-linux-297281.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-jsoncpp/rev/314229/arch/Linux/installer/jsoncpp-0.5.0.314229-linux-314229.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>a88378cb3019a47f3249243384d3c5da</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/605/1270/jsoncpp-0.5.0.500597-linux64-500597.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e5a832cffe307a1e814ca0664be30b10</string>
+ <string>483ba51ff4060d02900adf8b7ca12e32</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/jsoncpp_3p-update-jsoncpp/rev/297580/arch/CYGWIN/installer/jsoncpp-0.5.0.297580-windows-297580.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/608/1281/jsoncpp-0.5.0.500597-windows-500597.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>25694d8f71efba5479e0475cd1bf3c2f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/607/1278/jsoncpp-0.5.0.500597-windows64-500597.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>0.5.0.297580</string>
+ <string>0.5.0.500597</string>
</map>
<key>kdu</key>
<map>
@@ -1166,13 +1580,25 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>e62f2fc1ee9ab791d603c5b717b46119</string>
+ <string>c2a8811ab2ff1e60a8afc6268c5b44c1</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/kdu_3p-update-kdu/rev/296932/arch/Darwin/installer/kdu-7.2.296932-darwin-296932.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1119/2596/kdu-7.8.501106-darwin-501106.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>a13540f797be940fc9fd6d9299633a1a</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1118/2591/kdu-7.8.501106-darwin64-501106.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
@@ -1185,21 +1611,45 @@
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>c4e560a31c009ad3e62b79daf2cc8628</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/958/2200/kdu-7.8.500948-linux64-500948.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>a0e5c050a4975c81611d9f1862ac57fb</string>
+ <string>f25f1b6e36c571d5ddb5625ac5fe1633</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/kdu_3p-update-kdu/rev/296932/arch/CYGWIN/installer/kdu-7.2.296932-windows-296932.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1123/2612/kdu-7.8.501106-windows-501106.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>fc706eaebd1a81b8f6e95acb6e06cc28</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1122/2609/kdu-7.8.501106-windows64-501106.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>7.2.296932</string>
+ <string>7.8.501106</string>
</map>
<key>libhunspell</key>
<map>
@@ -1227,33 +1677,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>4b238300cf9c405cdcab18030372832f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/534/1149/libhunspell-1.3.2.500526-darwin64-500526.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>988deae5c63ec638ad222b400a431f5b</string>
+ <string>0d8009c3b6c1eb510593476dd1d821b5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/hunspell_3p-update-hunspell/rev/296916/arch/Linux/installer/libhunspell-1.3.2.296916-linux-296916.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-hunspell/rev/314217/arch/Linux/installer/libhunspell-1.3.2.314217-linux-314217.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ffbdd109356d66ddfefd8a5d57f63f1f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/533/1144/libhunspell-1.3.2.500526-linux64-500526.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>ada0ad726842d902c09ab20a7ad5ac8f</string>
+ <string>a2025f748a6311ab390f89068b22c702</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/hunspell_3p-update-hunspell/rev/296916/arch/CYGWIN/installer/libhunspell-1.3.2.296916-windows-296916.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/535/1152/libhunspell-1.3.2.500526-windows-500526.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>233d86906ef88fa331263162a53e29f2</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/536/1155/libhunspell-1.3.2.500526-windows64-500526.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.3.2.296916</string>
+ <string>1.3.2.500526</string>
</map>
<key>libndofdev</key>
<map>
@@ -1281,21 +1767,45 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>840bb6219f63a789749f5f6583c44eee</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/704/1420/libndofdev-0.1.500695-darwin64-500695.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>1c40c22fb7b84ccccefbf797e2478ec4</string>
+ <string>fdbebbbde3b289d93c0c8c294cf859cb</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libndofdev_3p-update-libndofdev/rev/297264/arch/CYGWIN/installer/libndofdev-0.1.297264-windows-297264.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/708/1426/libndofdev-0.1.500695-windows-500695.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>15cef2cec6c8d1980011e26249bd4e90</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/707/1423/libndofdev-0.1.500695-windows64-500695.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>0.1.297264</string>
+ <string>0.1.500695</string>
</map>
<key>libpng</key>
<map>
@@ -1323,33 +1833,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>537b59a75709bd9abe0abe0c7309add4</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/883/1951/libpng-1.6.8.500873-darwin64-500873.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>6dec32fc2527f8cafd616f9271ff3478</string>
+ <string>0758f3cb4c02ebab61854b811b0894e9</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libpng_3p-update-libpng/rev/297051/arch/Linux/installer/libpng-1.6.8.297051-linux-297051.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libpng/rev/314214/arch/Linux/installer/libpng-1.6.8.314214-linux-314214.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>13de93ea11544051b69f238eeb644fd3</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/882/1946/libpng-1.6.8.500873-linux64-500873.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>09eb65e66e0230ab01e57e643647a4f1</string>
+ <string>9c2950f9d16566979dcd6ca6336778b3</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libpng_3p-update-libpng/rev/297708/arch/CYGWIN/installer/libpng-1.6.8.297708-windows-297708.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/885/1957/libpng-1.6.8.500873-windows-500873.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>18fe233471e91d5d3ac6d08a296b79ba</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/884/1954/libpng-1.6.8.500873-windows64-500873.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.6.8.297708</string>
+ <string>1.6.8.500873</string>
</map>
<key>libuuid</key>
<map>
@@ -1370,13 +1916,25 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>f231b6ec8bc2f050cfb1ee20bd83190d</string>
+ <string>a2eaf9515cd129f3e21a08e92689006b</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libuuid_3p-update-libuuid/rev/295209/arch/Linux/installer/libuuid-1.6.2-linux-295209.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libuuid/rev/314269/arch/Linux/installer/libuuid-1.6.2-linux-314269.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>fb89f1281dd54d8b99b339fc5b712b27</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libuuid/rev/314269/arch/Linux/installer/libuuid-1.6.2-linux64-314269.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
</map>
<key>version</key>
<string>1.6.2</string>
@@ -1407,33 +1965,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>89a71a652a5ecd7cf6142ff56f40f018</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/891/1973/libxml2-2.9.4.500877-darwin64-500877.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>b8b584853dc1344bb3571c13b06ec39e</string>
+ <string>6954173a141d928f2614076577d952de</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libxml_3p-update-libxml/rev/297050/arch/Linux/installer/libxml2-2.9.1.297050-linux-297050.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libxml/rev/314197/arch/Linux/installer/libxml2-2.9.1.314197-linux-314197.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>740fc93f195c77b3a0c0800b31878ecb</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/890/1968/libxml2-2.9.4.500877-linux64-500877.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>37fa0e86e54f5f283aa653d770fc8ed5</string>
+ <string>c2461ba7629c4cef5af623464aded3c6</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libxml_3p-update-libxml/rev/297050/arch/CYGWIN/installer/libxml2-2.9.1.297050-windows-297050.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/888/1960/libxml2-2.9.4.500877-windows-500877.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>8ec25000f5d72e26c2e7555c73898fbb</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/889/1963/libxml2-2.9.4.500877-windows64-500877.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>2.9.1.297050</string>
+ <string>2.9.4.500877</string>
</map>
<key>llappearance_utility</key>
<map>
@@ -1454,9 +2048,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>faa1e5b7cf70c143caabe190fa5588ce</string>
+ <string>fddd634dec5ec03924d62cc774f7f8ea</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/304432/arch/Linux/installer/llappearance_utility-0.0.1-linux-304432.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_viewer-llappearance-utility/rev/317266/arch/Linux/installer/llappearance_utility-0.0.1-linux-317266.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@@ -1484,11 +2078,11 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>29a1f64df46094eda0d681821a98d17e</string>
+ <string>2845033912eb947a1401847ece1469ce</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/Darwin/installer/llceflib-1.5.3.311349-darwin-311349.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/321153/arch/Darwin/installer/llceflib-1.5.3.321153-darwin-321153.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@@ -1498,18 +2092,30 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>827b7c339a2cd401d9d23f9ee02cb83f</string>
+ <string>640cd808de734d9a6ca564475d951980</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/CYGWIN/installer/llceflib-1.5.3.311349-windows-311349.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1121/2604/llceflib-1.5.3.501109-windows-501109.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>f4b75f37ba344db3efeddfafff10f5f9</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1120/2601/llceflib-1.5.3.501109-windows64-501109.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.5.3.311349</string>
+ <string>1.5.3.501109</string>
</map>
<key>llphysicsextensions_source</key>
<map>
@@ -1537,33 +2143,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>8d66b068425d2cbc65949c83d7f37d23</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/486/1031/llphysicsextensions_source-1.0.500392-darwin64-500392.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>c94dc7ab6efe59c0d5d04fc447257c57</string>
+ <string>18ebea18be4cf0d3da4a6bb73787395c</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions/rev/313564/arch/Linux/installer/llphysicsextensions_source-1.0.313564-linux-313564.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_llphysicsextensions/rev/314244/arch/Linux/installer/llphysicsextensions_source-1.0.314244-linux-314244.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>20279e8be7f8971c59f0b8f6aa513098</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/463/980/llphysicsextensions_source-1.0.500392-linux64-500392.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e760be34addeb0cd6e2ec43394834bac</string>
+ <string>0ac91b8fadeebb767d8c7a4ab5272319</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions/rev/313564/arch/CYGWIN/installer/llphysicsextensions_source-1.0.313564-windows-313564.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/508/1090/llphysicsextensions_source-1.0.500392-windows-500392.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ec95c627af598b6db5be99cff5559699</string>
+ <key>url</key>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/507/1087/llphysicsextensions_source-1.0.500392-windows64-500392.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.0.313564</string>
+ <string>1.0.500392</string>
</map>
<key>llphysicsextensions_stub</key>
<map>
@@ -1591,33 +2233,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>c7676595a2b49e41aa3e32bf99e5cf2f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1081/2505/llphysicsextensions_stub-1.0.501069-darwin64-501069.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e99afb25a4fd5b08c5cd3060ae9c1d59</string>
+ <string>f7dc825d13dec920a36641823f87dd94</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions/rev/313563/arch/Linux/installer/llphysicsextensions_stub-1.0.313563-linux-313563.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_llphysicsextensions/rev/314246/arch/Linux/installer/llphysicsextensions_stub-1.0.314246-linux-314246.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>430a1c16c2a0f999742411389e6bb50f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1080/2500/llphysicsextensions_stub-1.0.501069-linux64-501069.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>6f4307a35c692e44b872125d7932df8e</string>
+ <string>72b163adfc692d4930fa391043329c88</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions/rev/313563/arch/CYGWIN/installer/llphysicsextensions_stub-1.0.313563-windows-313563.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1083/2511/llphysicsextensions_stub-1.0.501069-windows-501069.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>b0a066c3fcee095843d9077ccbc8a75b</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1082/2508/llphysicsextensions_stub-1.0.501069-windows64-501069.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.0.313563</string>
+ <string>1.0.501069</string>
</map>
<key>mesa</key>
<map>
@@ -1664,16 +2342,28 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>9e30c9e228d6a825b6774b97ff052973</string>
+ <string>22c7be12c1d2ee87b059be903d7f2fbd</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/nvapi_3p-update-nvapi/rev/295118/arch/CYGWIN/installer/nvapi-304-windows-295118.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-nvapi/rev/314405/arch/CYGWIN/installer/nvapi-352.314405-windows-314405.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>90e32843a0e21037001dc88240008e1f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-nvapi/rev/314405/arch/CYGWIN/installer/nvapi-352.314405-windows64-314405.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>304</string>
+ <string>352.314405</string>
</map>
<key>ogg_vorbis</key>
<map>
@@ -1701,33 +2391,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>bb8bed08fd5973a040c509ef8b545ec8</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/490/1046/ogg_vorbis-1.2.2-1.3.2.500397-darwin64-500397.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>b0cd31d5b07a9fc25c4d69ba2f95eace</string>
+ <string>5c9d94dce4551b19790057766ff939ea</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oggvorbis_3p-update-oggvorbis/rev/296878/arch/Linux/installer/ogg_vorbis-1.2.2-1.3.2.296878-linux-296878.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-oggvorbis/rev/314224/arch/Linux/installer/ogg_vorbis-1.2.2-1.3.2.314224-linux-314224.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>45ebd074053dc9cae8c5c74b52085d4b</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/465/990/ogg_vorbis-1.2.2-1.3.2.500397-linux64-500397.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>f358717739c288ec7401d6d1936ef878</string>
+ <string>f7edf86dcf2d9be7bee98c91256fa569</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oggvorbis_3p-update-oggvorbis/rev/296878/arch/CYGWIN/installer/ogg_vorbis-1.2.2-1.3.2.296878-windows-296878.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/512/1108/ogg_vorbis-1.2.2-1.3.2.500397-windows-500397.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>497ec6ac26c2e136ee65acbed86cb2ef</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/511/1105/ogg_vorbis-1.2.2-1.3.2.500397-windows64-500397.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.2.2-1.3.2.296878</string>
+ <string>1.2.2-1.3.2.500397</string>
</map>
<key>open-libndofdev</key>
<map>
@@ -1778,37 +2504,61 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>15ebe611213c9577691ffbade081549d</string>
+ <string>24b91eda3831a51c7774644016c4cb09</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openal_3p-update-openal/rev/297677/arch/Linux/installer/openal-1.12.854-1.1.0.297677-linux-297677.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/Linux/installer/openal-1.12.854-1.1.0.314223-linux-314223.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7530fab3979312da75a903d87b73e3a9</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/Linux/installer/openal-1.12.854-1.1.0.314223-linux64-314223.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>3bf6e26aeec71f36c8b6e20c6b883fe9</string>
+ <string>d9c86f79a6bb56a670e2801c33fd2dd1</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openal_3p-update-openal/rev/297677/arch/CYGWIN/installer/openal-1.12.854-1.1.0.297677-windows-297677.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/CYGWIN/installer/openal-1.12.854-1.1.0.314223-windows-314223.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>e0fdd9394a8cd8c6360b922f6f237e57</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/CYGWIN/installer/openal-1.12.854-1.1.0.314223-windows64-314223.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.12.854-1.1.0.297677</string>
+ <string>1.12.854-1.1.0.314223</string>
</map>
<key>openjpeg</key>
<map>
<key>copyright</key>
- <string>Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium, Copyright (c) 2002-2007, Professor Benoit Macq, Copyright (c) 2001-2003, David Janssens, Copyright (c) 2002-2003, Yannick Verschueren, Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe, Copyright (c) 2005, Herve Drolon, FreeImage Team</string>
+ <string>Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium; Copyright (c) 2002-2007, Professor Benoit Macq; Copyright (c) 2001-2003, David Janssens; Copyright (c) 2002-2003, Yannick Verschueren; Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe; Copyright (c) 2005, Herve Drolon, FreeImage Team; Copyright (c) 2006-2007, Parvatha Elangovan; Copyright (c) 2008, Jerome Fimes, Communications &amp; Systemes &lt;jerome.fimes@c-s.fr&gt;; Copyright (c) 2010-2011, Kaori Hagihara; Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France; Copyright (c) 2012, CS Systemes d'Information, France;</string>
<key>description</key>
<string>The OpenJPEG library is an open-source JPEG 2000 codec written in C language.</string>
<key>license</key>
@@ -1831,33 +2581,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>f7013e1f0b6a877090622fd73ec72cbc</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1114/2576/openjpeg-1.5.1.501102-darwin64-501102.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>675c283030879d3d9c49082bfa2192eb</string>
+ <string>e82317482647559d46a818ba48e9423a</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openjpeg_3p-update-openjpeg/rev/297018/arch/Linux/installer/openjpeg-1.4.297018-linux-297018.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openjpeg/rev/314205/arch/Linux/installer/openjpeg-2.0.0.314205-linux-314205.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>ac66f3197010b1549a5e4467aebbc27d</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1113/2571/openjpeg-1.5.1.501102-linux64-501102.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>b35adcf74d22c128045aa87aade74736</string>
+ <string>8a7f0be5647e07235d205ac00805fb78</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openjpeg_3p-update-openjpeg/rev/297018/arch/CYGWIN/installer/openjpeg-1.4.297018-windows-297018.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1116/2586/openjpeg-1.5.1.501102-windows-501102.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>398544058036bc27097fcff208934d11</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1115/2581/openjpeg-1.5.1.501102-windows64-501102.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.4.297018</string>
+ <string>1.5.1.501102</string>
</map>
<key>openssl</key>
<map>
@@ -1885,33 +2671,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7011482b07b32b375ecc3e891c37f469</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1063/2462/openssl-1.0.1u.501051-darwin64-501051.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>c310ba9971cbd796b303c3be67fb11c6</string>
+ <string>f46a601d60b7dbcfde32afc0cb64453e</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openssl_3p-update-openssl/rev/297168/arch/Linux/installer/openssl-1.0.1h.297168-linux-297168.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openssl/rev/314227/arch/Linux/installer/openssl-1.0.1h.314227-linux-314227.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>50bb9aca605a599cb1a46da3c45f78ac</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1062/2473/openssl-1.0.1u.501051-linux64-501051.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>398743f47578cbb44f5504128780369f</string>
+ <string>7d9801f9ce049ffd30fbe06b6bac4c91</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openssl_3p-update-openssl/rev/297168/arch/CYGWIN/installer/openssl-1.0.1h.297168-windows-297168.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1064/2465/openssl-1.0.1u.501051-windows-501051.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>c3e404a9cc51d64c71ec13dbd44b8409</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1065/2468/openssl-1.0.1u.501051-windows64-501051.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.0.1h.297168</string>
+ <string>1.0.1u.501051</string>
</map>
<key>pcre</key>
<map>
@@ -1939,63 +2761,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>addfbc0635b0ea65d7a151dd7ec5ef85</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/909/2015/pcre-8.35.500898-darwin64-500898.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>b82817bcc2f63094d9c915d018d0b036</string>
+ <string>24a119b18e63017ad932ad54df8161bc</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/pcre_3p-update-pcre/rev/297155/arch/Linux/installer/pcre-8.35.-linux-297155.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-pcre/rev/314136/arch/Linux/installer/pcre-8.35.314136-linux-314136.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>0f058ca2176e7d02d51e54c66a96f336</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/908/2010/pcre-8.35.500898-linux64-500898.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>96ed836c89a99dfc22f9c16a0d7272d3</string>
+ <string>150220f39f0aa5a8d9e609b450a9b147</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/pcre_3p-update-pcre/rev/297155/arch/CYGWIN/installer/pcre-8.35.-windows-297155.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/911/2021/pcre-8.35.500898-windows-500898.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
- </map>
- <key>version</key>
- <string>8.35.</string>
- </map>
- <key>quicktime</key>
- <map>
- <key>copyright</key>
- <string>2010 Apple</string>
- <key>description</key>
- <string>QuickTime 7.3 SDK for Windows</string>
- <key>license</key>
- <string>unknown</string>
- <key>license_file</key>
- <string>LICENSES/quicktime.txt</string>
- <key>name</key>
- <string>quicktime</string>
- <key>platforms</key>
- <map>
- <key>windows</key>
+ <key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>78650a79bda6435e623a940ad425a593</string>
+ <string>eaebfb4a96a6306ee8e0b18434d125f9</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/quicktime_3p-update-quicktime/rev/300073/arch/CYGWIN/installer/quicktime-7.3-windows-300073.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/910/2018/pcre-8.35.500898-windows64-500898.tar.bz2</string>
</map>
<key>name</key>
- <string>windows</string>
+ <string>windows64</string>
</map>
</map>
<key>version</key>
- <string>7.3</string>
+ <string>8.35.500898</string>
</map>
<key>slvoice</key>
<map>
@@ -2016,40 +2844,76 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>3dd9bf4185bf2df413d890ca9eeab76c</string>
+ <string>8c2f921001a8ee29b826a45181465735</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/vivox_3p-slvoice/rev/302004/arch/Darwin/installer/slvoice-4.6.0017.22050.302004-darwin-302004.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-slvoice/rev/314209/arch/Darwin/installer/slvoice-4.6.0017.21209.314209-darwin-314209.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>c9b0d816cf14bebba138ea6f9f463553</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/614/1294/slvoice-4.6.0017.21209.500605-darwin64-500605.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>06c3a9b1005249f0c94a8b9f3775f3d3</string>
+ <string>e5832a68562c3409a56a3583d101864b</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/vivox_3p-slvoice/rev/302004/arch/Linux/installer/slvoice-3.2.0002.10426.302004-linux-302004.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-slvoice/rev/314209/arch/Linux/installer/slvoice-3.2.0002.10426.314209-linux-314209.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>92b0ae08832bd0e99c34ef8f3e6346ad</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/613/1289/slvoice-3.2.0002.10426.500605-linux64-500605.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>47a3316dae47cc4e7c1ea7b74ba8dd1e</string>
+ <string>3ce62e3696f26a1e09e0c769280e5608</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/vivox_3p-slvoice/rev/302004/arch/CYGWIN/installer/slvoice-4.6.0017.22050.302004-windows-302004.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/616/1300/slvoice-4.6.0017.21209.500605-windows-500605.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>61c41dd565e2caa38bd0056970094749</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/615/1297/slvoice-4.6.0017.21209.500605-windows64-500605.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>3.2.0002.10426.302004</string>
+ <string>4.6.0017.21209.500605</string>
</map>
<key>tut</key>
<map>
@@ -2070,9 +2934,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>2f32faa00e600911f838a7d82da5a8db</string>
+ <string>722563bd6e2ae0c7e53c027d267154f7</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/tut_3p-update-tut/rev/297257/arch/Linux/installer/tut-2008.11.30-common-297257.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/496/1054/tut-2008.11.30-common-500403.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
@@ -2107,6 +2971,18 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>5b9cd1d6fac519aad59f6d53a54229c5</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/347/872/uriparser-0.8.0.1-darwin64-500342.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
@@ -2119,22 +2995,86 @@
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>087375378f104cdac0cb0fe0ca43dd4d</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/346/880/uriparser-0.8.0.1-linux64-500342.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e4520158dda88453e46942eab6f9c0a8</string>
+ <string>1becd11c19dd1763f0322ba4d1a5ee06</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/uriparser_3p-update-uriparser/rev/299435/arch/CYGWIN/installer/uriparser-0.8.0.1-windows-299435.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/521/1129/uriparser-0.8.0.1-windows-500342.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>587db55a2a3ce57628374b5e27b3272e</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/349/875/uriparser-0.8.0.1-windows64-500342.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
<string>0.8.0.1</string>
</map>
+ <key>vlc-bin</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string>
+ <key>license</key>
+ <string>GPL2</string>
+ <key>license_file</key>
+ <string>LICENSES/vlc.txt</string>
+ <key>name</key>
+ <string>vlc-bin</string>
+ <key>platforms</key>
+ <map>
+ <key>linux</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>2f410640df3f9812d1abff02a414cfa8</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>04cff37070a5f65f3652b4ddcec7183f</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/317935/arch/CYGWIN/installer/vlc_bin-2.2.4.317935-windows-317935.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>2.2.4.317935</string>
+ </map>
<key>xmlrpc-epi</key>
<map>
<key>copyright</key>
@@ -2161,33 +3101,69 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>b2d31df56a10c634657eed856c8d7895</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/728/1494/xmlrpc_epi-0.54.1.500719-darwin64-500719.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>30bb26d6cc78c16047fc85a63f48fcdb</string>
+ <string>b63f828e798287d475991134cdcfbca3</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/xmlrpc-emi_3p-update-xmlrpc-epi/rev/297075/arch/Linux/installer/xmlrpc_epi-0.54.1.297075-linux-297075.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-xmlrpc-epi/rev/314240/arch/Linux/installer/xmlrpc_epi-0.54.1.314240-linux-314240.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>35df17c3eb673030dea4bde9191aa506</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/727/1489/xmlrpc_epi-0.54.1.500719-linux64-500719.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>a7e1a8369a5afd52e1b6fc1f14155033</string>
+ <string>6c16f020bf01155e6746487af0b26173</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/xmlrpc-emi_3p-update-xmlrpc-epi/rev/297075/arch/CYGWIN/installer/xmlrpc_epi-0.54.1.297075-windows-297075.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/729/1497/xmlrpc_epi-0.54.1.500719-windows-500719.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>a9dda7caa8835c52b3735711cfee4eb9</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/730/1500/xmlrpc_epi-0.54.1.500719-windows64-500719.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>0.54.1.297075</string>
+ <string>0.54.1.500719</string>
</map>
<key>zlib</key>
<map>
@@ -2215,35 +3191,71 @@
<key>name</key>
<string>darwin</string>
</map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>e204dee29902549f50af1af2bb098df5</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/867/1903/zlib-1.2.8.500857-darwin64-500857.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>2eb8e59b6464222dcf4435016ad5f618</string>
+ <string>98a8c775c581ca80bb559e8b4e8eaae7</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/zlib_3p-update-zlib/rev/296881/arch/Linux/installer/zlib-1.2.8.296881-linux-296881.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-zlib/rev/314131/arch/Linux/installer/zlib-1.2.8.314131-linux-314131.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>dab6be8b0596c1e3354f2b6d41335131</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/866/1898/zlib-1.2.8.500857-linux64-500857.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>ae420ec6d30411c07aac2502d7bbc0f3</string>
+ <string>f92cbb0ab5e5d20789bf6102f9a27aa6</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/zlib_3p-update-zlib/rev/296881/arch/CYGWIN/installer/zlib-1.2.8.296881-windows-296881.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/868/1906/zlib-1.2.8.500857-windows-500857.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>70a56767f6a109af412838875d0b5f1b</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/869/1909/zlib-1.2.8.500857-windows64-500857.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
</map>
<key>version</key>
- <string>1.2.8.296881</string>
+ <string>1.2.8.500857</string>
</map>
</map>
<key>package_description</key>
@@ -2276,7 +3288,7 @@
<key>options</key>
<array>
<string>-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</string>
- <string>-DWORD_SIZE:STRING=32</string>
+ <string>-DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE</string>
<string>-DROOT_PROJECT_NAME:STRING=SecondLife</string>
<string>-DINSTALL_PROPRIETARY=TRUE</string>
</array>
@@ -2297,7 +3309,7 @@
<key>options</key>
<array>
<string>-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo</string>
- <string>-DWORD_SIZE:STRING=32</string>
+ <string>-DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE</string>
<string>-DROOT_PROJECT_NAME:STRING=SecondLife</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
</array>
@@ -2317,7 +3329,7 @@
<key>options</key>
<array>
<string>-DCMAKE_BUILD_TYPE:STRING=Release</string>
- <string>-DWORD_SIZE:STRING=32</string>
+ <string>-DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE</string>
<string>-DROOT_PROJECT_NAME:STRING=SecondLife</string>
<string>-DINSTALL_PROPRIETARY=TRUE</string>
</array>
@@ -2338,7 +3350,7 @@
<key>options</key>
<array>
<string>-DCMAKE_BUILD_TYPE:STRING=Release</string>
- <string>-DWORD_SIZE:STRING=32</string>
+ <string>-DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE</string>
<string>-DROOT_PROJECT_NAME:STRING=SecondLife</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
</array>
@@ -2350,7 +3362,7 @@
<key>name</key>
<string>common</string>
</map>
- <key>darwin</key>
+ <key>darwin64</key>
<map>
<key>build_directory</key>
<string>build-darwin-i386</string>
@@ -2368,8 +3380,10 @@
</array>
<key>options</key>
<array>
- <string>-configuration RelWithDebInfo</string>
- <string>-project SecondLife.xcodeproj</string>
+ <string>-configuration</string>
+ <string>RelWithDebInfo</string>
+ <string>-project</string>
+ <string>SecondLife.xcodeproj</string>
</array>
</map>
<key>configure</key>
@@ -2381,7 +3395,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Xcode'</string>
+ <string>Xcode</string>
</array>
</map>
<key>default</key>
@@ -2397,8 +3411,10 @@
<string>xcodebuild</string>
<key>options</key>
<array>
- <string>-configuration RelWithDebInfo</string>
- <string>-project SecondLife.xcodeproj</string>
+ <string>-configuration</string>
+ <string>RelWithDebInfo</string>
+ <string>-project</string>
+ <string>SecondLife.xcodeproj</string>
</array>
</map>
<key>configure</key>
@@ -2406,7 +3422,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Xcode'</string>
+ <string>Xcode</string>
</array>
</map>
<key>name</key>
@@ -2424,10 +3440,12 @@
</array>
<key>options</key>
<array>
- <string>-configuration Release</string>
- <string>-project SecondLife.xcodeproj</string>
+ <string>-configuration</string>
+ <string>Release</string>
+ <string>-project</string>
+ <string>SecondLife.xcodeproj</string>
<string>-DENABLE_SIGNING:BOOL=YES</string>
- <string>-DSIGNING_IDENTITY:STRING="Developer ID Application: Linden Research, Inc."</string>
+ <string>-DSIGNING_IDENTITY:STRING=Developer ID Application: Linden Research, Inc.</string>
</array>
</map>
<key>configure</key>
@@ -2439,7 +3457,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Xcode'</string>
+ <string>Xcode</string>
</array>
</map>
<key>name</key>
@@ -2456,7 +3474,7 @@
<string>-configuration Release</string>
<string>-project SecondLife.xcodeproj</string>
<string>-DENABLE_SIGNING:BOOL=YES</string>
- <string>-DSIGNING_IDENTITY:STRING="Developer ID Application: Linden Research, Inc."</string>
+ <string>-DSIGNING_IDENTITY:STRING=Developer ID Application: Linden Research, Inc.</string>
</array>
</map>
<key>configure</key>
@@ -2464,7 +3482,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Xcode'</string>
+ <string>Xcode</string>
</array>
</map>
<key>name</key>
@@ -2472,7 +3490,7 @@
</map>
</map>
<key>name</key>
- <string>darwin</string>
+ <string>darwin64</string>
</map>
<key>linux</key>
<map>
@@ -2488,7 +3506,8 @@
<string>make</string>
<key>options</key>
<array>
- <string>-j 12</string>
+ <string>-j</string>
+ <string>12</string>
</array>
</map>
<key>configure</key>
@@ -2500,7 +3519,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Unix Makefiles'</string>
+ <string>Unix Makefiles</string>
</array>
</map>
<key>default</key>
@@ -2516,7 +3535,8 @@
<string>make</string>
<key>options</key>
<array>
- <string>-j 7</string>
+ <string>-j</string>
+ <string>7</string>
</array>
</map>
<key>configure</key>
@@ -2524,7 +3544,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Unix Makefiles'</string>
+ <string>Unix Makefiles</string>
</array>
</map>
<key>name</key>
@@ -2538,7 +3558,8 @@
<string>make</string>
<key>options</key>
<array>
- <string>-j 12</string>
+ <string>-j</string>
+ <string>12</string>
</array>
</map>
<key>configure</key>
@@ -2550,7 +3571,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Unix Makefiles'</string>
+ <string>Unix Makefiles</string>
</array>
</map>
<key>name</key>
@@ -2564,7 +3585,8 @@
<string>make</string>
<key>options</key>
<array>
- <string>-j 7</string>
+ <string>-j</string>
+ <string>7</string>
</array>
</map>
<key>configure</key>
@@ -2572,7 +3594,7 @@
<key>options</key>
<array>
<string>-G</string>
- <string>'Unix Makefiles'</string>
+ <string>Unix Makefiles</string>
</array>
</map>
<key>name</key>
@@ -2593,7 +3615,7 @@
<key>windows</key>
<map>
<key>build_directory</key>
- <string>build-vc120</string>
+ <string>build-vc120-$AUTOBUILD_ADDRSIZE</string>
<key>configurations</key>
<map>
<key>RelWithDebInfo</key>
@@ -2609,7 +3631,7 @@
<key>options</key>
<array>
<string>/build</string>
- <string>"RelWithDebInfo|Win32"</string>
+ <string>RelWithDebInfo|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}</string>
</array>
</map>
<key>configure</key>
@@ -2617,19 +3639,11 @@
<key>arguments</key>
<array>
<string>..\indra</string>
- <string>&amp;&amp;</string>
- <string>..\indra\tools\vstool\VSTool.exe</string>
- <string>--solution</string>
- <string>SecondLife.sln</string>
- <string>--config</string>
- <string>RelWithDebInfo</string>
- <string>--startup</string>
- <string>secondlife-bin</string>
</array>
<key>options</key>
<array>
<string>-G</string>
- <string>"Visual Studio 12"</string>
+ <string>${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}</string>
</array>
</map>
<key>default</key>
@@ -2650,12 +3664,12 @@
<key>options</key>
<array>
<string>/p:Configuration=RelWithDebInfo</string>
- <string>/p:Platform=Win32</string>
+ <string>/p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}</string>
<string>/t:Build</string>
<string>/p:useenv=true</string>
<string>/verbosity:minimal</string>
<string>/toolsversion:4.0</string>
- <string>/p:"VCBuildAdditionalOptions= /incremental"</string>
+ <string>/p:VCBuildAdditionalOptions= /incremental</string>
</array>
</map>
<key>configure</key>
@@ -2663,19 +3677,11 @@
<key>arguments</key>
<array>
<string>..\indra</string>
- <string>&amp;&amp;</string>
- <string>..\indra\tools\vstool\VSTool.exe</string>
- <string>--solution</string>
- <string>SecondLife.sln</string>
- <string>--config</string>
- <string>RelWithDebInfo</string>
- <string>--startup</string>
- <string>secondlife-bin</string>
</array>
<key>options</key>
<array>
<string>-G</string>
- <string>"Visual Studio 12"</string>
+ <string>${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}</string>
<string>-DUNATTENDED:BOOL=ON</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
<string>-DUSE_KDU=FALSE</string>
@@ -2697,7 +3703,7 @@
<key>options</key>
<array>
<string>/build</string>
- <string>"Release|Win32"</string>
+ <string>Release|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}</string>
</array>
</map>
<key>configure</key>
@@ -2705,19 +3711,11 @@
<key>arguments</key>
<array>
<string>..\indra</string>
- <string>&amp;&amp;</string>
- <string>..\indra\tools\vstool\VSTool.exe</string>
- <string>--solution</string>
- <string>SecondLife.sln</string>
- <string>--config</string>
- <string>Release</string>
- <string>--startup</string>
- <string>secondlife-bin</string>
</array>
<key>options</key>
<array>
<string>-G</string>
- <string>"Visual Studio 12"</string>
+ <string>${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}</string>
</array>
</map>
<key>name</key>
@@ -2736,12 +3734,12 @@
<key>options</key>
<array>
<string>/p:Configuration=Release</string>
- <string>/p:Platform=Win32</string>
+ <string>/p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}</string>
<string>/t:Build</string>
<string>/p:useenv=true</string>
<string>/verbosity:minimal</string>
<string>/toolsversion:4.0</string>
- <string>/p:"VCBuildAdditionalOptions= /incremental"</string>
+ <string>/p:VCBuildAdditionalOptions= /incremental</string>
</array>
</map>
<key>configure</key>
@@ -2749,19 +3747,11 @@
<key>arguments</key>
<array>
<string>..\indra</string>
- <string>&amp;&amp;</string>
- <string>..\indra\tools\vstool\VSTool.exe</string>
- <string>--solution</string>
- <string>SecondLife.sln</string>
- <string>--config</string>
- <string>Release</string>
- <string>--startup</string>
- <string>secondlife-bin</string>
</array>
<key>options</key>
<array>
<string>-G</string>
- <string>"Visual Studio 12"</string>
+ <string>${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}</string>
<string>-DUNATTENDED:BOOL=ON</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
<string>-DUSE_KDU=FALSE</string>
diff --git a/build.sh b/build.sh
index b7afdcd7f3..15bbe19f66 100755
--- a/build.sh
+++ b/build.sh
@@ -97,6 +97,7 @@ pre_build()
"$autobuild" configure --quiet -c $variant -- \
-DPACKAGE:BOOL=ON \
+ -DUNATTENDED:BOOL=ON \
-DRELEASE_CRASH_REPORTING:BOOL=ON \
-DVIEWER_CHANNEL:STRING="\"$viewer_channel\"" \
-DGRID:STRING="\"$viewer_grid\"" \
@@ -179,6 +180,8 @@ then
exit 1
fi
+initialize_build # provided by master buildscripts build.sh
+
# Check to see if we're skipping the platform
if ! eval '$build_'"$arch"
then
@@ -212,6 +215,8 @@ initialize_build
python_cmd "$helpers/codeticket.py" addinput "Viewer Channel" "${viewer_channel}"
initialize_version
+initialize_version # provided by buildscripts build.sh; sets version id
+
# Now run the build
succeeded=true
build_processes=
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 8ed41ddc34..f7d1ece72f 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -190,9 +190,19 @@ Ansariel Hiller
STORM-2094
MAINT-5756
MAINT-4677
+ MAINT-6300
+ MAINT-6397
MAINT-6432
+ MAINT-6513
+ MAINT-6514
+ MAINT-6552
STORM-2133
MAINT-6511
+ MAINT-6612
+ MAINT-6637
+ MAINT-6636
+ MAINT-6744
+ MAINT-6752
Aralara Rajal
Arare Chantilly
CHUIBUG-191
@@ -790,6 +800,7 @@ Kitty Barnett
MAINT-6152
MAINT-6153
MAINT-6154
+ MAINT-6568
Kolor Fall
Komiko Okamoto
Korvel Noh
@@ -1021,6 +1032,7 @@ Nicky Dasmijn
OPEN-187
STORM-2010
STORM-2082
+ MAINT-6665
Nicky Perian
OPEN-1
STORM-1087
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 86fc2dfff5..96ff9a645e 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -2,16 +2,28 @@
#
# Compilation options shared by all Second Life components.
+#*****************************************************************************
+# It's important to realize that CMake implicitly concatenates
+# CMAKE_CXX_FLAGS with (e.g.) CMAKE_CXX_FLAGS_RELEASE for Release builds. So
+# set switches in CMAKE_CXX_FLAGS that should affect all builds, but in
+# CMAKE_CXX_FLAGS_RELEASE or CMAKE_CXX_FLAGS_RELWITHDEBINFO for switches
+# that should affect only that build variant.
+#
+# Also realize that CMAKE_CXX_FLAGS may already be partially populated on
+# entry to this file.
+#*****************************************************************************
+
if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
include(Variables)
# Portable compilation flags.
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DADDRESS_SIZE=${ADDRESS_SIZE}")
+
set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1")
set(CMAKE_CXX_FLAGS_RELEASE
"-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -DNDEBUG")
-
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
"-DLL_RELEASE=1 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
@@ -74,17 +86,22 @@ if (WINDOWS)
/nologo
/Oy-
/Zc:wchar_t-
- /arch:SSE2
+# /arch:SSE2
/fp:fast
)
+
+ # Nicky: x64 implies SSE2
+ if( ADDRESS_SIZE EQUAL 32 )
+ add_definitions( /arch:SSE2 )
+ endif()
# Are we using the crummy Visual Studio KDU build workaround?
if (NOT VS_DISABLE_FATAL_WARNINGS)
add_definitions(/WX)
endif (NOT VS_DISABLE_FATAL_WARNINGS)
- # configure win32 API for windows XP+ compatibility
- set(WINVER "0x0501" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
+ # configure Win32 API for Windows Vista+ compatibility
+ set(WINVER "0x0600" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}")
endif (WINDOWS)
@@ -133,13 +150,6 @@ if (LINUX)
# Let's actually get a numerical version of gxx's version
STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION})
- # Hacks to work around gcc 4.1 TC build pool machines which can't process pragma warning disables
- # This is pure rubbish; I wish there was another way.
- #
- if(${CXX_VERSION_NUMBER} LESS 420)
- set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-uninitialized -Wno-unused-variable -Wno-unused-function ${CMAKE_CXX_FLAGS}")
- endif (${CXX_VERSION_NUMBER} LESS 420)
-
if(${CXX_VERSION_NUMBER} GREATER 459)
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}")
endif (${CXX_VERSION_NUMBER} GREATER 459)
@@ -173,9 +183,9 @@ if (LINUX)
add_definitions(-fvisibility=hidden)
# don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
add_definitions(-DLL_IGNORE_SIGCHLD)
- if (WORD_SIZE EQUAL 32)
+ if (ADDRESS_SIZE EQUAL 32)
add_definitions(-march=pentium4)
- endif (WORD_SIZE EQUAL 32)
+ endif (ADDRESS_SIZE EQUAL 32)
add_definitions(-mfpmath=sse)
#add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
if (NOT USESYSTEMLIBS)
@@ -201,8 +211,9 @@ if (DARWIN)
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
- set(ENABLE_SIGNING TRUE)
- set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
+## Really?? On developer machines too?
+##set(ENABLE_SIGNING TRUE)
+##set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
endif (DARWIN)
@@ -226,22 +237,17 @@ if (LINUX OR DARWIN)
set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
- if (WORD_SIZE EQUAL 32)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
- elseif (WORD_SIZE EQUAL 64)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64")
- endif (WORD_SIZE EQUAL 32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m${ADDRESS_SIZE}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m${ADDRESS_SIZE}")
endif (LINUX OR DARWIN)
if (USESYSTEMLIBS)
add_definitions(-DLL_USESYSTEMLIBS=1)
- if (LINUX AND ${ARCH} STREQUAL "i686")
+ if (LINUX AND ADDRESS_SIZE EQUAL 32)
add_definitions(-march=pentiumpro)
- endif (LINUX AND ${ARCH} STREQUAL "i686")
+ endif (LINUX AND ADDRESS_SIZE EQUAL 32)
else (USESYSTEMLIBS)
set(${ARCH}_linux_INCLUDES
diff --git a/indra/cmake/BuildPackagesInfo.cmake b/indra/cmake/BuildPackagesInfo.cmake
index 0f574ee39a..4e9baa61fe 100644
--- a/indra/cmake/BuildPackagesInfo.cmake
+++ b/indra/cmake/BuildPackagesInfo.cmake
@@ -6,5 +6,5 @@ add_custom_command(OUTPUT packages-info.txt
COMMENT Generating packages-info.txt for the about box
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/../autobuild.xml
DEPENDS ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py > packages-info.txt
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py "${VIEWER_CHANNEL}" "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}" > packages-info.txt
)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 6dc8e3dfbf..100645611e 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -24,14 +24,12 @@ set(cmake_SOURCE_FILES
DirectX.cmake
DragDrop.cmake
EXPAT.cmake
-## ExamplePlugin.cmake
FindAPR.cmake
FindAutobuild.cmake
FindBerkeleyDB.cmake
FindFMODEX.cmake
FindGLH.cmake
FindGoogleBreakpad.cmake
- FindGooglePerfTools.cmake
FindHUNSPELL.cmake
FindJsonCpp.cmake
FindNDOF.cmake
@@ -47,11 +45,8 @@ set(cmake_SOURCE_FILES
GLOD.cmake
## GStreamer010Plugin.cmake
GetPrerequisites_2_8.cmake
-## Glui.cmake
- Glut.cmake
GoogleBreakpad.cmake
GoogleMock.cmake
- GooglePerfTools.cmake
Havok.cmake
Hunspell.cmake
JPEG.cmake
@@ -91,7 +86,6 @@ set(cmake_SOURCE_FILES
Prebuilt.cmake
PulseAudio.cmake
Python.cmake
- QuickTimePlugin.cmake
TemplateCheck.cmake
Tut.cmake
UI.cmake
@@ -100,6 +94,7 @@ set(cmake_SOURCE_FILES
Variables.cmake
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
+ LibVLCPlugin.cmake
XmlRpcEpi.cmake
ZLIB.cmake
)
diff --git a/indra/cmake/ConfigurePkgConfig.cmake b/indra/cmake/ConfigurePkgConfig.cmake
index 82ee3e7a5b..55d865392e 100644
--- a/indra/cmake/ConfigurePkgConfig.cmake
+++ b/indra/cmake/ConfigurePkgConfig.cmake
@@ -6,17 +6,17 @@ SET(DEBUG_PKG_CONFIG "YES")
IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
# Guess at architecture-specific system library paths.
- if (WORD_SIZE EQUAL 32)
+ if (ADDRESS_SIZE EQUAL 32)
SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib)
SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib)
SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu)
SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu)
- else (WORD_SIZE EQUAL 32)
+ else (ADDRESS_SIZE EQUAL 32)
SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib)
SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib)
SET(PKG_CONFIG_MULTI_GUESS /usr/local/lib/x86_64-linux-gnu)
SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu)
- endif (WORD_SIZE EQUAL 32)
+ endif (ADDRESS_SIZE EQUAL 32)
# Use DPKG architecture, if available.
IF (${DPKG_ARCH})
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 70d85b864c..5b59666796 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -30,17 +30,16 @@ if(WINDOWS)
#*******************************
# Misc shared libs
- set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
- set(debug_files
- openjpegd.dll
- libapr-1.dll
- libaprutil-1.dll
- libapriconv-1.dll
- ssleay32.dll
- libeay32.dll
- glod.dll
- libhunspell.dll
- )
+# set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
+# set(debug_files
+# libapr-1.dll
+# libaprutil-1.dll
+# libapriconv-1.dll
+# ssleay32.dll
+# libeay32.dll
+# glod.dll
+# libhunspell.dll
+# )
set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(release_files
@@ -54,13 +53,8 @@ if(WINDOWS)
libhunspell.dll
)
- if(USE_TCMALLOC)
- set(debug_files ${debug_files} libtcmalloc_minimal-debug.dll)
- set(release_files ${release_files} libtcmalloc_minimal.dll)
- endif(USE_TCMALLOC)
-
if (FMODEX)
- set(debug_files ${debug_files} fmodexL.dll)
+# set(debug_files ${debug_files} fmodexL.dll)
set(release_files ${release_files} fmodex.dll)
endif (FMODEX)
@@ -234,10 +228,6 @@ elseif(LINUX)
libfontconfig.so.1
)
- if (USE_TCMALLOC)
- set(release_files ${release_files} "libtcmalloc_minimal.so")
- endif (USE_TCMALLOC)
-
if (FMODEX)
set(debug_files ${debug_files} "libfmodexL.so")
set(release_files ${release_files} "libfmodex.so")
@@ -294,13 +284,13 @@ set(third_party_targets ${third_party_targets} ${out_targets})
-copy_if_different(
- ${debug_src_dir}
- "${SHARED_LIB_STAGING_DIR_DEBUG}"
- out_targets
- ${debug_files}
- )
-set(third_party_targets ${third_party_targets} ${out_targets})
+#copy_if_different(
+# ${debug_src_dir}
+# "${SHARED_LIB_STAGING_DIR_DEBUG}"
+# out_targets
+# ${debug_files}
+# )
+#set(third_party_targets ${third_party_targets} ${out_targets})
copy_if_different(
${release_src_dir}
diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake
index 2a08c8fbae..9fd3923bfd 100644
--- a/indra/cmake/GLEXT.cmake
+++ b/indra/cmake/GLEXT.cmake
@@ -5,6 +5,6 @@ if (NOT USESYSTEMLIBS)
if (WINDOWS OR LINUX)
use_prebuilt_binary(glext)
endif (WINDOWS OR LINUX)
- use_prebuilt_binary(glh-linear)
+ use_prebuilt_binary(glh_linear)
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
endif (NOT USESYSTEMLIBS)
diff --git a/indra/cmake/GLH.cmake b/indra/cmake/GLH.cmake
index d0992f57b8..d5262f2efa 100644
--- a/indra/cmake/GLH.cmake
+++ b/indra/cmake/GLH.cmake
@@ -7,5 +7,5 @@ set(GLH_FIND_QUIETLY TRUE)
if (USESYSTEMLIBS)
include(FindGLH)
else (USESYSTEMLIBS)
- use_prebuilt_binary(glh-linear)
+ use_prebuilt_binary(glh_linear)
endif (USESYSTEMLIBS)
diff --git a/indra/cmake/Glui.cmake b/indra/cmake/Glui.cmake
deleted file mode 100644
index db353a91ec..0000000000
--- a/indra/cmake/Glui.cmake
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- cmake -*-
-include(Linking)
-include(Prebuilt)
-
-if (USESYSTEMLIBS)
- set(GLUI OFF CACHE BOOL
- "GLUI support for the llplugin/llmedia test apps.")
-else (USESYSTEMLIBS)
- use_prebuilt_binary(glui)
- set(GLUI ON CACHE BOOL
- "GLUI support for the llplugin/llmedia test apps.")
-endif (USESYSTEMLIBS)
-
-if (LINUX)
- set(GLUI ON CACHE BOOL
- "llplugin media apps HACK for Linux.")
-endif (LINUX)
-
-if (DARWIN OR LINUX)
- set(GLUI_LIBRARY
- glui)
-endif (DARWIN OR LINUX)
-
-if (WINDOWS)
- set(GLUI_LIBRARY
- debug glui32.lib
- optimized glui32.lib)
-endif (WINDOWS)
diff --git a/indra/cmake/Glut.cmake b/indra/cmake/Glut.cmake
deleted file mode 100644
index 314da30652..0000000000
--- a/indra/cmake/Glut.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- cmake -*-
-include(Linking)
-include(Prebuilt)
-
-if (WINDOWS)
- use_prebuilt_binary(freeglut)
- set(GLUT_LIBRARY
- debug freeglut_static.lib
- optimized freeglut_static.lib)
-endif (WINDOWS)
-
-if (LINUX)
- FIND_LIBRARY(GLUT_LIBRARY glut)
-endif (LINUX)
-
-if (DARWIN)
- include(CMakeFindFrameworks)
- find_library(GLUT_LIBRARY GLUT)
-endif (DARWIN)
diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake
deleted file mode 100644
index c1faeb9325..0000000000
--- a/indra/cmake/GooglePerfTools.cmake
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- cmake -*-
-include(Prebuilt)
-
-# If you want to enable or disable TCMALLOC in viewer builds, this is the place.
-# set ON or OFF as desired.
-set (USE_TCMALLOC OFF)
-
-if (USESYSTEMLIBS)
- include(FindGooglePerfTools)
-else (USESYSTEMLIBS)
- if (WINDOWS)
- if (USE_TCMALLOC)
- use_prebuilt_binary(gperftools)
- set(TCMALLOC_LIBRARIES
- debug libtcmalloc_minimal-debug
- optimized libtcmalloc_minimal)
- set(TCMALLOC_LINK_FLAGS "/INCLUDE:__tcmalloc")
- else (USE_TCMALLOC)
- set(TCMALLOC_LIBRARIES)
- set(TCMALLOC_LINK_FLAGS)
- endif (USE_TCMALLOC)
- set(GOOGLE_PERFTOOLS_FOUND "YES")
- endif (WINDOWS)
- if (LINUX)
- if (USE_TCMALLOC)
- use_prebuilt_binary(gperftools)
- set(TCMALLOC_LIBRARIES
- tcmalloc)
- else (USE_TCMALLOC)
- set(TCMALLOC_LIBRARIES)
- endif (USE_TCMALLOC)
- set(PROFILER_LIBRARIES profiler)
- set(GOOGLE_PERFTOOLS_INCLUDE_DIR
- ${LIBS_PREBUILT_DIR}/include)
- set(GOOGLE_PERFTOOLS_FOUND "YES")
- endif (LINUX)
-endif (USESYSTEMLIBS)
-
-if (GOOGLE_PERFTOOLS_FOUND)
- # XXX Disable temporarily, until we have compilation issues on 64-bit
- # Etch sorted.
- set(USE_GOOGLE_PERFTOOLS OFF CACHE BOOL "Build with Google PerfTools support.")
-endif (GOOGLE_PERFTOOLS_FOUND)
-
-if (WINDOWS)
- set(USE_GOOGLE_PERFTOOLS ON)
-endif (WINDOWS)
-
-if (USE_GOOGLE_PERFTOOLS)
- if (USE_TCMALLOC)
- set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1)
- else (USE_TCMALLOC)
- set(TCMALLOC_FLAG -ULL_USE_TCMALLOC)
- endif (USE_TCMALLOC)
-endif (USE_GOOGLE_PERFTOOLS)
-
-if (USE_GOOGLE_PERFTOOLS)
- include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR})
- set(GOOGLE_PERFTOOLS_LIBRARIES ${TCMALLOC_LIBRARIES} ${STACKTRACE_LIBRARIES} ${PROFILER_LIBRARIES})
-else (USE_GOOGLE_PERFTOOLS)
-endif (USE_GOOGLE_PERFTOOLS)
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index b50b4bcdb2..3e29297c58 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -4,7 +4,6 @@ include(APR)
include(Boost)
include(EXPAT)
include(ZLIB)
-include(GooglePerfTools)
set(LLCOMMON_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llcommon
@@ -34,8 +33,6 @@ else (LINUX)
${BOOST_SYSTEM_LIBRARY} )
endif (LINUX)
-# add_definitions(${TCMALLOC_FLAG})
-
set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a static library.")
if(LLCOMMON_LINK_SHARED)
add_definitions(-DLL_COMMON_LINK_SHARED=1)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index ba07a80f05..80af7ff2ab 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -18,7 +18,7 @@ else (USESYSTEMLIBS)
use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
- set (SDL_LIBRARY SDL directfb fusion direct)
+ set (SDL_LIBRARY SDL directfb fusion direct X11)
endif (LINUX)
endif (USESYSTEMLIBS)
diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake
new file mode 100644
index 0000000000..4472676fb4
--- /dev/null
+++ b/indra/cmake/LibVLCPlugin.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (USESYSTEMLIBS)
+ set(LIBVLCPLUGIN OFF CACHE BOOL
+ "LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
+else (USESYSTEMLIBS)
+ use_prebuilt_binary(vlc-bin)
+ set(LIBVLCPLUGIN ON CACHE BOOL
+ "LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
+ set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc)
+endif (USESYSTEMLIBS)
+
+if (WINDOWS)
+ set(VLC_PLUGIN_LIBRARIES
+ libvlc.lib
+ libvlccore.lib
+ )
+elseif (DARWIN)
+elseif (LINUX)
+ # Specify a full path to make sure we get a static link
+ set(VLC_PLUGIN_LIBRARIES
+ ${LIBS_PREBUILT_DIR}/lib/libvlc.a
+ ${LIBS_PREBUILT_DIR}/lib/libvlccore.a
+ )
+endif (WINDOWS)
diff --git a/indra/cmake/QuickTimePlugin.cmake b/indra/cmake/QuickTimePlugin.cmake
deleted file mode 100644
index c08e153ee3..0000000000
--- a/indra/cmake/QuickTimePlugin.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- cmake -*-
-
-if(INSTALL_PROPRIETARY)
- include(Prebuilt)
- if (WINDOWS)
- use_prebuilt_binary(quicktime)
- endif (WINDOWS)
-endif(INSTALL_PROPRIETARY)
-
-if (DARWIN)
- include(CMakeFindFrameworks)
- find_library(QUICKTIME_LIBRARY QuickTime)
-elseif (WINDOWS)
- set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK"
- CACHE PATH "Location of the QuickTime SDK.")
-
- find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient.lib
- PATHS
- ${ARCH_PREBUILT_DIRS_DEBUG}
- "${QUICKTIME_SDK_DIR}\\libraries"
- )
-
- find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient.lib
- PATHS
- ${ARCH_PREBUILT_DIRS_RELEASE}
- "${QUICKTIME_SDK_DIR}\\libraries"
- )
-
- if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
- set(QUICKTIME_LIBRARY
- optimized ${RELEASE_QUICKTIME_LIBRARY}
- debug ${DEBUG_QUICKTIME_LIBRARY}
- )
-
- endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
-
- include_directories(
- ${LIBS_PREBUILT_DIR}/include/quicktime
- "${QUICKTIME_SDK_DIR}\\CIncludes"
- )
-endif (DARWIN)
-
-mark_as_advanced(QUICKTIME_LIBRARY)
-
-if (QUICKTIME_LIBRARY)
- set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.")
-endif (QUICKTIME_LIBRARY)
-
diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake
index 31174209a3..77fd505df3 100644
--- a/indra/cmake/UI.cmake
+++ b/indra/cmake/UI.cmake
@@ -32,9 +32,9 @@ if (USESYSTEMLIBS)
add_definitions(${${pkg}_CFLAGS_OTHERS})
endforeach(pkg)
else (USESYSTEMLIBS)
- if (LINUX OR WINDOWS)
+ if (LINUX)
use_prebuilt_binary(gtk-atk-pango-glib)
- endif (LINUX OR WINDOWS)
+ endif (LINUX)
if (LINUX)
set(UI_LIBRARIES
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 63e296b556..3d0cb0a3c9 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -60,46 +60,55 @@ if (NOT CMAKE_BUILD_TYPE)
"Build type. One of: Debug Release RelWithDebInfo" FORCE)
endif (NOT CMAKE_BUILD_TYPE)
+# If someone has specified an address size, use that to determine the
+# architecture. Otherwise, let the architecture specify the address size.
+if (ADDRESS_SIZE EQUAL 32)
+ #message(STATUS "ADDRESS_SIZE is 32")
+ set(ARCH i686)
+elseif (ADDRESS_SIZE EQUAL 64)
+ #message(STATUS "ADDRESS_SIZE is 64")
+ set(ARCH x86_64)
+else (ADDRESS_SIZE EQUAL 32)
+ #message(STATUS "ADDRESS_SIZE is UNRECOGNIZED: '${ADDRESS_SIZE}'")
+ # Use Python's platform.machine() since uname -m isn't available everywhere.
+ # Even if you can assume cygwin uname -m, the answer depends on whether
+ # you're running 32-bit cygwin or 64-bit cygwin! But even 32-bit Python will
+ # report a 64-bit processor.
+ execute_process(COMMAND
+ "${PYTHON_EXECUTABLE}" "-c"
+ "import platform; print platform.machine()"
+ OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
+ # We expect values of the form i386, i686, x86_64, AMD64.
+ # In CMake, expressing ARCH.endswith('64') is awkward:
+ string(LENGTH "${ARCH}" ARCH_LENGTH)
+ math(EXPR ARCH_LEN_2 "${ARCH_LENGTH} - 2")
+ string(SUBSTRING "${ARCH}" ${ARCH_LEN_2} 2 ARCH_LAST_2)
+ if (ARCH_LAST_2 STREQUAL 64)
+ #message(STATUS "ARCH is detected as 64; ARCH is ${ARCH}")
+ set(ADDRESS_SIZE 64)
+ else ()
+ #message(STATUS "ARCH is detected as 32; ARCH is ${ARCH}")
+ set(ADDRESS_SIZE 32)
+ endif ()
+endif (ADDRESS_SIZE EQUAL 32)
+
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(WINDOWS ON BOOL FORCE)
- set(ARCH i686)
set(LL_ARCH ${ARCH}_win32)
set(LL_ARCH_DIR ${ARCH}-win32)
- set(WORD_SIZE 32)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(LINUX ON BOOl FORCE)
- # If someone has specified a word size, use that to determine the
- # architecture. Otherwise, let the architecture specify the word size.
- if (WORD_SIZE EQUAL 32)
- #message(STATUS "WORD_SIZE is 32")
- set(ARCH i686)
- elseif (WORD_SIZE EQUAL 64)
- #message(STATUS "WORD_SIZE is 64")
- set(ARCH x86_64)
- else (WORD_SIZE EQUAL 32)
- #message(STATUS "WORD_SIZE is UNDEFINED")
- execute_process(COMMAND uname -m COMMAND sed s/i.86/i686/
- OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (ARCH STREQUAL x86_64)
- #message(STATUS "ARCH is detected as 64; ARCH is ${ARCH}")
- set(WORD_SIZE 64)
- else (ARCH STREQUAL x86_64)
- #message(STATUS "ARCH is detected as 32; ARCH is ${ARCH}")
- set(WORD_SIZE 32)
- endif (ARCH STREQUAL x86_64)
- endif (WORD_SIZE EQUAL 32)
-
- if (WORD_SIZE EQUAL 32)
+ if (ADDRESS_SIZE EQUAL 32)
set(DEB_ARCHITECTURE i386)
set(FIND_LIBRARY_USE_LIB64_PATHS OFF)
set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib32 ${CMAKE_SYSTEM_LIBRARY_PATH})
- else (WORD_SIZE EQUAL 32)
+ else (ADDRESS_SIZE EQUAL 32)
set(DEB_ARCHITECTURE amd64)
set(FIND_LIBRARY_USE_LIB64_PATHS ON)
- endif (WORD_SIZE EQUAL 32)
+ endif (ADDRESS_SIZE EQUAL 32)
execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH
RESULT_VARIABLE DPKG_RESULT
@@ -140,18 +149,15 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS ssse3)
- set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++")
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
- # Build only for i386 by default, system default on MacOSX 10.6+ is x86_64
- if (NOT CMAKE_OSX_ARCHITECTURES)
- set(CMAKE_OSX_ARCHITECTURES "i386")
- endif (NOT CMAKE_OSX_ARCHITECTURES)
+ set(CMAKE_OSX_ARCHITECTURES "${ARCH}")
+ string(REPLACE "i686" "i386" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
+ string(REPLACE "AMD64" "x86_64" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
- set(ARCH ${CMAKE_OSX_ARCHITECTURES})
set(LL_ARCH ${ARCH}_darwin)
set(LL_ARCH_DIR universal-darwin)
- set(WORD_SIZE 32)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Default deploy grid
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index 32aa08a2b7..9f9ca6c39c 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1,3 +1,4 @@
2014-02-25 10:34
+
diff --git a/indra/lib/python/indra/base/__init__.py b/indra/lib/python/indra/base/__init__.py
deleted file mode 100755
index 2904fd3380..0000000000
--- a/indra/lib/python/indra/base/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"""\
-@file __init__.py
-@brief Initialization file for the indra.base module.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
diff --git a/indra/lib/python/indra/base/cllsd_test.py b/indra/lib/python/indra/base/cllsd_test.py
deleted file mode 100755
index 1f06898ffd..0000000000
--- a/indra/lib/python/indra/base/cllsd_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/python
-##
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-from indra.base import llsd, lluuid
-from datetime import datetime
-import cllsd
-import time, sys
-
-class myint(int):
- pass
-
-values = (
- '&<>',
- u'\u81acj',
- llsd.uri('http://foo<'),
- lluuid.UUID(),
- llsd.LLSD(['thing']),
- 1,
- myint(31337),
- sys.maxint + 10,
- llsd.binary('foo'),
- [],
- {},
- {u'f&\u1212': 3},
- 3.1,
- True,
- None,
- datetime.fromtimestamp(time.time()),
- )
-
-def valuator(values):
- for v in values:
- yield v
-
-longvalues = () # (values, list(values), iter(values), valuator(values))
-
-for v in values + longvalues:
- print '%r => %r' % (v, cllsd.llsd_to_xml(v))
-
-a = [[{'a':3}]] * 1000000
-
-s = time.time()
-print hash(cllsd.llsd_to_xml(a))
-e = time.time()
-t1 = e - s
-print t1
-
-s = time.time()
-print hash(llsd.LLSDXMLFormatter()._format(a))
-e = time.time()
-t2 = e - s
-print t2
-
-print 'Speedup:', t2 / t1
diff --git a/indra/lib/python/indra/base/config.py b/indra/lib/python/indra/base/config.py
deleted file mode 100755
index adafa29b51..0000000000
--- a/indra/lib/python/indra/base/config.py
+++ /dev/null
@@ -1,266 +0,0 @@
-"""\
-@file config.py
-@brief Utility module for parsing and accessing the indra.xml config file.
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import copy
-import errno
-import os
-import traceback
-import time
-import types
-
-from os.path import dirname, getmtime, join, realpath
-from indra.base import llsd
-
-_g_config = None
-
-class IndraConfig(object):
- """
- IndraConfig loads a 'indra' xml configuration file
- and loads into memory. This representation in memory
- can get updated to overwrite values or add new values.
-
- The xml configuration file is considered a live file and changes
- to the file are checked and reloaded periodically. If a value had
- been overwritten via the update or set method, the loaded values
- from the file are ignored (the values from the update/set methods
- override)
- """
- def __init__(self, indra_config_file):
- self._indra_config_file = indra_config_file
- self._reload_check_interval = 30 # seconds
- self._last_check_time = 0
- self._last_mod_time = 0
-
- self._config_overrides = {}
- self._config_file_dict = {}
- self._combined_dict = {}
-
- self._load()
-
- def _load(self):
- # if you initialize the IndraConfig with None, no attempt
- # is made to load any files
- if self._indra_config_file is None:
- return
-
- config_file = open(self._indra_config_file)
- self._config_file_dict = llsd.parse(config_file.read())
- self._combine_dictionaries()
- config_file.close()
-
- self._last_mod_time = self._get_last_modified_time()
- self._last_check_time = time.time() # now
-
- def _get_last_modified_time(self):
- """
- Returns the mtime (last modified time) of the config file,
- if such exists.
- """
- if self._indra_config_file is not None:
- return os.path.getmtime(self._indra_config_file)
-
- return 0
-
- def _combine_dictionaries(self):
- self._combined_dict = {}
- self._combined_dict.update(self._config_file_dict)
- self._combined_dict.update(self._config_overrides)
-
- def _reload_if_necessary(self):
- now = time.time()
-
- if (now - self._last_check_time) > self._reload_check_interval:
- self._last_check_time = now
- try:
- modtime = self._get_last_modified_time()
- if modtime > self._last_mod_time:
- self._load()
- except OSError, e:
- if e.errno == errno.ENOENT: # file not found
- # someone messed with our internal state
- # or removed the file
-
- print 'WARNING: Configuration file has been removed ' + (self._indra_config_file)
- print 'Disabling reloading of configuration file.'
-
- traceback.print_exc()
-
- self._indra_config_file = None
- self._last_check_time = 0
- self._last_mod_time = 0
- else:
- raise # pass the exception along to the caller
-
- def __getitem__(self, key):
- self._reload_if_necessary()
-
- return self._combined_dict[key]
-
- def get(self, key, default = None):
- try:
- return self.__getitem__(key)
- except KeyError:
- return default
-
- def __setitem__(self, key, value):
- """
- Sets the value of the config setting of key to be newval
-
- Once any key/value pair is changed via the set method,
- that key/value pair will remain set with that value until
- change via the update or set method
- """
- self._config_overrides[key] = value
- self._combine_dictionaries()
-
- def set(self, key, newval):
- return self.__setitem__(key, newval)
-
- def update(self, new_conf):
- """
- Load an XML file and apply its map as overrides or additions
- to the existing config. Update can be a file or a dict.
-
- Once any key/value pair is changed via the update method,
- that key/value pair will remain set with that value until
- change via the update or set method
- """
- if isinstance(new_conf, dict):
- overrides = new_conf
- else:
- # assuming that it is a filename
- config_file = open(new_conf)
- overrides = llsd.parse(config_file.read())
- config_file.close()
-
- self._config_overrides.update(overrides)
- self._combine_dictionaries()
-
- def as_dict(self):
- """
- Returns immutable copy of the IndraConfig as a dictionary
- """
- return copy.deepcopy(self._combined_dict)
-
-def load(config_xml_file = None):
- global _g_config
-
- load_default_files = config_xml_file is None
- if load_default_files:
- ## going from:
- ## "/opt/linden/indra/lib/python/indra/base/config.py"
- ## to:
- ## "/opt/linden/etc/indra.xml"
- config_xml_file = realpath(
- dirname(realpath(__file__)) + "../../../../../../etc/indra.xml")
-
- try:
- _g_config = IndraConfig(config_xml_file)
- except IOError:
- # Failure to load passed in file
- # or indra.xml default file
- if load_default_files:
- try:
- config_xml_file = realpath(
- dirname(realpath(__file__)) + "../../../../../../etc/globals.xml")
- _g_config = IndraConfig(config_xml_file)
- return
- except IOError:
- # Failure to load globals.xml
- # fall to code below
- pass
-
- # Either failed to load passed in file
- # or failed to load all default files
- _g_config = IndraConfig(None)
-
-def dump(indra_xml_file, indra_cfg = None, update_in_mem=False):
- '''
- Dump config contents into a file
- Kindof reverse of load.
- Optionally takes a new config to dump.
- Does NOT update global config unless requested.
- '''
- global _g_config
-
- if not indra_cfg:
- if _g_config is None:
- return
-
- indra_cfg = _g_config.as_dict()
-
- if not indra_cfg:
- return
-
- config_file = open(indra_xml_file, 'w')
- _config_xml = llsd.format_xml(indra_cfg)
- config_file.write(_config_xml)
- config_file.close()
-
- if update_in_mem:
- update(indra_cfg)
-
-def update(new_conf):
- global _g_config
-
- if _g_config is None:
- # To keep with how this function behaved
- # previously, a call to update
- # before the global is defined
- # make a new global config which does not
- # load data from a file.
- _g_config = IndraConfig(None)
-
- return _g_config.update(new_conf)
-
-def get(key, default = None):
- global _g_config
-
- if _g_config is None:
- load()
-
- return _g_config.get(key, default)
-
-def set(key, newval):
- """
- Sets the value of the config setting of key to be newval
-
- Once any key/value pair is changed via the set method,
- that key/value pair will remain set with that value until
- change via the update or set method or program termination
- """
- global _g_config
-
- if _g_config is None:
- _g_config = IndraConfig(None)
-
- _g_config.set(key, newval)
-
-def get_config():
- global _g_config
- return _g_config
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
deleted file mode 100755
index 4527b115f9..0000000000
--- a/indra/lib/python/indra/base/llsd.py
+++ /dev/null
@@ -1,1052 +0,0 @@
-"""\
-@file llsd.py
-@brief Types as well as parsing and formatting functions for handling LLSD.
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import datetime
-import base64
-import string
-import struct
-import time
-import types
-import re
-
-from indra.util.fastest_elementtree import ElementTreeError, fromstring
-from indra.base import lluuid
-
-# cllsd.c in server/server-1.25 has memory leaks,
-# so disabling cllsd for now
-#try:
-# import cllsd
-#except ImportError:
-# cllsd = None
-cllsd = None
-
-int_regex = re.compile(r"[-+]?\d+")
-real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?")
-alpha_regex = re.compile(r"[a-zA-Z]+")
-date_regex = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T"
- r"(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})"
- r"(?P<second_float>(\.\d+)?)Z")
-#date: d"YYYY-MM-DDTHH:MM:SS.FFFFFFZ"
-
-class LLSDParseError(Exception):
- pass
-
-class LLSDSerializationError(TypeError):
- pass
-
-
-class binary(str):
- pass
-
-class uri(str):
- pass
-
-
-BOOL_TRUE = ('1', '1.0', 'true')
-BOOL_FALSE = ('0', '0.0', 'false', '')
-
-
-def format_datestr(v):
- """ Formats a datetime or date object into the string format shared by xml and notation serializations."""
- if hasattr(v, 'microsecond'):
- return v.isoformat() + 'Z'
- else:
- return v.strftime('%Y-%m-%dT%H:%M:%SZ')
-
-def parse_datestr(datestr):
- """Parses a datetime object from the string format shared by xml and notation serializations."""
- if datestr == "":
- return datetime.datetime(1970, 1, 1)
-
- match = re.match(date_regex, datestr)
- if not match:
- raise LLSDParseError("invalid date string '%s'." % datestr)
-
- year = int(match.group('year'))
- month = int(match.group('month'))
- day = int(match.group('day'))
- hour = int(match.group('hour'))
- minute = int(match.group('minute'))
- second = int(match.group('second'))
- seconds_float = match.group('second_float')
- microsecond = 0
- if seconds_float:
- microsecond = int(float('0' + seconds_float) * 1e6)
- return datetime.datetime(year, month, day, hour, minute, second, microsecond)
-
-
-def bool_to_python(node):
- val = node.text or ''
- if val in BOOL_TRUE:
- return True
- else:
- return False
-
-def int_to_python(node):
- val = node.text or ''
- if not val.strip():
- return 0
- return int(val)
-
-def real_to_python(node):
- val = node.text or ''
- if not val.strip():
- return 0.0
- return float(val)
-
-def uuid_to_python(node):
- return lluuid.UUID(node.text)
-
-def str_to_python(node):
- return node.text or ''
-
-def bin_to_python(node):
- return binary(base64.decodestring(node.text or ''))
-
-def date_to_python(node):
- val = node.text or ''
- if not val:
- val = "1970-01-01T00:00:00Z"
- return parse_datestr(val)
-
-
-def uri_to_python(node):
- val = node.text or ''
- if not val:
- return None
- return uri(val)
-
-def map_to_python(node):
- result = {}
- for index in range(len(node))[::2]:
- result[node[index].text] = to_python(node[index+1])
- return result
-
-def array_to_python(node):
- return [to_python(child) for child in node]
-
-
-NODE_HANDLERS = dict(
- undef=lambda x: None,
- boolean=bool_to_python,
- integer=int_to_python,
- real=real_to_python,
- uuid=uuid_to_python,
- string=str_to_python,
- binary=bin_to_python,
- date=date_to_python,
- uri=uri_to_python,
- map=map_to_python,
- array=array_to_python,
- )
-
-def to_python(node):
- return NODE_HANDLERS[node.tag](node)
-
-class Nothing(object):
- pass
-
-
-class LLSDXMLFormatter(object):
- def __init__(self):
- self.type_map = {
- type(None) : self.UNDEF,
- bool : self.BOOLEAN,
- int : self.INTEGER,
- long : self.INTEGER,
- float : self.REAL,
- lluuid.UUID : self.UUID,
- binary : self.BINARY,
- str : self.STRING,
- unicode : self.STRING,
- uri : self.URI,
- datetime.datetime : self.DATE,
- datetime.date : self.DATE,
- list : self.ARRAY,
- tuple : self.ARRAY,
- types.GeneratorType : self.ARRAY,
- dict : self.MAP,
- LLSD : self.LLSD
- }
-
- def elt(self, name, contents=None):
- if(contents is None or contents is ''):
- return "<%s />" % (name,)
- else:
- if type(contents) is unicode:
- contents = contents.encode('utf-8')
- return "<%s>%s</%s>" % (name, contents, name)
-
- def xml_esc(self, v):
- if type(v) is unicode:
- v = v.encode('utf-8')
- return v.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
-
- def LLSD(self, v):
- return self.generate(v.thing)
- def UNDEF(self, v):
- return self.elt('undef')
- def BOOLEAN(self, v):
- if v:
- return self.elt('boolean', 'true')
- else:
- return self.elt('boolean', 'false')
- def INTEGER(self, v):
- return self.elt('integer', v)
- def REAL(self, v):
- return self.elt('real', v)
- def UUID(self, v):
- if(v.isNull()):
- return self.elt('uuid')
- else:
- return self.elt('uuid', v)
- def BINARY(self, v):
- return self.elt('binary', base64.encodestring(v))
- def STRING(self, v):
- return self.elt('string', self.xml_esc(v))
- def URI(self, v):
- return self.elt('uri', self.xml_esc(str(v)))
- def DATE(self, v):
- return self.elt('date', format_datestr(v))
- def ARRAY(self, v):
- return self.elt('array', ''.join([self.generate(item) for item in v]))
- def MAP(self, v):
- return self.elt(
- 'map',
- ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
- for key, value in v.items()]))
-
- typeof = type
- def generate(self, something):
- t = self.typeof(something)
- if self.type_map.has_key(t):
- return self.type_map[t](something)
- else:
- raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % (
- t, something))
-
- def _format(self, something):
- return '<?xml version="1.0" ?>' + self.elt("llsd", self.generate(something))
-
- def format(self, something):
- if cllsd:
- return cllsd.llsd_to_xml(something)
- return self._format(something)
-
-_g_xml_formatter = None
-def format_xml(something):
- global _g_xml_formatter
- if _g_xml_formatter is None:
- _g_xml_formatter = LLSDXMLFormatter()
- return _g_xml_formatter.format(something)
-
-class LLSDXMLPrettyFormatter(LLSDXMLFormatter):
- def __init__(self, indent_atom = None):
- # Call the super class constructor so that we have the type map
- super(LLSDXMLPrettyFormatter, self).__init__()
-
- # Override the type map to use our specialized formatters to
- # emit the pretty output.
- self.type_map[list] = self.PRETTY_ARRAY
- self.type_map[tuple] = self.PRETTY_ARRAY
- self.type_map[types.GeneratorType] = self.PRETTY_ARRAY,
- self.type_map[dict] = self.PRETTY_MAP
-
- # Private data used for indentation.
- self._indent_level = 1
- if indent_atom is None:
- self._indent_atom = ' '
- else:
- self._indent_atom = indent_atom
-
- def _indent(self):
- "Return an indentation based on the atom and indentation level."
- return self._indent_atom * self._indent_level
-
- def PRETTY_ARRAY(self, v):
- rv = []
- rv.append('<array>\n')
- self._indent_level = self._indent_level + 1
- rv.extend(["%s%s\n" %
- (self._indent(),
- self.generate(item))
- for item in v])
- self._indent_level = self._indent_level - 1
- rv.append(self._indent())
- rv.append('</array>')
- return ''.join(rv)
-
- def PRETTY_MAP(self, v):
- rv = []
- rv.append('<map>\n')
- self._indent_level = self._indent_level + 1
- keys = v.keys()
- keys.sort()
- rv.extend(["%s%s\n%s%s\n" %
- (self._indent(),
- self.elt('key', key),
- self._indent(),
- self.generate(v[key]))
- for key in keys])
- self._indent_level = self._indent_level - 1
- rv.append(self._indent())
- rv.append('</map>')
- return ''.join(rv)
-
- def format(self, something):
- data = []
- data.append('<?xml version="1.0" ?>\n<llsd>')
- data.append(self.generate(something))
- data.append('</llsd>\n')
- return '\n'.join(data)
-
-def format_pretty_xml(something):
- """@brief Serialize a python object as 'pretty' llsd xml.
-
- The output conforms to the LLSD DTD, unlike the output from the
- standard python xml.dom DOM::toprettyxml() method which does not
- preserve significant whitespace.
- This function is not necessarily suited for serializing very large
- objects. It is not optimized by the cllsd module, and sorts on
- dict (llsd map) keys alphabetically to ease human reading.
- """
- return LLSDXMLPrettyFormatter().format(something)
-
-class LLSDNotationFormatter(object):
- def __init__(self):
- self.type_map = {
- type(None) : self.UNDEF,
- bool : self.BOOLEAN,
- int : self.INTEGER,
- long : self.INTEGER,
- float : self.REAL,
- lluuid.UUID : self.UUID,
- binary : self.BINARY,
- str : self.STRING,
- unicode : self.STRING,
- uri : self.URI,
- datetime.datetime : self.DATE,
- datetime.date : self.DATE,
- list : self.ARRAY,
- tuple : self.ARRAY,
- types.GeneratorType : self.ARRAY,
- dict : self.MAP,
- LLSD : self.LLSD
- }
-
- def LLSD(self, v):
- return self.generate(v.thing)
- def UNDEF(self, v):
- return '!'
- def BOOLEAN(self, v):
- if v:
- return 'true'
- else:
- return 'false'
- def INTEGER(self, v):
- return "i%s" % v
- def REAL(self, v):
- return "r%s" % v
- def UUID(self, v):
- return "u%s" % v
- def BINARY(self, v):
- return 'b64"' + base64.encodestring(v) + '"'
- def STRING(self, v):
- if isinstance(v, unicode):
- v = v.encode('utf-8')
- return "'%s'" % v.replace("\\", "\\\\").replace("'", "\\'")
- def URI(self, v):
- return 'l"%s"' % str(v).replace("\\", "\\\\").replace('"', '\\"')
- def DATE(self, v):
- return 'd"%s"' % format_datestr(v)
- def ARRAY(self, v):
- return "[%s]" % ','.join([self.generate(item) for item in v])
- def MAP(self, v):
- def fix(key):
- if isinstance(key, unicode):
- return key.encode('utf-8')
- return key
- return "{%s}" % ','.join(["'%s':%s" % (fix(key).replace("\\", "\\\\").replace("'", "\\'"), self.generate(value))
- for key, value in v.items()])
-
- def generate(self, something):
- t = type(something)
- handler = self.type_map.get(t)
- if handler:
- return handler(something)
- else:
- try:
- return self.ARRAY(iter(something))
- except TypeError:
- raise LLSDSerializationError(
- "Cannot serialize unknown type: %s (%s)" % (t, something))
-
- def format(self, something):
- return self.generate(something)
-
-def format_notation(something):
- return LLSDNotationFormatter().format(something)
-
-def _hex_as_nybble(hex):
- if (hex >= '0') and (hex <= '9'):
- return ord(hex) - ord('0')
- elif (hex >= 'a') and (hex <='f'):
- return 10 + ord(hex) - ord('a')
- elif (hex >= 'A') and (hex <='F'):
- return 10 + ord(hex) - ord('A');
-
-class LLSDBinaryParser(object):
- def __init__(self):
- pass
-
- def parse(self, buffer, ignore_binary = False):
- """
- This is the basic public interface for parsing.
-
- @param buffer the binary data to parse in an indexable sequence.
- @param ignore_binary parser throws away data in llsd binary nodes.
- @return returns a python object.
- """
- self._buffer = buffer
- self._index = 0
- self._keep_binary = not ignore_binary
- return self._parse()
-
- def _parse(self):
- cc = self._buffer[self._index]
- self._index += 1
- if cc == '{':
- return self._parse_map()
- elif cc == '[':
- return self._parse_array()
- elif cc == '!':
- return None
- elif cc == '0':
- return False
- elif cc == '1':
- return True
- elif cc == 'i':
- # 'i' = integer
- idx = self._index
- self._index += 4
- return struct.unpack("!i", self._buffer[idx:idx+4])[0]
- elif cc == ('r'):
- # 'r' = real number
- idx = self._index
- self._index += 8
- return struct.unpack("!d", self._buffer[idx:idx+8])[0]
- elif cc == 'u':
- # 'u' = uuid
- idx = self._index
- self._index += 16
- return lluuid.uuid_bits_to_uuid(self._buffer[idx:idx+16])
- elif cc == 's':
- # 's' = string
- return self._parse_string()
- elif cc in ("'", '"'):
- # delimited/escaped string
- return self._parse_string_delim(cc)
- elif cc == 'l':
- # 'l' = uri
- return uri(self._parse_string())
- elif cc == ('d'):
- # 'd' = date in seconds since epoch
- idx = self._index
- self._index += 8
- seconds = struct.unpack("!d", self._buffer[idx:idx+8])[0]
- return datetime.datetime.fromtimestamp(seconds)
- elif cc == 'b':
- binary = self._parse_string()
- if self._keep_binary:
- return binary
- # *NOTE: maybe have a binary placeholder which has the
- # length.
- return None
- else:
- raise LLSDParseError("invalid binary token at byte %d: %d" % (
- self._index - 1, ord(cc)))
-
- def _parse_map(self):
- rv = {}
- size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0]
- self._index += 4
- count = 0
- cc = self._buffer[self._index]
- self._index += 1
- key = ''
- while (cc != '}') and (count < size):
- if cc == 'k':
- key = self._parse_string()
- elif cc in ("'", '"'):
- key = self._parse_string_delim(cc)
- else:
- raise LLSDParseError("invalid map key at byte %d." % (
- self._index - 1,))
- value = self._parse()
- rv[key] = value
- count += 1
- cc = self._buffer[self._index]
- self._index += 1
- if cc != '}':
- raise LLSDParseError("invalid map close token at byte %d." % (
- self._index,))
- return rv
-
- def _parse_array(self):
- rv = []
- size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0]
- self._index += 4
- count = 0
- cc = self._buffer[self._index]
- while (cc != ']') and (count < size):
- rv.append(self._parse())
- count += 1
- cc = self._buffer[self._index]
- if cc != ']':
- raise LLSDParseError("invalid array close token at byte %d." % (
- self._index,))
- self._index += 1
- return rv
-
- def _parse_string(self):
- size = struct.unpack("!i", self._buffer[self._index:self._index+4])[0]
- self._index += 4
- rv = self._buffer[self._index:self._index+size]
- self._index += size
- return rv
-
- def _parse_string_delim(self, delim):
- list = []
- found_escape = False
- found_hex = False
- found_digit = False
- byte = 0
- while True:
- cc = self._buffer[self._index]
- self._index += 1
- if found_escape:
- if found_hex:
- if found_digit:
- found_escape = False
- found_hex = False
- found_digit = False
- byte <<= 4
- byte |= _hex_as_nybble(cc)
- list.append(chr(byte))
- byte = 0
- else:
- found_digit = True
- byte = _hex_as_nybble(cc)
- elif cc == 'x':
- found_hex = True
- else:
- if cc == 'a':
- list.append('\a')
- elif cc == 'b':
- list.append('\b')
- elif cc == 'f':
- list.append('\f')
- elif cc == 'n':
- list.append('\n')
- elif cc == 'r':
- list.append('\r')
- elif cc == 't':
- list.append('\t')
- elif cc == 'v':
- list.append('\v')
- else:
- list.append(cc)
- found_escape = False
- elif cc == '\\':
- found_escape = True
- elif cc == delim:
- break
- else:
- list.append(cc)
- return ''.join(list)
-
-class LLSDNotationParser(object):
- """ Parse LLSD notation:
- map: { string:object, string:object }
- array: [ object, object, object ]
- undef: !
- boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
- integer: i####
- real: r####
- uuid: u####
- string: "g\'day" | 'have a "nice" day' | s(size)"raw data"
- uri: l"escaped"
- date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
- binary: b##"ff3120ab1" | b(size)"raw data"
- """
- def __init__(self):
- pass
-
- def parse(self, buffer, ignore_binary = False):
- """
- This is the basic public interface for parsing.
-
- @param buffer the notation string to parse.
- @param ignore_binary parser throws away data in llsd binary nodes.
- @return returns a python object.
- """
- if buffer == "":
- return False
-
- self._buffer = buffer
- self._index = 0
- return self._parse()
-
- def _parse(self):
- cc = self._buffer[self._index]
- self._index += 1
- if cc == '{':
- return self._parse_map()
- elif cc == '[':
- return self._parse_array()
- elif cc == '!':
- return None
- elif cc == '0':
- return False
- elif cc == '1':
- return True
- elif cc in ('F', 'f'):
- self._skip_alpha()
- return False
- elif cc in ('T', 't'):
- self._skip_alpha()
- return True
- elif cc == 'i':
- # 'i' = integer
- return self._parse_integer()
- elif cc == ('r'):
- # 'r' = real number
- return self._parse_real()
- elif cc == 'u':
- # 'u' = uuid
- return self._parse_uuid()
- elif cc in ("'", '"', 's'):
- return self._parse_string(cc)
- elif cc == 'l':
- # 'l' = uri
- delim = self._buffer[self._index]
- self._index += 1
- val = uri(self._parse_string(delim))
- if len(val) == 0:
- return None
- return val
- elif cc == ('d'):
- # 'd' = date in seconds since epoch
- return self._parse_date()
- elif cc == 'b':
- return self._parse_binary()
- else:
- raise LLSDParseError("invalid token at index %d: %d" % (
- self._index - 1, ord(cc)))
-
- def _parse_binary(self):
- i = self._index
- if self._buffer[i:i+2] == '64':
- q = self._buffer[i+2]
- e = self._buffer.find(q, i+3)
- try:
- return base64.decodestring(self._buffer[i+3:e])
- finally:
- self._index = e + 1
- else:
- raise LLSDParseError('random horrible binary format not supported')
-
- def _parse_map(self):
- """ map: { string:object, string:object } """
- rv = {}
- cc = self._buffer[self._index]
- self._index += 1
- key = ''
- found_key = False
- while (cc != '}'):
- if not found_key:
- if cc in ("'", '"', 's'):
- key = self._parse_string(cc)
- found_key = True
- elif cc.isspace() or cc == ',':
- cc = self._buffer[self._index]
- self._index += 1
- else:
- raise LLSDParseError("invalid map key at byte %d." % (
- self._index - 1,))
- elif cc.isspace() or cc == ':':
- cc = self._buffer[self._index]
- self._index += 1
- continue
- else:
- self._index += 1
- value = self._parse()
- rv[key] = value
- found_key = False
- cc = self._buffer[self._index]
- self._index += 1
-
- return rv
-
- def _parse_array(self):
- """ array: [ object, object, object ] """
- rv = []
- cc = self._buffer[self._index]
- while (cc != ']'):
- if cc.isspace() or cc == ',':
- self._index += 1
- cc = self._buffer[self._index]
- continue
- rv.append(self._parse())
- cc = self._buffer[self._index]
-
- if cc != ']':
- raise LLSDParseError("invalid array close token at index %d." % (
- self._index,))
- self._index += 1
- return rv
-
- def _parse_uuid(self):
- match = re.match(lluuid.UUID.uuid_regex, self._buffer[self._index:])
- if not match:
- raise LLSDParseError("invalid uuid token at index %d." % self._index)
-
- (start, end) = match.span()
- start += self._index
- end += self._index
- self._index = end
- return lluuid.UUID(self._buffer[start:end])
-
- def _skip_alpha(self):
- match = re.match(alpha_regex, self._buffer[self._index:])
- if match:
- self._index += match.end()
-
- def _parse_date(self):
- delim = self._buffer[self._index]
- self._index += 1
- datestr = self._parse_string(delim)
- return parse_datestr(datestr)
-
- def _parse_real(self):
- match = re.match(real_regex, self._buffer[self._index:])
- if not match:
- raise LLSDParseError("invalid real token at index %d." % self._index)
-
- (start, end) = match.span()
- start += self._index
- end += self._index
- self._index = end
- return float( self._buffer[start:end] )
-
- def _parse_integer(self):
- match = re.match(int_regex, self._buffer[self._index:])
- if not match:
- raise LLSDParseError("invalid integer token at index %d." % self._index)
-
- (start, end) = match.span()
- start += self._index
- end += self._index
- self._index = end
- return int( self._buffer[start:end] )
-
- def _parse_string(self, delim):
- """ string: "g\'day" | 'have a "nice" day' | s(size)"raw data" """
- rv = ""
-
- if delim in ("'", '"'):
- rv = self._parse_string_delim(delim)
- elif delim == 's':
- rv = self._parse_string_raw()
- else:
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- return rv
-
-
- def _parse_string_delim(self, delim):
- """ string: "g'day 'un" | 'have a "nice" day' """
- list = []
- found_escape = False
- found_hex = False
- found_digit = False
- byte = 0
- while True:
- cc = self._buffer[self._index]
- self._index += 1
- if found_escape:
- if found_hex:
- if found_digit:
- found_escape = False
- found_hex = False
- found_digit = False
- byte <<= 4
- byte |= _hex_as_nybble(cc)
- list.append(chr(byte))
- byte = 0
- else:
- found_digit = True
- byte = _hex_as_nybble(cc)
- elif cc == 'x':
- found_hex = True
- else:
- if cc == 'a':
- list.append('\a')
- elif cc == 'b':
- list.append('\b')
- elif cc == 'f':
- list.append('\f')
- elif cc == 'n':
- list.append('\n')
- elif cc == 'r':
- list.append('\r')
- elif cc == 't':
- list.append('\t')
- elif cc == 'v':
- list.append('\v')
- else:
- list.append(cc)
- found_escape = False
- elif cc == '\\':
- found_escape = True
- elif cc == delim:
- break
- else:
- list.append(cc)
- return ''.join(list)
-
- def _parse_string_raw(self):
- """ string: s(size)"raw data" """
- # Read the (size) portion.
- cc = self._buffer[self._index]
- self._index += 1
- if cc != '(':
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- rparen = self._buffer.find(')', self._index)
- if rparen == -1:
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- size = int(self._buffer[self._index:rparen])
-
- self._index = rparen + 1
- delim = self._buffer[self._index]
- self._index += 1
- if delim not in ("'", '"'):
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- rv = self._buffer[self._index:(self._index + size)]
- self._index += size
- cc = self._buffer[self._index]
- self._index += 1
- if cc != delim:
- raise LLSDParseError("invalid string token at index %d." % self._index)
-
- return rv
-
-def format_binary(something):
- return '<?llsd/binary?>\n' + _format_binary_recurse(something)
-
-def _format_binary_recurse(something):
- def _format_list(something):
- array_builder = []
- array_builder.append('[' + struct.pack('!i', len(something)))
- for item in something:
- array_builder.append(_format_binary_recurse(item))
- array_builder.append(']')
- return ''.join(array_builder)
-
- if something is None:
- return '!'
- elif isinstance(something, LLSD):
- return _format_binary_recurse(something.thing)
- elif isinstance(something, bool):
- if something:
- return '1'
- else:
- return '0'
- elif isinstance(something, (int, long)):
- return 'i' + struct.pack('!i', something)
- elif isinstance(something, float):
- return 'r' + struct.pack('!d', something)
- elif isinstance(something, lluuid.UUID):
- return 'u' + something._bits
- elif isinstance(something, binary):
- return 'b' + struct.pack('!i', len(something)) + something
- elif isinstance(something, str):
- return 's' + struct.pack('!i', len(something)) + something
- elif isinstance(something, unicode):
- something = something.encode('utf-8')
- return 's' + struct.pack('!i', len(something)) + something
- elif isinstance(something, uri):
- return 'l' + struct.pack('!i', len(something)) + something
- elif isinstance(something, datetime.datetime):
- seconds_since_epoch = time.mktime(something.timetuple())
- return 'd' + struct.pack('!d', seconds_since_epoch)
- elif isinstance(something, (list, tuple)):
- return _format_list(something)
- elif isinstance(something, dict):
- map_builder = []
- map_builder.append('{' + struct.pack('!i', len(something)))
- for key, value in something.items():
- if isinstance(key, unicode):
- key = key.encode('utf-8')
- map_builder.append('k' + struct.pack('!i', len(key)) + key)
- map_builder.append(_format_binary_recurse(value))
- map_builder.append('}')
- return ''.join(map_builder)
- else:
- try:
- return _format_list(list(something))
- except TypeError:
- raise LLSDSerializationError(
- "Cannot serialize unknown type: %s (%s)" %
- (type(something), something))
-
-
-def parse_binary(binary):
- if binary.startswith('<?llsd/binary?>'):
- just_binary = binary.split('\n', 1)[1]
- else:
- just_binary = binary
- return LLSDBinaryParser().parse(just_binary)
-
-def parse_xml(something):
- try:
- return to_python(fromstring(something)[0])
- except ElementTreeError, err:
- raise LLSDParseError(*err.args)
-
-def parse_notation(something):
- return LLSDNotationParser().parse(something)
-
-def parse(something):
- try:
- something = string.lstrip(something) #remove any pre-trailing whitespace
- if something.startswith('<?llsd/binary?>'):
- return parse_binary(something)
- # This should be better.
- elif something.startswith('<'):
- return parse_xml(something)
- else:
- return parse_notation(something)
- except KeyError, e:
- raise Exception('LLSD could not be parsed: %s' % (e,))
-
-class LLSD(object):
- def __init__(self, thing=None):
- self.thing = thing
-
- def __str__(self):
- return self.toXML(self.thing)
-
- parse = staticmethod(parse)
- toXML = staticmethod(format_xml)
- toPrettyXML = staticmethod(format_pretty_xml)
- toBinary = staticmethod(format_binary)
- toNotation = staticmethod(format_notation)
-
-
-undef = LLSD(None)
-
-XML_MIME_TYPE = 'application/llsd+xml'
-BINARY_MIME_TYPE = 'application/llsd+binary'
-
-# register converters for llsd in mulib, if it is available
-try:
- from mulib import stacked, mu
- stacked.NoProducer() # just to exercise stacked
- mu.safe_load(None) # just to exercise mu
-except:
- # mulib not available, don't print an error message since this is normal
- pass
-else:
- mu.add_parser(parse, XML_MIME_TYPE)
- mu.add_parser(parse, 'application/llsd+binary')
-
- def llsd_convert_xml(llsd_stuff, request):
- request.write(format_xml(llsd_stuff))
-
- def llsd_convert_binary(llsd_stuff, request):
- request.write(format_binary(llsd_stuff))
-
- for typ in [LLSD, dict, list, tuple, str, int, long, float, bool, unicode, type(None)]:
- stacked.add_producer(typ, llsd_convert_xml, XML_MIME_TYPE)
- stacked.add_producer(typ, llsd_convert_xml, 'application/xml')
- stacked.add_producer(typ, llsd_convert_xml, 'text/xml')
-
- stacked.add_producer(typ, llsd_convert_binary, 'application/llsd+binary')
-
- stacked.add_producer(LLSD, llsd_convert_xml, '*/*')
-
- # in case someone is using the legacy mu.xml wrapper, we need to
- # tell mu to produce application/xml or application/llsd+xml
- # (based on the accept header) from raw xml. Phoenix 2008-07-21
- stacked.add_producer(mu.xml, mu.produce_raw, XML_MIME_TYPE)
- stacked.add_producer(mu.xml, mu.produce_raw, 'application/xml')
-
-
-
-# mulib wsgi stuff
-# try:
-# from mulib import mu, adapters
-#
-# # try some known attributes from mulib to be ultra-sure we've imported it
-# mu.get_current
-# adapters.handlers
-# except:
-# # mulib not available, don't print an error message since this is normal
-# pass
-# else:
-# def llsd_xml_handler(content_type):
-# def handle_llsd_xml(env, start_response):
-# llsd_stuff, _ = mu.get_current(env)
-# result = format_xml(llsd_stuff)
-# start_response("200 OK", [('Content-Type', content_type)])
-# env['mu.negotiated_type'] = content_type
-# yield result
-# return handle_llsd_xml
-#
-# def llsd_binary_handler(content_type):
-# def handle_llsd_binary(env, start_response):
-# llsd_stuff, _ = mu.get_current(env)
-# result = format_binary(llsd_stuff)
-# start_response("200 OK", [('Content-Type', content_type)])
-# env['mu.negotiated_type'] = content_type
-# yield result
-# return handle_llsd_binary
-#
-# adapters.DEFAULT_PARSERS[XML_MIME_TYPE] = parse
-
-# for typ in [LLSD, dict, list, tuple, str, int, float, bool, unicode, type(None)]:
-# for content_type in (XML_MIME_TYPE, 'application/xml'):
-# adapters.handlers.set_handler(typ, llsd_xml_handler(content_type), content_type)
-#
-# adapters.handlers.set_handler(typ, llsd_binary_handler(BINARY_MIME_TYPE), BINARY_MIME_TYPE)
-#
-# adapters.handlers.set_handler(LLSD, llsd_xml_handler(XML_MIME_TYPE), '*/*')
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
deleted file mode 100755
index 7413ffe10d..0000000000
--- a/indra/lib/python/indra/base/lluuid.py
+++ /dev/null
@@ -1,319 +0,0 @@
-"""\
-@file lluuid.py
-@brief UUID parser/generator.
-
-$LicenseInfo:firstyear=2004&license=mit$
-
-Copyright (c) 2004-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import random, socket, string, time, re
-import uuid
-try:
- # Python 2.6
- from hashlib import md5
-except ImportError:
- # Python 2.5 and earlier
- from md5 import new as md5
-
-def _int2binstr(i,l):
- s=''
- for a in range(l):
- s=chr(i&0xFF)+s
- i>>=8
- return s
-
-def _binstr2int(s):
- i = long(0)
- for c in s:
- i = (i<<8) + ord(c)
- return i
-
-class UUID(object):
- """
- A class which represents a 16 byte integer. Stored as a 16 byte 8
- bit character string.
-
- The string version is to be of the form:
- AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex)
- where A=network address, B=timestamp, C=random.
- """
-
- NULL_STR = "00000000-0000-0000-0000-000000000000"
-
- # the UUIDREGEX_STRING is helpful for parsing UUID's in text
- hex_wildcard = r"[0-9a-fA-F]"
- word = hex_wildcard + r"{4,4}-"
- long_word = hex_wildcard + r"{8,8}-"
- very_long_word = hex_wildcard + r"{12,12}"
- UUID_REGEX_STRING = long_word + word + word + word + very_long_word
- uuid_regex = re.compile(UUID_REGEX_STRING)
-
- rand = random.Random()
- ip = ''
- try:
- ip = socket.gethostbyname(socket.gethostname())
- except(socket.gaierror, socket.error):
- # no ip address, so just default to somewhere in 10.x.x.x
- ip = '10'
- for i in range(3):
- ip += '.' + str(rand.randrange(1,254))
- hexip = ''.join(["%04x" % long(i) for i in ip.split('.')])
- lastid = ''
-
- def __init__(self, possible_uuid=None):
- """
- Initialize to first valid UUID in argument (if a string),
- or to null UUID if none found or argument is not supplied.
-
- If the argument is a UUID, the constructed object will be a copy of it.
- """
- self._bits = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- if possible_uuid is None:
- return
-
- if isinstance(possible_uuid, type(self)):
- self.set(possible_uuid)
- return
-
- uuid_match = UUID.uuid_regex.search(possible_uuid)
- if uuid_match:
- uuid_string = uuid_match.group()
- s = string.replace(uuid_string, '-', '')
- self._bits = _int2binstr(string.atol(s[:8],16),4) + \
- _int2binstr(string.atol(s[8:16],16),4) + \
- _int2binstr(string.atol(s[16:24],16),4) + \
- _int2binstr(string.atol(s[24:],16),4)
-
- def __len__(self):
- """
- Used by the len() builtin.
- """
- return 36
-
- def __nonzero__(self):
- return self._bits != "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-
- def __str__(self):
- uuid_string = self.toString()
- return uuid_string
-
- __repr__ = __str__
-
- def __getitem__(self, index):
- return str(self)[index]
-
- def __eq__(self, other):
- if isinstance(other, (str, unicode)):
- return other == str(self)
- return self._bits == getattr(other, '_bits', '')
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __le__(self, other):
- return self._bits <= other._bits
-
- def __ge__(self, other):
- return self._bits >= other._bits
-
- def __lt__(self, other):
- return self._bits < other._bits
-
- def __gt__(self, other):
- return self._bits > other._bits
-
- def __hash__(self):
- return hash(self._bits)
-
- def set(self, uuid):
- self._bits = uuid._bits
-
- def setFromString(self, uuid_string):
- """
- Given a string version of a uuid, set self bits
- appropriately. Returns self.
- """
- s = string.replace(uuid_string, '-', '')
- self._bits = _int2binstr(string.atol(s[:8],16),4) + \
- _int2binstr(string.atol(s[8:16],16),4) + \
- _int2binstr(string.atol(s[16:24],16),4) + \
- _int2binstr(string.atol(s[24:],16),4)
- return self
-
- def setFromMemoryDump(self, gdb_string):
- """
- We expect to get gdb_string as four hex units. eg:
- 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
- Which will be translated to:
- db547d14-1b3f4bc3-9b984f71-d22f890a
- Returns self.
- """
- s = string.replace(gdb_string, '0x', '')
- s = string.replace(s, ' ', '')
- t = ''
- for i in range(8,40,8):
- for j in range(0,8,2):
- t = t + s[i-j-2:i-j]
- self.setFromString(t)
-
- def toString(self):
- """
- Return as a string matching the LL standard
- AAAAAAAA-AAAA-BBBB-BBBB-BBBBBBCCCCCC (a 128-bit number in hex)
- where A=network address, B=timestamp, C=random.
- """
- return uuid_bits_to_string(self._bits)
-
- def getAsString(self):
- """
- Return a different string representation of the form
- AAAAAAAA-AAAABBBB-BBBBBBBB-BBCCCCCC (a 128-bit number in hex)
- where A=network address, B=timestamp, C=random.
- """
- i1 = _binstr2int(self._bits[0:4])
- i2 = _binstr2int(self._bits[4:8])
- i3 = _binstr2int(self._bits[8:12])
- i4 = _binstr2int(self._bits[12:16])
- return '%08lx-%08lx-%08lx-%08lx' % (i1,i2,i3,i4)
-
- def generate(self):
- """
- Generate a new uuid. This algorithm is slightly different
- from c++ implementation for portability reasons.
- Returns self.
- """
- m = md5()
- m.update(uuid.uuid1().bytes)
- self._bits = m.digest()
- return self
-
- def isNull(self):
- """
- Returns 1 if the uuid is null - ie, equal to default uuid.
- """
- return (self._bits == "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
-
- def xor(self, rhs):
- """
- xors self with rhs.
- """
- v1 = _binstr2int(self._bits[0:4]) ^ _binstr2int(rhs._bits[0:4])
- v2 = _binstr2int(self._bits[4:8]) ^ _binstr2int(rhs._bits[4:8])
- v3 = _binstr2int(self._bits[8:12]) ^ _binstr2int(rhs._bits[8:12])
- v4 = _binstr2int(self._bits[12:16]) ^ _binstr2int(rhs._bits[12:16])
- self._bits = _int2binstr(v1,4) + \
- _int2binstr(v2,4) + \
- _int2binstr(v3,4) + \
- _int2binstr(v4,4)
-
-
-# module-level null constant
-NULL = UUID()
-
-def printTranslatedMemory(four_hex_uints):
- """
- We expect to get the string as four hex units. eg:
- 0x147d54db 0xc34b3f1b 0x714f989b 0x0a892fd2
- Which will be translated to:
- db547d14-1b3f4bc3-9b984f71-d22f890a
- """
- uuid = UUID()
- uuid.setFromMemoryDump(four_hex_uints)
- print uuid.toString()
-
-def isUUID(id_str):
- """
- This function returns:
- - 1 if the string passed is a UUID
- - 0 is the string passed is not a UUID
- - None if it neither of the if's below is satisfied
- """
- if not id_str or len(id_str) < 5 or len(id_str) > 36:
- return 0
-
- if isinstance(id_str, UUID) or UUID.uuid_regex.match(id_str):
- return 1
-
- return None
-
-def isPossiblyID(id_str):
- """
- This function returns 1 if the string passed has some uuid-like
- characteristics. Otherwise returns 0.
- """
-
- is_uuid = isUUID(id_str)
- if is_uuid is not None:
- return is_uuid
-
- # build a string which matches every character.
- hex_wildcard = r"[0-9a-fA-F]"
- chars = len(id_str)
- next = min(chars, 8)
- matcher = hex_wildcard+"{"+str(next)+","+str(next)+"}"
- chars = chars - next
- if chars > 0:
- matcher = matcher + "-"
- chars = chars - 1
- for block in range(3):
- next = max(min(chars, 4), 0)
- if next:
- matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}"
- chars = chars - next
- if chars > 0:
- matcher = matcher + "-"
- chars = chars - 1
- if chars > 0:
- next = min(chars, 12)
- matcher = matcher + hex_wildcard+"{"+str(next)+","+str(next)+"}"
- #print matcher
- uuid_matcher = re.compile(matcher)
- if uuid_matcher.match(id_str):
- return 1
- return 0
-
-def uuid_bits_to_string(bits):
- i1 = _binstr2int(bits[0:4])
- i2 = _binstr2int(bits[4:6])
- i3 = _binstr2int(bits[6:8])
- i4 = _binstr2int(bits[8:10])
- i5 = _binstr2int(bits[10:12])
- i6 = _binstr2int(bits[12:16])
- return '%08lx-%04lx-%04lx-%04lx-%04lx%08lx' % (i1,i2,i3,i4,i5,i6)
-
-def uuid_bits_to_uuid(bits):
- return UUID(uuid_bits_to_string(bits))
-
-
-try:
- from mulib import stacked
- stacked.NoProducer() # just to exercise stacked
-except:
- #print "Couldn't import mulib.stacked, not registering UUID converter"
- pass
-else:
- def convertUUID(uuid, req):
- req.write(str(uuid))
-
- stacked.add_producer(UUID, convertUUID, "*/*")
- stacked.add_producer(UUID, convertUUID, "text/html")
diff --git a/indra/lib/python/indra/base/metrics.py b/indra/lib/python/indra/base/metrics.py
deleted file mode 100755
index ff8380265f..0000000000
--- a/indra/lib/python/indra/base/metrics.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""\
-@file metrics.py
-@author Phoenix
-@date 2007-11-27
-@brief simple interface for logging metrics
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys
-try:
- import syslog
-except ImportError:
- # Windows
- import sys
- class syslog(object):
- # wrap to a lame syslog for windows
- _logfp = sys.stderr
- def syslog(msg):
- _logfp.write(msg)
- if not msg.endswith('\n'):
- _logfp.write('\n')
- syslog = staticmethod(syslog)
-
-from indra.base.llsd import format_notation
-
-def record_metrics(table, stats):
- "Write a standard metrics log"
- _log("LLMETRICS", table, stats)
-
-def record_event(table, data):
- "Write a standard logmessage log"
- _log("LLLOGMESSAGE", table, data)
-
-def set_destination(dest):
- """Set the destination of metrics logs for this process.
-
- If you do not call this function prior to calling a logging
- method, that function will open sys.stdout as a destination.
- Attempts to set dest to None will throw a RuntimeError.
- @param dest a file-like object which will be the destination for logs."""
- if dest is None:
- raise RuntimeError("Attempt to unset metrics destination.")
- global _destination
- _destination = dest
-
-def destination():
- """Get the destination of the metrics logs for this process.
- Returns None if no destination is set"""
- global _destination
- return _destination
-
-class SysLogger(object):
- "A file-like object which writes to syslog."
- def __init__(self, ident='indra', logopt = None, facility = None):
- try:
- if logopt is None:
- logopt = syslog.LOG_CONS | syslog.LOG_PID
- if facility is None:
- facility = syslog.LOG_LOCAL0
- syslog.openlog(ident, logopt, facility)
- import atexit
- atexit.register(syslog.closelog)
- except AttributeError:
- # No syslog module on Windows
- pass
-
- def write(str):
- syslog.syslog(str)
- write = staticmethod(write)
-
- def flush():
- pass
- flush = staticmethod(flush)
-
-#
-# internal API
-#
-_sequence_id = 0
-_destination = None
-
-def _next_id():
- global _sequence_id
- next = _sequence_id
- _sequence_id += 1
- return next
-
-def _dest():
- global _destination
- if _destination is None:
- # this default behavior is documented in the metrics functions above.
- _destination = sys.stdout
- return _destination
-
-def _log(header, table, data):
- log_line = "%s (%d) %s %s" \
- % (header, _next_id(), table, format_notation(data))
- dest = _dest()
- dest.write(log_line)
- dest.flush()
diff --git a/indra/lib/python/indra/ipc/httputil.py b/indra/lib/python/indra/ipc/httputil.py
deleted file mode 100755
index d53f34a771..0000000000
--- a/indra/lib/python/indra/ipc/httputil.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/python
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-
-import warnings
-
-warnings.warn("indra.ipc.httputil has been deprecated; use eventlet.httpc instead", DeprecationWarning, 2)
-
-from eventlet.httpc import *
-
-
-makeConnection = make_connection
diff --git a/indra/lib/python/indra/ipc/llsdhttp.py b/indra/lib/python/indra/ipc/llsdhttp.py
deleted file mode 100755
index cbe8ee1eca..0000000000
--- a/indra/lib/python/indra/ipc/llsdhttp.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""\
-@file llsdhttp.py
-@brief Functions to ease moving llsd over http
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import os.path
-import os
-import urlparse
-
-from indra.base import llsd
-
-from eventlet import httpc
-
-suite = httpc.HttpSuite(llsd.format_xml, llsd.parse, 'application/llsd+xml')
-delete = suite.delete
-delete_ = suite.delete_
-get = suite.get
-get_ = suite.get_
-head = suite.head
-head_ = suite.head_
-post = suite.post
-post_ = suite.post_
-put = suite.put
-put_ = suite.put_
-request = suite.request
-request_ = suite.request_
-
-# import every httpc error exception into our namespace for convenience
-for x in httpc.status_to_error_map.itervalues():
- globals()[x.__name__] = x
-ConnectionError = httpc.ConnectionError
-Retriable = httpc.Retriable
-
-for x in (httpc.ConnectionError,):
- globals()[x.__name__] = x
-
-
-def postFile(url, filename):
- f = open(filename)
- body = f.read()
- f.close()
- llsd_body = llsd.parse(body)
- return post_(url, llsd_body)
-
-
-# deprecated in favor of get_
-def getStatus(url, use_proxy=False):
- status, _headers, _body = get_(url, use_proxy=use_proxy)
- return status
-
-# deprecated in favor of put_
-def putStatus(url, data):
- status, _headers, _body = put_(url, data)
- return status
-
-# deprecated in favor of delete_
-def deleteStatus(url):
- status, _headers, _body = delete_(url)
- return status
-
-# deprecated in favor of post_
-def postStatus(url, data):
- status, _headers, _body = post_(url, data)
- return status
-
-
-def postFileStatus(url, filename):
- status, _headers, body = postFile(url, filename)
- return status, body
-
-
-def getFromSimulator(path, use_proxy=False):
- return get('http://' + simulatorHostAndPort + path, use_proxy=use_proxy)
-
-
-def postToSimulator(path, data=None):
- return post('http://' + simulatorHostAndPort + path, data)
diff --git a/indra/lib/python/indra/ipc/mysql_pool.py b/indra/lib/python/indra/ipc/mysql_pool.py
deleted file mode 100755
index e5855a3091..0000000000
--- a/indra/lib/python/indra/ipc/mysql_pool.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""\
-@file mysql_pool.py
-@brief Thin wrapper around eventlet.db_pool that chooses MySQLdb and Tpool.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import MySQLdb
-from eventlet import db_pool
-
-class DatabaseConnector(db_pool.DatabaseConnector):
- def __init__(self, credentials, *args, **kwargs):
- super(DatabaseConnector, self).__init__(MySQLdb, credentials,
- conn_pool=db_pool.ConnectionPool,
- *args, **kwargs)
-
- # get is extended relative to eventlet.db_pool to accept a port argument
- def get(self, host, dbname, port=3306):
- key = (host, dbname, port)
- if key not in self._databases:
- new_kwargs = self._kwargs.copy()
- new_kwargs['db'] = dbname
- new_kwargs['host'] = host
- new_kwargs['port'] = port
- new_kwargs.update(self.credentials_for(host))
- dbpool = ConnectionPool(*self._args, **new_kwargs)
- self._databases[key] = dbpool
-
- return self._databases[key]
-
-class ConnectionPool(db_pool.TpooledConnectionPool):
- """A pool which gives out saranwrapped MySQLdb connections from a pool
- """
-
- def __init__(self, *args, **kwargs):
- super(ConnectionPool, self).__init__(MySQLdb, *args, **kwargs)
-
- def get(self):
- conn = super(ConnectionPool, self).get()
- # annotate the connection object with the details on the
- # connection; this is used elsewhere to check that you haven't
- # suddenly changed databases in midstream while making a
- # series of queries on a connection.
- arg_names = ['host','user','passwd','db','port','unix_socket','conv','connect_timeout',
- 'compress', 'named_pipe', 'init_command', 'read_default_file', 'read_default_group',
- 'cursorclass', 'use_unicode', 'charset', 'sql_mode', 'client_flag', 'ssl',
- 'local_infile']
- # you could have constructed this connectionpool with a mix of
- # keyword and non-keyword arguments, but we want to annotate
- # the connection object with a dict so it's easy to check
- # against so here we are converting the list of non-keyword
- # arguments (in self._args) into a dict of keyword arguments,
- # and merging that with the actual keyword arguments
- # (self._kwargs). The arg_names variable lists the
- # constructor arguments for MySQLdb Connection objects.
- converted_kwargs = dict([ (arg_names[i], arg) for i, arg in enumerate(self._args) ])
- converted_kwargs.update(self._kwargs)
- conn.connection_parameters = converted_kwargs
- return conn
-
diff --git a/indra/lib/python/indra/ipc/russ.py b/indra/lib/python/indra/ipc/russ.py
deleted file mode 100755
index ac780f128b..0000000000
--- a/indra/lib/python/indra/ipc/russ.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""\
-@file russ.py
-@brief Recursive URL Substitution Syntax helpers
-@author Phoenix
-
-Many details on how this should work is available on the wiki:
-https://wiki.secondlife.com/wiki/Recursive_URL_Substitution_Syntax
-
-Adding features to this should be reflected in that page in the
-implementations section.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import urllib
-from indra.ipc import llsdhttp
-
-class UnbalancedBraces(Exception):
- pass
-
-class UnknownDirective(Exception):
- pass
-
-class BadDirective(Exception):
- pass
-
-def format_value_for_path(value):
- if type(value) in [list, tuple]:
- # *NOTE: treat lists as unquoted path components so that the quoting
- # doesn't get out-of-hand. This is a workaround for the fact that
- # russ always quotes, even if the data it's given is already quoted,
- # and it's not safe to simply unquote a path directly, so if we want
- # russ to substitute urls parts inside other url parts we always
- # have to do so via lists of unquoted path components.
- return '/'.join([urllib.quote(str(item)) for item in value])
- else:
- return urllib.quote(str(value))
-
-def format(format_str, context):
- """@brief Format format string according to rules for RUSS.
-@see https://osiris.lindenlab.com/mediawiki/index.php/Recursive_URL_Substitution_Syntax
-@param format_str The input string to format.
-@param context A map used for string substitutions.
-@return Returns the formatted string. If no match, the braces remain intact.
-"""
- while True:
- #print "format_str:", format_str
- all_matches = _find_sub_matches(format_str)
- if not all_matches:
- break
- substitutions = 0
- while True:
- matches = all_matches.pop()
- # we work from right to left to make sure we do not
- # invalidate positions earlier in format_str
- matches.reverse()
- for pos in matches:
- # Use index since _find_sub_matches should have raised
- # an exception, and failure to find now is an exception.
- end = format_str.index('}', pos)
- #print "directive:", format_str[pos+1:pos+5]
- if format_str[pos + 1] == '$':
- value = context[format_str[pos + 2:end]]
- if value is not None:
- value = format_value_for_path(value)
- elif format_str[pos + 1] == '%':
- value = _build_query_string(
- context.get(format_str[pos + 2:end]))
- elif format_str[pos+1:pos+5] == 'http' or format_str[pos+1:pos+5] == 'file':
- value = _fetch_url_directive(format_str[pos + 1:end])
- else:
- raise UnknownDirective, format_str[pos:end + 1]
- if value is not None:
- format_str = format_str[:pos]+str(value)+format_str[end+1:]
- substitutions += 1
-
- # If there were any substitutions at this depth, re-parse
- # since this may have revealed new things to substitute
- if substitutions:
- break
- if not all_matches:
- break
-
- # If there were no substitutions at all, and we have exhausted
- # the possible matches, bail.
- if not substitutions:
- break
- return format_str
-
-def _find_sub_matches(format_str):
- """@brief Find all of the substitution matches.
-@param format_str the RUSS conformant format string.
-@return Returns an array of depths of arrays of positional matches in input.
-"""
- depth = 0
- matches = []
- for pos in range(len(format_str)):
- if format_str[pos] == '{':
- depth += 1
- if not len(matches) == depth:
- matches.append([])
- matches[depth - 1].append(pos)
- continue
- if format_str[pos] == '}':
- depth -= 1
- continue
- if not depth == 0:
- raise UnbalancedBraces, format_str
- return matches
-
-def _build_query_string(query_dict):
- """\
- @breif given a dict, return a query string. utility wrapper for urllib.
- @param query_dict input query dict
- @returns Returns an urlencoded query string including leading '?'.
- """
- if query_dict:
- keys = query_dict.keys()
- keys.sort()
- def stringize(value):
- if type(value) in (str,unicode):
- return value
- else:
- return str(value)
- query_list = [urllib.quote(str(key)) + '=' + urllib.quote(stringize(query_dict[key])) for key in keys]
- return '?' + '&'.join(query_list)
- else:
- return ''
-
-def _fetch_url_directive(directive):
- "*FIX: This only supports GET"
- commands = directive.split('|')
- resource = llsdhttp.get(commands[0])
- if len(commands) == 3:
- resource = _walk_resource(resource, commands[2])
- return resource
-
-def _walk_resource(resource, path):
- path = path.split('/')
- for child in path:
- if not child:
- continue
- resource = resource[child]
- return resource
diff --git a/indra/lib/python/indra/ipc/servicebuilder.py b/indra/lib/python/indra/ipc/servicebuilder.py
deleted file mode 100755
index 0a0ce2b4e2..0000000000
--- a/indra/lib/python/indra/ipc/servicebuilder.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""\
-@file servicebuilder.py
-@author Phoenix
-@brief Class which will generate service urls.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-from indra.base import config
-from indra.ipc import llsdhttp
-from indra.ipc import russ
-
-# *NOTE: agent presence relies on this variable existing and being current, it is a huge hack
-services_config = {}
-try:
- services_config = llsdhttp.get(config.get('services-config'))
-except:
- pass
-
-_g_builder = None
-def _builder():
- global _g_builder
- if _g_builder is None:
- _g_builder = ServiceBuilder()
- return _g_builder
-
-def build(name, context={}, **kwargs):
- """ Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both!
-
- Example use:
- > context = {'channel':'Second Life Release', 'version':'1.18.2.0'}
- > servicebuilder.build('version-manager-version', context)
- 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
- > servicebuilder.build('version-manager-version', channel='Second Life Release', version='1.18.2.0')
- 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
- > servicebuilder.build('version-manager-version', context, version='1.18.1.2')
- 'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2'
- """
- global _g_builder
- if _g_builder is None:
- _g_builder = ServiceBuilder()
- return _g_builder.buildServiceURL(name, context, **kwargs)
-
-def build_path(name, context={}, **kwargs):
- context = context.copy() # shouldn't modify the caller's dictionary
- context.update(kwargs)
- return _builder().buildPath(name, context)
-
-class ServiceBuilder(object):
- def __init__(self, services_definition = services_config):
- """\
- @brief
- @brief Create a ServiceBuilder.
- @param services_definition Complete services definition, services.xml.
- """
- # no need to keep a copy of the services section of the
- # complete services definition, but it doesn't hurt much.
- self.services = services_definition['services']
- self.builders = {}
- for service in self.services:
- service_builder = service.get('service-builder')
- if not service_builder:
- continue
- if isinstance(service_builder, dict):
- # We will be constructing several builders
- for name, builder in service_builder.iteritems():
- full_builder_name = service['name'] + '-' + name
- self.builders[full_builder_name] = builder
- else:
- self.builders[service['name']] = service_builder
-
- def buildPath(self, name, context):
- """\
- @brief given the environment on construction, return a service path.
- @param name The name of the service.
- @param context A dict of name value lookups for the service.
- @returns Returns the
- """
- return russ.format(self.builders[name], context)
-
- def buildServiceURL(self, name, context={}, **kwargs):
- """\
- @brief given the environment on construction, return a service URL.
- @param name The name of the service.
- @param context A dict of name value lookups for the service.
- @param kwargs Any keyword arguments are treated as members of the
- context, this allows you to be all 31337 by writing shit like:
- servicebuilder.build('name', param=value)
- @returns Returns the
- """
- context = context.copy() # shouldn't modify the caller's dictionary
- context.update(kwargs)
- base_url = config.get('services-base-url')
- svc_path = russ.format(self.builders[name], context)
- return base_url + svc_path
-
-
-def on_in(query_name, host_key, schema_key):
- """\
- @brief Constructs an on/in snippet (for running named queries)
- from a schema name and two keys referencing values stored in
- indra.xml.
-
- @param query_name Name of the query.
- @param host_key Logical name of destination host. Will be
- looked up in indra.xml.
- @param schema_key Logical name of destination schema. Will
- be looked up in indra.xml.
- """
- return "on/config:%s/in/config:%s/%s" % (host_key.strip('/'),
- schema_key.strip('/'),
- query_name.lstrip('/'))
-
diff --git a/indra/lib/python/indra/ipc/siesta.py b/indra/lib/python/indra/ipc/siesta.py
deleted file mode 100755
index d867e71537..0000000000
--- a/indra/lib/python/indra/ipc/siesta.py
+++ /dev/null
@@ -1,468 +0,0 @@
-"""\
-@file siesta.py
-@brief A tiny llsd based RESTful web services framework
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-from indra.base import config
-from indra.base import llsd
-from webob import exc
-import webob
-import re, socket
-
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
-try:
- import cjson
- json_decode = cjson.decode
- json_encode = cjson.encode
- JsonDecodeError = cjson.DecodeError
- JsonEncodeError = cjson.EncodeError
-except ImportError:
- import simplejson
- json_decode = simplejson.loads
- json_encode = simplejson.dumps
- JsonDecodeError = ValueError
- JsonEncodeError = TypeError
-
-
-llsd_parsers = {
- 'application/json': json_decode,
- llsd.BINARY_MIME_TYPE: llsd.parse_binary,
- 'application/llsd+notation': llsd.parse_notation,
- llsd.XML_MIME_TYPE: llsd.parse_xml,
- 'application/xml': llsd.parse_xml,
- }
-
-
-def mime_type(content_type):
- '''Given a Content-Type header, return only the MIME type.'''
-
- return content_type.split(';', 1)[0].strip().lower()
-
-class BodyLLSD(object):
- '''Give a webob Request or Response an llsd based "content" property.
-
- Getting the content property parses the body, and caches the result.
-
- Setting the content property formats a payload, and the body property
- is set.'''
-
- def _llsd__get(self):
- '''Get, set, or delete the LLSD value stored in this object.'''
-
- try:
- return self._llsd
- except AttributeError:
- if not self.body:
- raise AttributeError('No llsd attribute has been set')
- else:
- mtype = mime_type(self.content_type)
- try:
- parser = llsd_parsers[mtype]
- except KeyError:
- raise exc.HTTPUnsupportedMediaType(
- 'Content type %s not supported' % mtype).exception
- try:
- self._llsd = parser(self.body)
- except (llsd.LLSDParseError, JsonDecodeError, TypeError), err:
- raise exc.HTTPBadRequest(
- 'Could not parse body: %r' % err.args).exception
- return self._llsd
-
- def _llsd__set(self, val):
- req = getattr(self, 'request', None)
- if req is not None:
- formatter, ctype = formatter_for_request(req)
- self.content_type = ctype
- else:
- formatter, ctype = formatter_for_mime_type(
- mime_type(self.content_type))
- self.body = formatter(val)
-
- def _llsd__del(self):
- if hasattr(self, '_llsd'):
- del self._llsd
-
- content = property(_llsd__get, _llsd__set, _llsd__del)
-
-
-class Response(webob.Response, BodyLLSD):
- '''Response class with LLSD support.
-
- A sensible default content type is used.
-
- Setting the llsd property also sets the body. Getting the llsd
- property parses the body if necessary.
-
- If you set the body property directly, the llsd property will be
- deleted.'''
-
- default_content_type = 'application/llsd+xml'
-
- def _body__set(self, body):
- if hasattr(self, '_llsd'):
- del self._llsd
- super(Response, self)._body__set(body)
-
- def cache_forever(self):
- self.cache_expires(86400 * 365)
-
- body = property(webob.Response._body__get, _body__set,
- webob.Response._body__del,
- webob.Response._body__get.__doc__)
-
-
-class Request(webob.Request, BodyLLSD):
- '''Request class with LLSD support.
-
- Sensible content type and accept headers are used by default.
-
- Setting the content property also sets the body. Getting the content
- property parses the body if necessary.
-
- If you set the body property directly, the content property will be
- deleted.'''
-
- default_content_type = 'application/llsd+xml'
- default_accept = ('application/llsd+xml; q=0.5, '
- 'application/llsd+notation; q=0.3, '
- 'application/llsd+binary; q=0.2, '
- 'application/xml; q=0.1, '
- 'application/json; q=0.0')
-
- def __init__(self, environ=None, *args, **kwargs):
- if environ is None:
- environ = {}
- else:
- environ = environ.copy()
- if 'CONTENT_TYPE' not in environ:
- environ['CONTENT_TYPE'] = self.default_content_type
- if 'HTTP_ACCEPT' not in environ:
- environ['HTTP_ACCEPT'] = self.default_accept
- super(Request, self).__init__(environ, *args, **kwargs)
-
- def _body__set(self, body):
- if hasattr(self, '_llsd'):
- del self._llsd
- super(Request, self)._body__set(body)
-
- def path_urljoin(self, *parts):
- return '/'.join([path_url.rstrip('/')] + list(parts))
-
- body = property(webob.Request._body__get, _body__set,
- webob.Request._body__del, webob.Request._body__get.__doc__)
-
- def create_response(self, content=None, status='200 OK',
- conditional_response=webob.NoDefault):
- resp = self.ResponseClass(status=status, request=self,
- conditional_response=conditional_response)
- resp.content = content
- return resp
-
- def curl(self):
- '''Create and fill out a pycurl easy object from this request.'''
-
- import pycurl
- c = pycurl.Curl()
- c.setopt(pycurl.URL, self.url())
- if self.headers:
- c.setopt(pycurl.HTTPHEADER,
- ['%s: %s' % (k, self.headers[k]) for k in self.headers])
- c.setopt(pycurl.FOLLOWLOCATION, True)
- c.setopt(pycurl.AUTOREFERER, True)
- c.setopt(pycurl.MAXREDIRS, 16)
- c.setopt(pycurl.NOSIGNAL, True)
- c.setopt(pycurl.READFUNCTION, self.body_file.read)
- c.setopt(pycurl.SSL_VERIFYHOST, 2)
-
- if self.method == 'POST':
- c.setopt(pycurl.POST, True)
- post301 = getattr(pycurl, 'POST301', None)
- if post301 is not None:
- # Added in libcurl 7.17.1.
- c.setopt(post301, True)
- elif self.method == 'PUT':
- c.setopt(pycurl.PUT, True)
- elif self.method != 'GET':
- c.setopt(pycurl.CUSTOMREQUEST, self.method)
- return c
-
-Request.ResponseClass = Response
-Response.RequestClass = Request
-
-
-llsd_formatters = {
- 'application/json': json_encode,
- 'application/llsd+binary': llsd.format_binary,
- 'application/llsd+notation': llsd.format_notation,
- 'application/llsd+xml': llsd.format_xml,
- 'application/xml': llsd.format_xml,
- }
-
-formatter_qualities = (
- ('application/llsd+xml', 1.0),
- ('application/llsd+notation', 0.5),
- ('application/llsd+binary', 0.4),
- ('application/xml', 0.3),
- ('application/json', 0.2),
- )
-
-def formatter_for_mime_type(mime_type):
- '''Return a formatter that encodes to the given MIME type.
-
- The result is a pair of function and MIME type.'''
- try:
- return llsd_formatters[mime_type], mime_type
- except KeyError:
- raise exc.HTTPInternalServerError(
- 'Could not use MIME type %r to format response' %
- mime_type).exception
-
-
-def formatter_for_request(req):
- '''Return a formatter that encodes to the preferred type of the client.
-
- The result is a pair of function and actual MIME type.'''
- ctype = req.accept.best_match(formatter_qualities)
- try:
- return llsd_formatters[ctype], ctype
- except KeyError:
- raise exc.HTTPNotAcceptable().exception
-
-
-def wsgi_adapter(func, environ, start_response):
- '''Adapt a Siesta callable to act as a WSGI application.'''
- # Process the request as appropriate.
- try:
- req = Request(environ)
- #print req.urlvars
- resp = func(req, **req.urlvars)
- if not isinstance(resp, webob.Response):
- try:
- formatter, ctype = formatter_for_request(req)
- resp = req.ResponseClass(formatter(resp), content_type=ctype)
- resp._llsd = resp
- except (JsonEncodeError, TypeError), err:
- resp = exc.HTTPInternalServerError(
- detail='Could not format response')
- except exc.HTTPException, e:
- resp = e
- except socket.error, e:
- resp = exc.HTTPInternalServerError(detail=e.args[1])
- return resp(environ, start_response)
-
-
-def llsd_callable(func):
- '''Turn a callable into a Siesta application.'''
-
- def replacement(environ, start_response):
- return wsgi_adapter(func, environ, start_response)
-
- return replacement
-
-
-def llsd_method(http_method, func):
- def replacement(environ, start_response):
- if environ['REQUEST_METHOD'] == http_method:
- return wsgi_adapter(func, environ, start_response)
- return exc.HTTPMethodNotAllowed()(environ, start_response)
-
- return replacement
-
-
-http11_methods = 'OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT'.split()
-http11_methods.sort()
-
-def llsd_class(cls):
- '''Turn a class into a Siesta application.
-
- A new instance is created for each request. A HTTP method FOO is
- turned into a call to the handle_foo method of the instance.'''
-
- def foo(req, **kwargs):
- instance = cls()
- method = req.method.lower()
- try:
- handler = getattr(instance, 'handle_' + method)
- except AttributeError:
- allowed = [m for m in http11_methods
- if hasattr(instance, 'handle_' + m.lower())]
- raise exc.HTTPMethodNotAllowed(
- headers={'Allow': ', '.join(allowed)}).exception
- #print "kwargs: ", kwargs
- return handler(req, **kwargs)
-
- def replacement(environ, start_response):
- return wsgi_adapter(foo, environ, start_response)
-
- return replacement
-
-
-def curl(reqs):
- import pycurl
-
- m = pycurl.CurlMulti()
- curls = [r.curl() for r in reqs]
- io = {}
- for c in curls:
- fp = StringIO()
- hdr = StringIO()
- c.setopt(pycurl.WRITEFUNCTION, fp.write)
- c.setopt(pycurl.HEADERFUNCTION, hdr.write)
- io[id(c)] = fp, hdr
- m.handles = curls
- try:
- while True:
- ret, num_handles = m.perform()
- if ret != pycurl.E_CALL_MULTI_PERFORM:
- break
- finally:
- m.close()
-
- for req, c in zip(reqs, curls):
- fp, hdr = io[id(c)]
- hdr.seek(0)
- status = hdr.readline().rstrip()
- headers = []
- name, values = None, None
-
- # XXX We don't currently handle bogus header data.
-
- for line in hdr.readlines():
- if not line[0].isspace():
- if name:
- headers.append((name, ' '.join(values)))
- name, value = line.strip().split(':', 1)
- value = [value]
- else:
- values.append(line.strip())
- if name:
- headers.append((name, ' '.join(values)))
-
- resp = c.ResponseClass(fp.getvalue(), status, headers, request=req)
-
-
-route_re = re.compile(r'''
- \{ # exact character "{"
- (\w*) # "config" or variable (restricted to a-z, 0-9, _)
- (?:([:~])([^}]+))? # optional :type or ~regex part
- \} # exact character "}"
- ''', re.VERBOSE)
-
-predefined_regexps = {
- 'uuid': r'[a-f0-9][a-f0-9-]{31,35}',
- 'int': r'\d+',
- 'host': r'[a-z0-9][a-z0-9\-\.]*',
- }
-
-def compile_route(route):
- fp = StringIO()
- last_pos = 0
- for match in route_re.finditer(route):
- #print "matches: ", match.groups()
- fp.write(re.escape(route[last_pos:match.start()]))
- var_name = match.group(1)
- sep = match.group(2)
- expr = match.group(3)
- if var_name == 'config':
- expr = re.escape(str(config.get(var_name)))
- else:
- if expr:
- if sep == ':':
- expr = predefined_regexps[expr]
- # otherwise, treat what follows '~' as a regexp
- else:
- expr = '[^/]+'
- if var_name != '':
- expr = '(?P<%s>%s)' % (var_name, expr)
- else:
- expr = '(%s)' % (expr,)
- fp.write(expr)
- last_pos = match.end()
- fp.write(re.escape(route[last_pos:]))
- compiled_route = '^%s$' % fp.getvalue()
- #print route, "->", compiled_route
- return compiled_route
-
-class Router(object):
- '''WSGI routing class. Parses a URL and hands off a request to
- some other WSGI application. If no suitable application is found,
- responds with a 404.'''
-
- def __init__(self):
- self._new_routes = []
- self._routes = []
- self._paths = []
-
- def add(self, route, app, methods=None):
- self._new_routes.append((route, app, methods))
-
- def _create_routes(self):
- for route, app, methods in self._new_routes:
- self._paths.append(route)
- self._routes.append(
- (re.compile(compile_route(route)),
- app,
- methods and dict.fromkeys(methods)))
- self._new_routes = []
-
- def __call__(self, environ, start_response):
- # load up the config from the config file. Only needs to be
- # done once per interpreter. This is the entry point of all
- # siesta applications, so this is where we trap it.
- _conf = config.get_config()
- if _conf is None:
- import os.path
- fname = os.path.join(
- environ.get('ll.config_dir', '/local/linden/etc'),
- 'indra.xml')
- config.load(fname)
-
- # proceed with handling the request
- self._create_routes()
- path_info = environ['PATH_INFO']
- request_method = environ['REQUEST_METHOD']
- allowed = []
- for regex, app, methods in self._routes:
- m = regex.match(path_info)
- if m:
- #print "groupdict:",m.groupdict()
- if not methods or request_method in methods:
- environ['paste.urlvars'] = m.groupdict()
- return app(environ, start_response)
- else:
- allowed += methods
- if allowed:
- allowed = dict.fromkeys(allows).keys()
- allowed.sort()
- resp = exc.HTTPMethodNotAllowed(
- headers={'Allow': ', '.join(allowed)})
- else:
- resp = exc.HTTPNotFound()
- return resp(environ, start_response)
diff --git a/indra/lib/python/indra/ipc/siesta_test.py b/indra/lib/python/indra/ipc/siesta_test.py
deleted file mode 100755
index a35eed2460..0000000000
--- a/indra/lib/python/indra/ipc/siesta_test.py
+++ /dev/null
@@ -1,235 +0,0 @@
-#!/usr/bin/python
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-from indra.base import llsd, lluuid
-from indra.ipc import siesta
-import datetime, math, unittest
-from webob import exc
-
-
-class ClassApp(object):
- def handle_get(self, req):
- pass
-
- def handle_post(self, req):
- return req.llsd
-
-
-def callable_app(req):
- if req.method == 'UNDERPANTS':
- raise exc.HTTPMethodNotAllowed()
- elif req.method == 'GET':
- return None
- return req.llsd
-
-
-class TestBase:
- def test_basic_get(self):
- req = siesta.Request.blank('/')
- self.assertEquals(req.get_response(self.server).body,
- llsd.format_xml(None))
-
- def test_bad_method(self):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'UNDERPANTS'
- self.assertEquals(req.get_response(self.server).status_int,
- exc.HTTPMethodNotAllowed.code)
-
- json_safe = {
- 'none': None,
- 'bool_true': True,
- 'bool_false': False,
- 'int_zero': 0,
- 'int_max': 2147483647,
- 'int_min': -2147483648,
- 'long_zero': 0,
- 'long_max': 2147483647L,
- 'long_min': -2147483648L,
- 'float_zero': 0,
- 'float': math.pi,
- 'float_huge': 3.14159265358979323846e299,
- 'str_empty': '',
- 'str': 'foo',
- u'unic\u1e51de_empty': u'',
- u'unic\u1e51de': u'\u1e4exx\u10480',
- }
- json_safe['array'] = json_safe.values()
- json_safe['tuple'] = tuple(json_safe.values())
- json_safe['dict'] = json_safe.copy()
-
- json_unsafe = {
- 'uuid_empty': lluuid.UUID(),
- 'uuid_full': lluuid.UUID('dc61ab0530200d7554d23510559102c1a98aab1b'),
- 'binary_empty': llsd.binary(),
- 'binary': llsd.binary('f\0\xff'),
- 'uri_empty': llsd.uri(),
- 'uri': llsd.uri('http://www.secondlife.com/'),
- 'datetime_empty': datetime.datetime(1970,1,1),
- 'datetime': datetime.datetime(1999,9,9,9,9,9),
- }
- json_unsafe.update(json_safe)
- json_unsafe['array'] = json_unsafe.values()
- json_unsafe['tuple'] = tuple(json_unsafe.values())
- json_unsafe['dict'] = json_unsafe.copy()
- json_unsafe['iter'] = iter(json_unsafe.values())
-
- def _test_client_content_type_good(self, content_type, ll):
- def run(ll):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'POST'
- req.content_type = content_type
- req.llsd = ll
- req.accept = content_type
- resp = req.get_response(self.server)
- self.assertEquals(resp.status_int, 200)
- return req, resp
-
- if False and isinstance(ll, dict):
- def fixup(v):
- if isinstance(v, float):
- return '%.5f' % v
- if isinstance(v, long):
- return int(v)
- if isinstance(v, (llsd.binary, llsd.uri)):
- return v
- if isinstance(v, (tuple, list)):
- return [fixup(i) for i in v]
- if isinstance(v, dict):
- return dict([(k, fixup(i)) for k, i in v.iteritems()])
- return v
- for k, v in ll.iteritems():
- l = [k, v]
- req, resp = run(l)
- self.assertEquals(fixup(resp.llsd), fixup(l))
-
- run(ll)
-
- def test_client_content_type_json_good(self):
- self._test_client_content_type_good('application/json', self.json_safe)
-
- def test_client_content_type_llsd_xml_good(self):
- self._test_client_content_type_good('application/llsd+xml',
- self.json_unsafe)
-
- def test_client_content_type_llsd_notation_good(self):
- self._test_client_content_type_good('application/llsd+notation',
- self.json_unsafe)
-
- def test_client_content_type_llsd_binary_good(self):
- self._test_client_content_type_good('application/llsd+binary',
- self.json_unsafe)
-
- def test_client_content_type_xml_good(self):
- self._test_client_content_type_good('application/xml',
- self.json_unsafe)
-
- def _test_client_content_type_bad(self, content_type):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'POST'
- req.body = '\0invalid nonsense under all encodings'
- req.content_type = content_type
- self.assertEquals(req.get_response(self.server).status_int,
- exc.HTTPBadRequest.code)
-
- def test_client_content_type_json_bad(self):
- self._test_client_content_type_bad('application/json')
-
- def test_client_content_type_llsd_xml_bad(self):
- self._test_client_content_type_bad('application/llsd+xml')
-
- def test_client_content_type_llsd_notation_bad(self):
- self._test_client_content_type_bad('application/llsd+notation')
-
- def test_client_content_type_llsd_binary_bad(self):
- self._test_client_content_type_bad('application/llsd+binary')
-
- def test_client_content_type_xml_bad(self):
- self._test_client_content_type_bad('application/xml')
-
- def test_client_content_type_bad(self):
- req = siesta.Request.blank('/')
- req.environ['REQUEST_METHOD'] = 'POST'
- req.body = 'XXX'
- req.content_type = 'application/nonsense'
- self.assertEquals(req.get_response(self.server).status_int,
- exc.HTTPUnsupportedMediaType.code)
-
- def test_request_default_content_type(self):
- req = siesta.Request.blank('/')
- self.assertEquals(req.content_type, req.default_content_type)
-
- def test_request_default_accept(self):
- req = siesta.Request.blank('/')
- from webob import acceptparse
- self.assertEquals(str(req.accept).replace(' ', ''),
- req.default_accept.replace(' ', ''))
-
- def test_request_llsd_auto_body(self):
- req = siesta.Request.blank('/')
- req.llsd = {'a': 2}
- self.assertEquals(req.body, '<?xml version="1.0" ?><llsd><map>'
- '<key>a</key><integer>2</integer></map></llsd>')
-
- def test_request_llsd_mod_body_changes_llsd(self):
- req = siesta.Request.blank('/')
- req.llsd = {'a': 2}
- req.body = '<?xml version="1.0" ?><llsd><integer>1337</integer></llsd>'
- self.assertEquals(req.llsd, 1337)
-
- def test_request_bad_llsd_fails(self):
- def crashme(ctype):
- def boom():
- class foo(object): pass
- req = siesta.Request.blank('/')
- req.content_type = ctype
- req.llsd = foo()
- for mime_type in siesta.llsd_parsers:
- self.assertRaises(TypeError, crashme(mime_type))
-
-
-class ClassServer(TestBase, unittest.TestCase):
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- self.server = siesta.llsd_class(ClassApp)
-
-
-class CallableServer(TestBase, unittest.TestCase):
- def __init__(self, *args, **kwargs):
- unittest.TestCase.__init__(self, *args, **kwargs)
- self.server = siesta.llsd_callable(callable_app)
-
-
-class RouterServer(unittest.TestCase):
- def test_router(self):
- def foo(req, quux):
- print quux
-
- r = siesta.Router()
- r.add('/foo/{quux:int}', siesta.llsd_callable(foo), methods=['GET'])
- req = siesta.Request.blank('/foo/33')
- req.get_response(r)
-
- req = siesta.Request.blank('/foo/bar')
- self.assertEquals(req.get_response(r).status_int,
- exc.HTTPNotFound.code)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/indra/lib/python/indra/ipc/webdav.py b/indra/lib/python/indra/ipc/webdav.py
deleted file mode 100755
index 98b8499b6a..0000000000
--- a/indra/lib/python/indra/ipc/webdav.py
+++ /dev/null
@@ -1,597 +0,0 @@
-"""
-@file webdav.py
-@brief Classes to make manipulation of a webdav store easier.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys, os, httplib, urlparse
-import socket, time
-import xml.dom.minidom
-import syslog
-# import signal
-
-__revision__ = '0'
-
-dav_debug = False
-
-
-# def urlsafe_b64decode (enc):
-# return base64.decodestring (enc.replace ('_', '/').replace ('-', '+'))
-
-# def urlsafe_b64encode (str):
-# return base64.encodestring (str).replace ('+', '-').replace ('/', '_')
-
-
-class DAVError (Exception):
- """ Base class for exceptions in this module. """
- def __init__ (self, status=0, message='', body='', details=''):
- self.status = status
- self.message = message
- self.body = body
- self.details = details
- Exception.__init__ (self, '%d:%s:%s%s' % (self.status, self.message,
- self.body, self.details))
-
- def print_to_stderr (self):
- """ print_to_stderr docstring """
- print >> sys.stderr, str (self.status) + ' ' + self.message
- print >> sys.stderr, str (self.details)
-
-
-class Timeout (Exception):
- """ Timeout docstring """
- def __init__ (self, arg=''):
- Exception.__init__ (self, arg)
-
-
-def alarm_handler (signum, frame):
- """ alarm_handler docstring """
- raise Timeout ('caught alarm')
-
-
-class WebDAV:
- """ WebDAV docstring """
- def __init__ (self, url, proxy=None, retries_before_fail=6):
- self.init_url = url
- self.init_proxy = proxy
- self.retries_before_fail = retries_before_fail
- url_parsed = urlparse.urlsplit (url)
-
- self.top_path = url_parsed[ 2 ]
- # make sure top_path has a trailing /
- if self.top_path == None or self.top_path == '':
- self.top_path = '/'
- elif len (self.top_path) > 1 and self.top_path[-1:] != '/':
- self.top_path += '/'
-
- if dav_debug:
- syslog.syslog ('new WebDAV %s : %s' % (str (url), str (proxy)))
-
- if proxy:
- proxy_parsed = urlparse.urlsplit (proxy)
- self.host_header = url_parsed[ 1 ]
- host_and_port = proxy_parsed[ 1 ].split (':')
- self.host = host_and_port[ 0 ]
- if len (host_and_port) > 1:
- self.port = int(host_and_port[ 1 ])
- else:
- self.port = 80
- else: # no proxy
- host_and_port = url_parsed[ 1 ].split (':')
- self.host_header = None
- self.host = host_and_port[ 0 ]
- if len (host_and_port) > 1:
- self.port = int(host_and_port[ 1 ])
- else:
- self.port = 80
-
- self.connection = False
- self.connect ()
-
-
- def log (self, msg, depth=0):
- """ log docstring """
- if dav_debug and depth == 0:
- host = str (self.init_url)
- if host == 'http://int.tuco.lindenlab.com:80/asset/':
- host = 'tuco'
- if host == 'http://harriet.lindenlab.com/asset-keep/':
- host = 'harriet/asset-keep'
- if host == 'http://harriet.lindenlab.com/asset-flag/':
- host = 'harriet/asset-flag'
- if host == 'http://harriet.lindenlab.com/asset/':
- host = 'harriet/asset'
- if host == 'http://ozzy.lindenlab.com/asset/':
- host = 'ozzy/asset'
- if host == 'http://station11.lindenlab.com:12041/:':
- host = 'station11:12041'
- proxy = str (self.init_proxy)
- if proxy == 'None':
- proxy = ''
- if proxy == 'http://int.tuco.lindenlab.com:3128/':
- proxy = 'tuco'
- syslog.syslog ('WebDAV (%s:%s) %s' % (host, proxy, str (msg)))
-
-
- def connect (self):
- """ connect docstring """
- self.log ('connect')
- self.connection = httplib.HTTPConnection (self.host, self.port)
-
- def __err (self, response, details):
- """ __err docstring """
- raise DAVError (response.status, response.reason, response.read (),
- str (self.init_url) + ':' + \
- str (self.init_proxy) + ':' + str (details))
-
- def request (self, method, path, body=None, headers=None,
- read_all=True, body_hook = None, recurse=0, allow_cache=True):
- """ request docstring """
- # self.log ('request %s %s' % (method, path))
- if headers == None:
- headers = {}
- if not allow_cache:
- headers['Pragma'] = 'no-cache'
- headers['cache-control'] = 'no-cache'
- try:
- if method.lower () != 'purge':
- if path.startswith ('/'):
- path = path[1:]
- if self.host_header: # use proxy
- headers[ 'host' ] = self.host_header
- fullpath = 'http://%s%s%s' % (self.host_header,
- self.top_path, path)
- else: # no proxy
- fullpath = self.top_path + path
- else:
- fullpath = path
-
- self.connection.request (method, fullpath, body, headers)
- if body_hook:
- body_hook ()
-
- # signal.signal (signal.SIGALRM, alarm_handler)
- # try:
- # signal.alarm (120)
- # signal.alarm (0)
- # except Timeout, e:
- # if recurse < 6:
- # return self.retry_request (method, path, body, headers,
- # read_all, body_hook, recurse)
- # else:
- # raise DAVError (0, 'timeout', self.host,
- # (method, path, body, headers, recurse))
-
- response = self.connection.getresponse ()
-
- if read_all:
- while len (response.read (1024)) > 0:
- pass
- if (response.status == 500 or \
- response.status == 503 or \
- response.status == 403) and \
- recurse < self.retries_before_fail:
- return self.retry_request (method, path, body, headers,
- read_all, body_hook, recurse)
- return response
- except (httplib.ResponseNotReady,
- httplib.BadStatusLine,
- socket.error):
- # if the server hangs up on us (keepalive off, broken pipe),
- # we need to reconnect and try again.
- if recurse < self.retries_before_fail:
- return self.retry_request (method, path, body, headers,
- read_all, body_hook, recurse)
- raise DAVError (0, 'reconnect failed', self.host,
- (method, path, body, headers, recurse))
-
-
- def retry_request (self, method, path, body, headers,
- read_all, body_hook, recurse):
- """ retry_request docstring """
- time.sleep (10.0 * recurse)
- self.connect ()
- return self.request (method, path, body, headers,
- read_all, body_hook, recurse+1)
-
-
-
- def propfind (self, path, body=None, depth=1):
- """ propfind docstring """
- # self.log ('propfind %s' % path)
- headers = {'Content-Type':'text/xml; charset="utf-8"',
- 'Depth':str(depth)}
- response = self.request ('PROPFIND', path, body, headers, False)
- if response.status == 207:
- return response # Multi-Status
- self.__err (response, ('PROPFIND', path, body, headers, 0))
-
-
- def purge (self, path):
- """ issue a squid purge command """
- headers = {'Accept':'*/*'}
- response = self.request ('PURGE', path, None, headers)
- if response.status == 200 or response.status == 404:
- # 200 if it was purge, 404 if it wasn't there.
- return response
- self.__err (response, ('PURGE', path, None, headers))
-
-
- def get_file_size (self, path):
- """
- Use propfind to ask a webdav server what the size of
- a file is. If used on a directory (collection) return 0
- """
- self.log ('get_file_size %s' % path)
- # "getcontentlength" property
- # 8.1.1 Example - Retrieving Named Properties
- # http://docs.python.org/lib/module-xml.dom.html
- nsurl = 'http://apache.org/dav/props/'
- doc = xml.dom.minidom.Document ()
- propfind_element = doc.createElementNS (nsurl, "D:propfind")
- propfind_element.setAttributeNS (nsurl, 'xmlns:D', 'DAV:')
- doc.appendChild (propfind_element)
- prop_element = doc.createElementNS (nsurl, "D:prop")
- propfind_element.appendChild (prop_element)
- con_len_element = doc.createElementNS (nsurl, "D:getcontentlength")
- prop_element.appendChild (con_len_element)
-
- response = self.propfind (path, doc.toxml ())
- doc.unlink ()
-
- resp_doc = xml.dom.minidom.parseString (response.read ())
- cln = resp_doc.getElementsByTagNameNS ('DAV:','getcontentlength')[ 0 ]
- try:
- content_length = int (cln.childNodes[ 0 ].nodeValue)
- except IndexError:
- return 0
- resp_doc.unlink ()
- return content_length
-
-
- def file_exists (self, path):
- """
- do an http head on the given file. return True if it succeeds
- """
- self.log ('file_exists %s' % path)
- expect_gzip = path.endswith ('.gz')
- response = self.request ('HEAD', path)
- got_gzip = response.getheader ('Content-Encoding', '').strip ()
- if got_gzip.lower () == 'x-gzip' and expect_gzip == False:
- # the asset server fakes us out if we ask for the non-gzipped
- # version of an asset, but the server has the gzipped version.
- return False
- return response.status == 200
-
-
- def mkdir (self, path):
- """ mkdir docstring """
- self.log ('mkdir %s' % path)
- headers = {}
- response = self.request ('MKCOL', path, None, headers)
- if response.status == 201:
- return # success
- if response.status == 405:
- return # directory already existed?
- self.__err (response, ('MKCOL', path, None, headers, 0))
-
-
- def delete (self, path):
- """ delete docstring """
- self.log ('delete %s' % path)
- headers = {'Depth':'infinity'} # collections require infinity
- response = self.request ('DELETE', path, None, headers)
- if response.status == 204:
- return # no content
- if response.status == 404:
- return # hmm
- self.__err (response, ('DELETE', path, None, headers, 0))
-
-
- def list_directory (self, path, dir_filter=None, allow_cache=True,
- minimum_cache_time=False):
- """
- Request an http directory listing and parse the filenames out of lines
- like: '<LI><A HREF="X"> X</A>'. If a filter function is provided,
- only return filenames that the filter returns True for.
-
- This is sort of grody, but it seems faster than other ways of getting
- this information from an isilon.
- """
- self.log ('list_directory %s' % path)
-
- def try_match (lline, before, after):
- """ try_match docstring """
- try:
- blen = len (before)
- asset_start_index = lline.index (before)
- asset_end_index = lline.index (after, asset_start_index + blen)
- asset = line[ asset_start_index + blen : asset_end_index ]
-
- if not dir_filter or dir_filter (asset):
- return [ asset ]
- return []
- except ValueError:
- return []
-
- if len (path) > 0 and path[-1:] != '/':
- path += '/'
-
- response = self.request ('GET', path, None, {}, False,
- allow_cache=allow_cache)
-
- if allow_cache and minimum_cache_time: # XXX
- print response.getheader ('Date')
- # s = "2005-12-06T12:13:14"
- # from datetime import datetime
- # from time import strptime
- # datetime(*strptime(s, "%Y-%m-%dT%H:%M:%S")[0:6])
- # datetime.datetime(2005, 12, 6, 12, 13, 14)
-
- if response.status != 200:
- self.__err (response, ('GET', path, None, {}, 0))
- assets = []
- for line in response.read ().split ('\n'):
- lline = line.lower ()
- if lline.find ("parent directory") == -1:
- # isilon file
- assets += try_match (lline, '<li><a href="', '"> ')
- # apache dir
- assets += try_match (lline, 'alt="[dir]"> <a href="', '/">')
- # apache file
- assets += try_match (lline, 'alt="[ ]"> <a href="', '">')
- return assets
-
-
- def __tmp_filename (self, path_and_file):
- """ __tmp_filename docstring """
- head, tail = os.path.split (path_and_file)
- if head != '':
- return head + '/.' + tail + '.' + str (os.getpid ())
- else:
- return head + '.' + tail + '.' + str (os.getpid ())
-
-
- def __put__ (self, filesize, body_hook, remotefile):
- """ __put__ docstring """
- headers = {'Content-Length' : str (filesize)}
- remotefile_tmp = self.__tmp_filename (remotefile)
- response = self.request ('PUT', remotefile_tmp, None,
- headers, True, body_hook)
- if not response.status in (201, 204): # created, no content
- self.__err (response, ('PUT', remotefile, None, headers, 0))
- if filesize != self.get_file_size (remotefile_tmp):
- try:
- self.delete (remotefile_tmp)
- except:
- pass
- raise DAVError (0, 'tmp upload error', remotefile_tmp)
- # move the file to its final location
- try:
- self.rename (remotefile_tmp, remotefile)
- except DAVError, exc:
- if exc.status == 403: # try to clean up the tmp file
- try:
- self.delete (remotefile_tmp)
- except:
- pass
- raise
- if filesize != self.get_file_size (remotefile):
- raise DAVError (0, 'file upload error', str (remotefile_tmp))
-
-
- def put_string (self, strng, remotefile):
- """ put_string docstring """
- self.log ('put_string %d -> %s' % (len (strng), remotefile))
- filesize = len (strng)
- def body_hook ():
- """ body_hook docstring """
- self.connection.send (strng)
- self.__put__ (filesize, body_hook, remotefile)
-
-
- def put_file (self, localfile, remotefile):
- """
- Send a local file to a remote webdav store. First, upload to
- a temporary filename. Next make sure the file is the size we
- expected. Next, move the file to its final location. Next,
- check the file size at the final location.
- """
- self.log ('put_file %s -> %s' % (localfile, remotefile))
- filesize = os.path.getsize (localfile)
- def body_hook ():
- """ body_hook docstring """
- handle = open (localfile)
- while True:
- data = handle.read (1300)
- if len (data) == 0:
- break
- self.connection.send (data)
- handle.close ()
- self.__put__ (filesize, body_hook, remotefile)
-
-
- def create_empty_file (self, remotefile):
- """ create an empty file """
- self.log ('touch_file %s' % (remotefile))
- headers = {'Content-Length' : '0'}
- response = self.request ('PUT', remotefile, None, headers)
- if not response.status in (201, 204): # created, no content
- self.__err (response, ('PUT', remotefile, None, headers, 0))
- if self.get_file_size (remotefile) != 0:
- raise DAVError (0, 'file upload error', str (remotefile))
-
-
- def __get_file_setup (self, remotefile, check_size=True):
- """ __get_file_setup docstring """
- if check_size:
- remotesize = self.get_file_size (remotefile)
- response = self.request ('GET', remotefile, None, {}, False)
- if response.status != 200:
- self.__err (response, ('GET', remotefile, None, {}, 0))
- try:
- content_length = int (response.getheader ("Content-Length"))
- except TypeError:
- content_length = None
- if check_size:
- if content_length != remotesize:
- raise DAVError (0, 'file DL size error', remotefile)
- return (response, content_length)
-
-
- def __get_file_read (self, writehandle, response, content_length):
- """ __get_file_read docstring """
- if content_length != None:
- so_far_length = 0
- while so_far_length < content_length:
- data = response.read (content_length - so_far_length)
- if len (data) == 0:
- raise DAVError (0, 'short file download')
- so_far_length += len (data)
- writehandle.write (data)
- while len (response.read ()) > 0:
- pass
- else:
- while True:
- data = response.read ()
- if (len (data) < 1):
- break
- writehandle.write (data)
-
-
- def get_file (self, remotefile, localfile, check_size=True):
- """
- Get a remote file from a webdav server. Download to a local
- tmp file, then move into place. Sanity check file sizes as
- we go.
- """
- self.log ('get_file %s -> %s' % (remotefile, localfile))
- (response, content_length) = \
- self.__get_file_setup (remotefile, check_size)
- localfile_tmp = self.__tmp_filename (localfile)
- handle = open (localfile_tmp, 'w')
- self.__get_file_read (handle, response, content_length)
- handle.close ()
- if check_size:
- if content_length != os.path.getsize (localfile_tmp):
- raise DAVError (0, 'file DL size error',
- remotefile+','+localfile)
- os.rename (localfile_tmp, localfile)
-
-
- def get_file_as_string (self, remotefile, check_size=True):
- """
- download a file from a webdav server and return it as a string.
- """
- self.log ('get_file_as_string %s' % remotefile)
- (response, content_length) = \
- self.__get_file_setup (remotefile, check_size)
- # (tmp_handle, tmp_filename) = tempfile.mkstemp ()
- tmp_handle = os.tmpfile ()
- self.__get_file_read (tmp_handle, response, content_length)
- tmp_handle.seek (0)
- ret = tmp_handle.read ()
- tmp_handle.close ()
- # os.unlink (tmp_filename)
- return ret
-
-
- def get_post_as_string (self, remotefile, body):
- """
- Do an http POST, send body, get response and return it.
- """
- self.log ('get_post_as_string %s' % remotefile)
- # headers = {'Content-Type':'application/x-www-form-urlencoded'}
- headers = {'Content-Type':'text/xml; charset="utf-8"'}
- # b64body = urlsafe_b64encode (asset_url)
- response = self.request ('POST', remotefile, body, headers, False)
- if response.status != 200:
- self.__err (response, ('POST', remotefile, body, headers, 0))
- try:
- content_length = int (response.getheader ('Content-Length'))
- except TypeError:
- content_length = None
- tmp_handle = os.tmpfile ()
- self.__get_file_read (tmp_handle, response, content_length)
- tmp_handle.seek (0)
- ret = tmp_handle.read ()
- tmp_handle.close ()
- return ret
-
-
- def __destination_command (self, verb, remotesrc, dstdav, remotedst):
- """
- self and dstdav should point to the same http server.
- """
- if len (remotedst) > 0 and remotedst[ 0 ] == '/':
- remotedst = remotedst[1:]
- headers = {'Destination': 'http://%s:%d%s%s' % (dstdav.host,
- dstdav.port,
- dstdav.top_path,
- remotedst)}
- response = self.request (verb, remotesrc, None, headers)
- if response.status == 201:
- return # created
- if response.status == 204:
- return # no content
- self.__err (response, (verb, remotesrc, None, headers, 0))
-
-
- def rename (self, remotesrc, remotedst):
- """ rename a file on a webdav server """
- self.log ('rename %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('MOVE', remotesrc, self, remotedst)
- def xrename (self, remotesrc, dstdav, remotedst):
- """ rename a file on a webdav server """
- self.log ('xrename %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('MOVE', remotesrc, dstdav, remotedst)
-
-
- def copy (self, remotesrc, remotedst):
- """ copy a file on a webdav server """
- self.log ('copy %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('COPY', remotesrc, self, remotedst)
- def xcopy (self, remotesrc, dstdav, remotedst):
- """ copy a file on a webdav server """
- self.log ('xcopy %s -> %s' % (remotesrc, remotedst))
- self.__destination_command ('COPY', remotesrc, dstdav, remotedst)
-
-
-def put_string (data, url):
- """
- upload string s to a url
- """
- url_parsed = urlparse.urlsplit (url)
- dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ]))
- dav.put_string (data, url_parsed[ 2 ])
-
-
-def get_string (url, check_size=True):
- """
- return the contents of a url as a string
- """
- url_parsed = urlparse.urlsplit (url)
- dav = WebDAV ('%s://%s/' % (url_parsed[ 0 ], url_parsed[ 1 ]))
- return dav.get_file_as_string (url_parsed[ 2 ], check_size)
diff --git a/indra/lib/python/indra/ipc/xml_rpc.py b/indra/lib/python/indra/ipc/xml_rpc.py
deleted file mode 100755
index 47536c10c3..0000000000
--- a/indra/lib/python/indra/ipc/xml_rpc.py
+++ /dev/null
@@ -1,273 +0,0 @@
-"""\
-@file xml_rpc.py
-@brief An implementation of a parser/generator for the XML-RPC xml format.
-
-$LicenseInfo:firstyear=2006&license=mit$
-
-Copyright (c) 2006-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-
-from greenlet import greenlet
-
-from mulib import mu
-
-from xml.sax import handler
-from xml.sax import parseString
-
-
-# States
-class Expected(object):
- def __init__(self, tag):
- self.tag = tag
-
- def __getattr__(self, name):
- return type(self)(name)
-
- def __repr__(self):
- return '%s(%r)' % (
- type(self).__name__, self.tag)
-
-
-class START(Expected):
- pass
-
-
-class END(Expected):
- pass
-
-
-class STR(object):
- tag = ''
-
-
-START = START('')
-END = END('')
-
-
-class Malformed(Exception):
- pass
-
-
-class XMLParser(handler.ContentHandler):
- def __init__(self, state_machine, next_states):
- handler.ContentHandler.__init__(self)
- self.state_machine = state_machine
- if not isinstance(next_states, tuple):
- next_states = (next_states, )
- self.next_states = next_states
- self._character_buffer = ''
-
- def assertState(self, state, name, *rest):
- if not isinstance(self.next_states, tuple):
- self.next_states = (self.next_states, )
- for next in self.next_states:
- if type(state) == type(next):
- if next.tag and next.tag != name:
- raise Malformed(
- "Expected %s, got %s %s %s" % (
- next, state, name, rest))
- break
- else:
- raise Malformed(
- "Expected %s, got %s %s %s" % (
- self.next_states, state, name, rest))
-
- def startElement(self, name, attrs):
- self.assertState(START, name.lower(), attrs)
- self.next_states = self.state_machine.switch(START, (name.lower(), dict(attrs)))
-
- def endElement(self, name):
- if self._character_buffer.strip():
- characters = self._character_buffer.strip()
- self._character_buffer = ''
- self.assertState(STR, characters)
- self.next_states = self.state_machine.switch(characters)
- self.assertState(END, name.lower())
- self.next_states = self.state_machine.switch(END, name.lower())
-
- def error(self, exc):
- self.bozo = 1
- self.exc = exc
-
- def fatalError(self, exc):
- self.error(exc)
- raise exc
-
- def characters(self, characters):
- self._character_buffer += characters
-
-
-def parse(what):
- child = greenlet(xml_rpc)
- me = greenlet.getcurrent()
- startup_states = child.switch(me)
- parser = XMLParser(child, startup_states)
- try:
- parseString(what, parser)
- except Malformed:
- print what
- raise
- return child.switch()
-
-
-def xml_rpc(yielder):
- yielder.switch(START.methodcall)
- yielder.switch(START.methodname)
- methodName = yielder.switch(STR)
- yielder.switch(END.methodname)
-
- yielder.switch(START.params)
-
- root = None
- params = []
- while True:
- state, _ = yielder.switch(START.param, END.params)
- if state == END:
- break
-
- yielder.switch(START.value)
-
- params.append(
- handle(yielder))
-
- yielder.switch(END.value)
- yielder.switch(END.param)
-
- yielder.switch(END.methodcall)
- ## Resume parse
- yielder.switch()
- ## Return result to parse
- return methodName.strip(), params
-
-
-def handle(yielder):
- _, (tag, attrs) = yielder.switch(START)
- if tag in ['int', 'i4']:
- result = int(yielder.switch(STR))
- elif tag == 'boolean':
- result = bool(int(yielder.switch(STR)))
- elif tag == 'string':
- result = yielder.switch(STR)
- elif tag == 'double':
- result = float(yielder.switch(STR))
- elif tag == 'datetime.iso8601':
- result = yielder.switch(STR)
- elif tag == 'base64':
- result = base64.b64decode(yielder.switch(STR))
- elif tag == 'struct':
- result = {}
- while True:
- state, _ = yielder.switch(START.member, END.struct)
- if state == END:
- break
-
- yielder.switch(START.name)
- key = yielder.switch(STR)
- yielder.switch(END.name)
-
- yielder.switch(START.value)
- result[key] = handle(yielder)
- yielder.switch(END.value)
-
- yielder.switch(END.member)
- ## We already handled </struct> above, don't want to handle it below
- return result
- elif tag == 'array':
- result = []
- yielder.switch(START.data)
- while True:
- state, _ = yielder.switch(START.value, END.data)
- if state == END:
- break
-
- result.append(handle(yielder))
-
- yielder.switch(END.value)
-
- yielder.switch(getattr(END, tag))
-
- return result
-
-
-VALUE = mu.tag_factory('value')
-BOOLEAN = mu.tag_factory('boolean')
-INT = mu.tag_factory('int')
-STRUCT = mu.tag_factory('struct')
-MEMBER = mu.tag_factory('member')
-NAME = mu.tag_factory('name')
-ARRAY = mu.tag_factory('array')
-DATA = mu.tag_factory('data')
-STRING = mu.tag_factory('string')
-DOUBLE = mu.tag_factory('double')
-METHODRESPONSE = mu.tag_factory('methodResponse')
-PARAMS = mu.tag_factory('params')
-PARAM = mu.tag_factory('param')
-
-mu.inline_elements['string'] = True
-mu.inline_elements['boolean'] = True
-mu.inline_elements['name'] = True
-
-
-def _generate(something):
- if isinstance(something, dict):
- result = STRUCT()
- for key, value in something.items():
- result[
- MEMBER[
- NAME[key], _generate(value)]]
- return VALUE[result]
- elif isinstance(something, list):
- result = DATA()
- for item in something:
- result[_generate(item)]
- return VALUE[ARRAY[[result]]]
- elif isinstance(something, basestring):
- return VALUE[STRING[something]]
- elif isinstance(something, bool):
- if something:
- return VALUE[BOOLEAN['1']]
- return VALUE[BOOLEAN['0']]
- elif isinstance(something, int):
- return VALUE[INT[something]]
- elif isinstance(something, float):
- return VALUE[DOUBLE[something]]
-
-def generate(*args):
- params = PARAMS()
- for arg in args:
- params[PARAM[_generate(arg)]]
- return METHODRESPONSE[params]
-
-
-if __name__ == '__main__':
- print parse("""<?xml version="1.0"?> <methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>41</i4></value> </param> </params> </methodCall>
-""")
-
-
-
-
-
-
-
-
-
diff --git a/indra/lib/python/indra/util/fastest_elementtree.py b/indra/lib/python/indra/util/fastest_elementtree.py
deleted file mode 100755
index 4fcf662dd9..0000000000
--- a/indra/lib/python/indra/util/fastest_elementtree.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""\
-@file fastest_elementtree.py
-@brief Concealing some gnarly import logic in here. This should export the interface of elementtree.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-# The parsing exception raised by the underlying library depends
-# on the ElementTree implementation we're using, so we provide an
-# alias here.
-#
-# Use ElementTreeError as the exception type for catching parsing
-# errors.
-
-
-# Using cElementTree might cause some unforeseen problems, so here's a
-# convenient off switch.
-use_celementree = True
-
-try:
- if not use_celementree:
- raise ImportError()
- # Python 2.3 and 2.4.
- from cElementTree import *
- ElementTreeError = SyntaxError
-except ImportError:
- try:
- if not use_celementree:
- raise ImportError()
- # Python 2.5 and above.
- from xml.etree.cElementTree import *
- ElementTreeError = SyntaxError
- except ImportError:
- # Pure Python code.
- try:
- # Python 2.3 and 2.4.
- from elementtree.ElementTree import *
- except ImportError:
- # Python 2.5 and above.
- from xml.etree.ElementTree import *
-
- # The pure Python ElementTree module uses Expat for parsing.
- from xml.parsers.expat import ExpatError as ElementTreeError
diff --git a/indra/lib/python/indra/util/helpformatter.py b/indra/lib/python/indra/util/helpformatter.py
deleted file mode 100755
index ba5c9b67d1..0000000000
--- a/indra/lib/python/indra/util/helpformatter.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""\
-@file helpformatter.py
-@author Phoenix
-@brief Class for formatting optparse descriptions.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import optparse
-import textwrap
-
-class Formatter(optparse.IndentedHelpFormatter):
- def __init__(
- self,
- p_indentIncrement = 2,
- p_maxHelpPosition = 24,
- p_width = 79,
- p_shortFirst = 1) :
- optparse.HelpFormatter.__init__(
- self,
- p_indentIncrement,
- p_maxHelpPosition,
- p_width,
- p_shortFirst)
- def format_description(self, p_description):
- t_descWidth = self.width - self.current_indent
- t_indent = " " * (self.current_indent + 2)
- return "\n".join(
- [textwrap.fill(descr, t_descWidth, initial_indent = t_indent,
- subsequent_indent = t_indent)
- for descr in p_description.split("\n")] )
diff --git a/indra/lib/python/indra/util/iterators.py b/indra/lib/python/indra/util/iterators.py
deleted file mode 100755
index 9013fa6303..0000000000
--- a/indra/lib/python/indra/util/iterators.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""\
-@file iterators.py
-@brief Useful general-purpose iterators.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-from __future__ import nested_scopes
-
-def iter_chunks(rows, aggregate_size=100):
- """
- Given an iterable set of items (@p rows), produces lists of up to @p
- aggregate_size items at a time, for example:
-
- iter_chunks([1,2,3,4,5,6,7,8,9,10], 3)
-
- Values for @p aggregate_size < 1 will raise ValueError.
-
- Will return a generator that produces, in the following order:
- - [1, 2, 3]
- - [4, 5, 6]
- - [7, 8, 9]
- - [10]
- """
- if aggregate_size < 1:
- raise ValueError()
-
- def iter_chunks_inner():
- row_iter = iter(rows)
- done = False
- agg = []
- while not done:
- try:
- row = row_iter.next()
- agg.append(row)
- except StopIteration:
- done = True
- if agg and (len(agg) >= aggregate_size or done):
- yield agg
- agg = []
-
- return iter_chunks_inner()
diff --git a/indra/lib/python/indra/util/iterators_test.py b/indra/lib/python/indra/util/iterators_test.py
deleted file mode 100755
index 66928c8e7d..0000000000
--- a/indra/lib/python/indra/util/iterators_test.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""\
-@file iterators_test.py
-@brief Test cases for iterators module.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import unittest
-
-from indra.util.iterators import iter_chunks
-
-class TestIterChunks(unittest.TestCase):
- """Unittests for iter_chunks"""
- def test_bad_agg_size(self):
- rows = [1,2,3,4]
- self.assertRaises(ValueError, iter_chunks, rows, 0)
- self.assertRaises(ValueError, iter_chunks, rows, -1)
-
- try:
- for i in iter_chunks(rows, 0):
- pass
- except ValueError:
- pass
- else:
- self.fail()
-
- try:
- result = list(iter_chunks(rows, 0))
- except ValueError:
- pass
- else:
- self.fail()
- def test_empty(self):
- rows = []
- result = list(iter_chunks(rows))
- self.assertEqual(result, [])
- def test_small(self):
- rows = [[1]]
- result = list(iter_chunks(rows, 2))
- self.assertEqual(result, [[[1]]])
- def test_size(self):
- rows = [[1],[2]]
- result = list(iter_chunks(rows, 2))
- self.assertEqual(result, [[[1],[2]]])
- def test_multi_agg(self):
- rows = [[1],[2],[3],[4],[5]]
- result = list(iter_chunks(rows, 2))
- self.assertEqual(result, [[[1],[2]],[[3],[4]],[[5]]])
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/indra/lib/python/indra/util/llperformance.py b/indra/lib/python/indra/util/llperformance.py
deleted file mode 100755
index 57dd64de3f..0000000000
--- a/indra/lib/python/indra/util/llperformance.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file llperformance.py
-
-$LicenseInfo:firstyear=2010&license=viewerlgpl$
-Second Life Viewer Source Code
-Copyright (C) 2010-2011, Linden Research, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation;
-version 2.1 of the License only.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-$/LicenseInfo$
-"""
-
-# ------------------------------------------------
-# Sim metrics utility functions.
-
-import glob, os, time, sys, stat, exceptions
-
-from indra.base import llsd
-
-gBlockMap = {} #Map of performance metric data with function hierarchy information.
-gCurrentStatPath = ""
-
-gIsLoggingEnabled=False
-
-class LLPerfStat:
- def __init__(self,key):
- self.mTotalTime = 0
- self.mNumRuns = 0
- self.mName=key
- self.mTimeStamp = int(time.time()*1000)
- self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
-
- def __str__(self):
- return "%f" % self.mTotalTime
-
- def start(self):
- self.mStartTime = int(time.time() * 1000000)
- self.mNumRuns += 1
-
- def stop(self):
- execution_time = int(time.time() * 1000000) - self.mStartTime
- self.mTotalTime += execution_time
-
- def get_map(self):
- results={}
- results['name']=self.mName
- results['utc_time']=self.mUTCTime
- results['timestamp']=self.mTimeStamp
- results['us']=self.mTotalTime
- results['count']=self.mNumRuns
- return results
-
-class PerfError(exceptions.Exception):
- def __init__(self):
- return
-
- def __Str__(self):
- print "","Unfinished LLPerfBlock"
-
-class LLPerfBlock:
- def __init__( self, key ):
- global gBlockMap
- global gCurrentStatPath
- global gIsLoggingEnabled
-
- #Check to see if we're running metrics right now.
- if gIsLoggingEnabled:
- self.mRunning = True #Mark myself as running.
-
- self.mPreviousStatPath = gCurrentStatPath
- gCurrentStatPath += "/" + key
- if gCurrentStatPath not in gBlockMap:
- gBlockMap[gCurrentStatPath] = LLPerfStat(key)
-
- self.mStat = gBlockMap[gCurrentStatPath]
- self.mStat.start()
-
- def finish( self ):
- global gBlockMap
- global gIsLoggingEnabled
-
- if gIsLoggingEnabled:
- self.mStat.stop()
- self.mRunning = False
- gCurrentStatPath = self.mPreviousStatPath
-
-# def __del__( self ):
-# if self.mRunning:
-# #SPATTERS FIXME
-# raise PerfError
-
-class LLPerformance:
- #--------------------------------------------------
- # Determine whether or not we want to log statistics
-
- def __init__( self, process_name = "python" ):
- self.process_name = process_name
- self.init_testing()
- self.mTimeStamp = int(time.time()*1000)
- self.mUTCTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
-
- def init_testing( self ):
- global gIsLoggingEnabled
-
- host_performance_file = "/dev/shm/simperf/simperf_proc_config.llsd"
-
- #If file exists, open
- if os.path.exists(host_performance_file):
- file = open (host_performance_file,'r')
-
- #Read serialized LLSD from file.
- body = llsd.parse(file.read())
-
- #Calculate time since file last modified.
- stats = os.stat(host_performance_file)
- now = time.time()
- mod = stats[stat.ST_MTIME]
- age = now - mod
-
- if age < ( body['duration'] ):
- gIsLoggingEnabled = True
-
-
- def get ( self ):
- global gIsLoggingEnabled
- return gIsLoggingEnabled
-
- #def output(self,ptr,path):
- # if 'stats' in ptr:
- # stats = ptr['stats']
- # self.mOutputPtr[path] = stats.get_map()
-
- # if 'children' in ptr:
- # children=ptr['children']
-
- # curptr = self.mOutputPtr
- # curchildren={}
- # curptr['children'] = curchildren
-
- # for key in children:
- # curchildren[key]={}
- # self.mOutputPtr = curchildren[key]
- # self.output(children[key],path + '/' + key)
-
- def done(self):
- global gBlockMap
-
- if not self.get():
- return
-
- output_name = "/dev/shm/simperf/%s_proc.%d.llsd" % (self.process_name, os.getpid())
- output_file = open(output_name, 'w')
- process_info = {
- "name" : self.process_name,
- "pid" : os.getpid(),
- "ppid" : os.getppid(),
- "timestamp" : self.mTimeStamp,
- "utc_time" : self.mUTCTime,
- }
- output_file.write(llsd.format_notation(process_info))
- output_file.write('\n')
-
- for key in gBlockMap.keys():
- gBlockMap[key] = gBlockMap[key].get_map()
- output_file.write(llsd.format_notation(gBlockMap))
- output_file.write('\n')
- output_file.close()
-
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
deleted file mode 100755
index 7e0e115d14..0000000000
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""\
-@file llsubprocess.py
-@author Phoenix
-@date 2008-01-18
-@brief The simplest possible wrapper for a common sub-process paradigm.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import os
-import popen2
-import time
-import select
-
-class Timeout(RuntimeError):
- "Exception raised when a subprocess times out."
- pass
-
-def run(command, args=None, data=None, timeout=None):
- """\
-@brief Run command with arguments
-
-This is it. This is the function I want to run all the time when doing
-subprocces, but end up copying the code everywhere. none of the
-standard commands are secure and provide a way to specify input, get
-all the output, and get the result.
-@param command A string specifying a process to launch.
-@param args Arguments to be passed to command. Must be list, tuple or None.
-@param data input to feed to the command.
-@param timeout Maximum number of many seconds to run.
-@return Returns (result, stdout, stderr) from process.
-"""
- cmd = [command]
- if args:
- cmd.extend([str(arg) for arg in args])
- #print "cmd: ","' '".join(cmd)
- child = popen2.Popen3(cmd, True)
- #print child.pid
- out = []
- err = []
- result = -1
- time_left = timeout
- tochild = [child.tochild.fileno()]
- while True:
- time_start = time.time()
- #print "time:",time_left
- p_in, p_out, p_err = select.select(
- [child.fromchild.fileno(), child.childerr.fileno()],
- tochild,
- [],
- time_left)
- if p_in:
- new_line = os.read(child.fromchild.fileno(), 32 * 1024)
- if new_line:
- #print "line:",new_line
- out.append(new_line)
- new_line = os.read(child.childerr.fileno(), 32 * 1024)
- if new_line:
- #print "error:", new_line
- err.append(new_line)
- if p_out:
- if data:
- #print "p_out"
- bytes = os.write(child.tochild.fileno(), data)
- data = data[bytes:]
- if len(data) == 0:
- data = None
- tochild = []
- child.tochild.close()
- result = child.poll()
- if result != -1:
- # At this point, the child process has exited and result
- # is the return value from the process. Between the time
- # we called select() and poll() the process may have
- # exited so read all the data left on the child process
- # stdout and stderr.
- last = child.fromchild.read()
- if last:
- out.append(last)
- last = child.childerr.read()
- if last:
- err.append(last)
- child.tochild.close()
- child.fromchild.close()
- child.childerr.close()
- break
- if time_left is not None:
- time_left -= (time.time() - time_start)
- if time_left < 0:
- raise Timeout
- #print "result:",result
- out = ''.join(out)
- #print "stdout:", out
- err = ''.join(err)
- #print "stderr:", err
- return result, out, err
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
deleted file mode 100755
index 6bf956107d..0000000000
--- a/indra/lib/python/indra/util/named_query.py
+++ /dev/null
@@ -1,592 +0,0 @@
-"""\
-@file named_query.py
-@author Ryan Williams, Phoenix
-@date 2007-07-31
-@brief An API for running named queries.
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import errno
-import MySQLdb
-import MySQLdb.cursors
-import os
-import os.path
-import re
-import time
-
-from indra.base import llsd
-from indra.base import config
-
-DEBUG = False
-NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
-NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
-
-_g_named_manager = None
-
-def _init_g_named_manager(sql_dir = None):
- """Initializes a global NamedManager object to point at a
- specified named queries hierarchy.
-
- This function is intended entirely for testing purposes,
- because it's tricky to control the config from inside a test."""
- global NQ_FILE_SUFFIX
- NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
- global NQ_FILE_SUFFIX_LEN
- NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
-
- if sql_dir is None:
- sql_dir = config.get('named-query-base-dir')
-
- # extra fallback directory in case config doesn't return what we want
- if sql_dir is None:
- sql_dir = os.path.abspath(
- os.path.join(
- os.path.realpath(os.path.dirname(__file__)), "..", "..", "..", "..", "web", "dataservice", "sql"))
-
- global _g_named_manager
- _g_named_manager = NamedQueryManager(
- os.path.abspath(os.path.realpath(sql_dir)))
-
-def get(name, schema = None):
- "Get the named query object to be used to perform queries"
- if _g_named_manager is None:
- _init_g_named_manager()
- return _g_named_manager.get(name).for_schema(schema)
-
-def sql(connection, name, params):
- # use module-global NamedQuery object to perform default substitution
- return get(name).sql(connection, params)
-
-def run(connection, name, params, expect_rows = None):
- """\
-@brief given a connection, run a named query with the params
-
-Note that this function will fetch ALL rows.
-@param connection The connection to use
-@param name The name of the query to run
-@param params The parameters passed into the query
-@param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack.
-@return Returns the result set as a list of dicts.
-"""
- return get(name).run(connection, params, expect_rows)
-
-class ExpectationFailed(Exception):
- """ Exception that is raised when an expectation for an sql query
- is not met."""
- def __init__(self, message):
- Exception.__init__(self, message)
- self.message = message
-
-class NamedQuery(object):
- def __init__(self, name, filename):
- """ Construct a NamedQuery object. The name argument is an
- arbitrary name as a handle for the query, and the filename is
- a path to a file or a file-like object containing an llsd named
- query document."""
- self._stat_interval_seconds = 5 # 5 seconds
- self._name = name
- if (filename is not None and isinstance(filename, (str, unicode))
- and NQ_FILE_SUFFIX != filename[-NQ_FILE_SUFFIX_LEN:]):
- filename = filename + NQ_FILE_SUFFIX
- self._location = filename
- self._alternative = dict()
- self._last_mod_time = 0
- self._last_check_time = 0
- self.deleted = False
- self.load_contents()
-
- def name(self):
- """ The name of the query. """
- return self._name
-
- def get_modtime(self):
- """ Returns the mtime (last modified time) of the named query
- filename. For file-like objects, expect a modtime of 0"""
- if self._location and isinstance(self._location, (str, unicode)):
- return os.path.getmtime(self._location)
- return 0
-
- def load_contents(self):
- """ Loads and parses the named query file into self. Does
- nothing if self.location is nonexistant."""
- if self._location:
- if isinstance(self._location, (str, unicode)):
- contents = llsd.parse(open(self._location).read())
- else:
- # we probably have a file-like object. Godspeed!
- contents = llsd.parse(self._location.read())
- self._reference_contents(contents)
- # Check for alternative implementations
- try:
- for name, alt in self._contents['alternative'].items():
- nq = NamedQuery(name, None)
- nq._reference_contents(alt)
- self._alternative[name] = nq
- except KeyError, e:
- pass
- self._last_mod_time = self.get_modtime()
- self._last_check_time = time.time()
-
- def _reference_contents(self, contents):
- "Helper method which builds internal structure from parsed contents"
- self._contents = contents
- self._ttl = int(self._contents.get('ttl', 0))
- self._return_as_map = bool(self._contents.get('return_as_map', False))
- self._legacy_dbname = self._contents.get('legacy_dbname', None)
-
- # reset these before doing the sql conversion because we will
- # read them there. reset these while loading so we pick up
- # changes.
- self._around = set()
- self._append = set()
- self._integer = set()
- self._options = self._contents.get('dynamic_where', {})
- for key in self._options:
- if isinstance(self._options[key], basestring):
- self._options[key] = self._convert_sql(self._options[key])
- elif isinstance(self._options[key], list):
- lines = []
- for line in self._options[key]:
- lines.append(self._convert_sql(line))
- self._options[key] = lines
- else:
- moreopt = {}
- for kk in self._options[key]:
- moreopt[kk] = self._convert_sql(self._options[key][kk])
- self._options[key] = moreopt
- self._base_query = self._convert_sql(self._contents['base_query'])
- self._query_suffix = self._convert_sql(
- self._contents.get('query_suffix', ''))
-
- def _convert_sql(self, sql):
- """convert the parsed sql into a useful internal structure.
-
- This function has to turn the named query format into a pyformat
- style. It also has to look for %:name% and :name% and
- ready them for use in LIKE statements"""
- if sql:
- # This first sub is to properly escape any % signs that
- # are meant to be literally passed through to mysql in the
- # query. It leaves any %'s that are used for
- # like-expressions.
- expr = re.compile("(?<=[^a-zA-Z0-9_-])%(?=[^:])")
- sql = expr.sub('%%', sql)
-
- # This should tackle the rest of the %'s in the query, by
- # converting them to LIKE clauses.
- expr = re.compile("(%?):([a-zA-Z][a-zA-Z0-9_-]*)%")
- sql = expr.sub(self._prepare_like, sql)
- expr = re.compile("#:([a-zA-Z][a-zA-Z0-9_-]*)")
- sql = expr.sub(self._prepare_integer, sql)
- expr = re.compile(":([a-zA-Z][a-zA-Z0-9_-]*)")
- sql = expr.sub("%(\\1)s", sql)
- return sql
-
- def _prepare_like(self, match):
- """This function changes LIKE statement replace behavior
-
- It works by turning %:name% to %(_name_around)s and :name% to
- %(_name_append)s. Since a leading '_' is not a valid keyname
- input (enforced via unit tests), it will never clash with
- existing keys. Then, when building the statement, the query
- runner will generate corrected strings."""
- if match.group(1) == '%':
- # there is a leading % so this is treated as prefix/suffix
- self._around.add(match.group(2))
- return "%(" + self._build_around_key(match.group(2)) + ")s"
- else:
- # there is no leading %, so this is suffix only
- self._append.add(match.group(2))
- return "%(" + self._build_append_key(match.group(2)) + ")s"
-
- def _build_around_key(self, key):
- return "_" + key + "_around"
-
- def _build_append_key(self, key):
- return "_" + key + "_append"
-
- def _prepare_integer(self, match):
- """This function adjusts the sql for #:name replacements
-
- It works by turning #:name to %(_name_as_integer)s. Since a
- leading '_' is not a valid keyname input (enforced via unit
- tests), it will never clash with existing keys. Then, when
- building the statement, the query runner will generate
- corrected strings."""
- self._integer.add(match.group(1))
- return "%(" + self._build_integer_key(match.group(1)) + ")s"
-
- def _build_integer_key(self, key):
- return "_" + key + "_as_integer"
-
- def _strip_wildcards_to_list(self, value):
- """Take string, and strip out the LIKE special characters.
-
- Technically, this is database dependant, but postgresql and
- mysql use the same wildcards, and I am not aware of a general
- way to handle this. I think you need a sql statement of the
- form:
-
- LIKE_STRING( [ANY,ONE,str]... )
-
- which would treat ANY as their any string, and ONE as their
- single glyph, and str as something that needs database
- specific encoding to not allow any % or _ to affect the query.
-
- As it stands, I believe it's impossible to write a named query
- style interface which uses like to search the entire space of
- text available. Imagine the query:
-
- % of brain used by average linden
-
- In order to search for %, it must be escaped, so once you have
- escaped the string to not do wildcard searches, and be escaped
- for the database, and then prepended the wildcard you come
- back with one of:
-
- 1) %\% of brain used by average linden
- 2) %%% of brain used by average linden
-
- Then, when passed to the database to be escaped to be database
- safe, you get back:
-
- 1) %\\% of brain used by average linden
- : which means search for any character sequence, followed by a
- backslash, followed by any sequence, followed by ' of
- brain...'
- 2) %%% of brain used by average linden
- : which (I believe) means search for a % followed by any
- character sequence followed by 'of brain...'
-
- Neither of which is what we want!
-
- So, we need a vendor (or extention) for LIKE_STRING. Anyone
- want to write it?"""
- if isinstance(value, unicode):
- utf8_value = value
- else:
- utf8_value = unicode(value, "utf-8")
- esc_list = []
- remove_chars = set(u"%_")
- for glyph in utf8_value:
- if glyph in remove_chars:
- continue
- esc_list.append(glyph.encode("utf-8"))
- return esc_list
-
- def delete(self):
- """ Makes this query unusable by deleting all the members and
- setting the deleted member. This is desired when the on-disk
- query has been deleted but the in-memory copy remains."""
- # blow away all members except _name, _location, and deleted
- name, location = self._name, self._location
- for key in self.__dict__.keys():
- del self.__dict__[key]
- self.deleted = True
- self._name, self._location = name, location
-
- def ttl(self):
- """ Estimated time to live of this query. Used for web
- services to set the Expires header."""
- return self._ttl
-
- def legacy_dbname(self):
- return self._legacy_dbname
-
- def return_as_map(self):
- """ Returns true if this query is configured to return its
- results as a single map (as opposed to a list of maps, the
- normal behavior)."""
-
- return self._return_as_map
-
- def for_schema(self, db_name):
- "Look trough the alternates and return the correct query"
- if db_name is None:
- return self
- try:
- return self._alternative[db_name]
- except KeyError, e:
- pass
- return self
-
- def run(self, connection, params, expect_rows = None, use_dictcursor = True):
- """given a connection, run a named query with the params
-
- Note that this function will fetch ALL rows. We do this because it
- opens and closes the cursor to generate the values, and this
- isn't a generator so the cursor has no life beyond the method call.
-
- @param cursor The connection to use (this generates its own cursor for the query)
- @param name The name of the query to run
- @param params The parameters passed into the query
- @param expect_rows The number of rows expected. Set to 1 if return_as_map is true. Raises ExpectationFailed if the number of returned rows doesn't exactly match. Kind of a hack.
- @param use_dictcursor Set to false to use a normal cursor and manually convert the rows to dicts.
- @return Returns the result set as a list of dicts, or, if the named query has return_as_map set to true, returns a single dict.
- """
- if use_dictcursor:
- cursor = connection.cursor(MySQLdb.cursors.DictCursor)
- else:
- cursor = connection.cursor()
-
- full_query, params = self._construct_sql(params)
- if DEBUG:
- print "SQL:", self.sql(connection, params)
- rows = cursor.execute(full_query, params)
-
- # *NOTE: the expect_rows argument is a very cheesy way to get some
- # validation on the result set. If you want to add more expectation
- # logic, do something more object-oriented and flexible. Or use an ORM.
- if(self._return_as_map):
- expect_rows = 1
- if expect_rows is not None and rows != expect_rows:
- cursor.close()
- raise ExpectationFailed("Statement expected %s rows, got %s. Sql: '%s' %s" % (
- expect_rows, rows, full_query, params))
-
- # convert to dicts manually if we're not using a dictcursor
- if use_dictcursor:
- result_set = cursor.fetchall()
- else:
- if cursor.description is None:
- # an insert or something
- x = cursor.fetchall()
- cursor.close()
- return x
-
- names = [x[0] for x in cursor.description]
-
- result_set = []
- for row in cursor.fetchall():
- converted_row = {}
- for idx, col_name in enumerate(names):
- converted_row[col_name] = row[idx]
- result_set.append(converted_row)
-
- cursor.close()
- if self._return_as_map:
- return result_set[0]
- return result_set
-
- def _construct_sql(self, params):
- """ Returns a query string and a dictionary of parameters,
- suitable for directly passing to the execute() method."""
- self.refresh()
-
- # build the query from the options available and the params
- base_query = []
- base_query.append(self._base_query)
- for opt, extra_where in self._options.items():
- if type(extra_where) in (dict, list, tuple):
- if opt in params:
- base_query.append(extra_where[params[opt]])
- else:
- if opt in params and params[opt]:
- base_query.append(extra_where)
- if self._query_suffix:
- base_query.append(self._query_suffix)
- full_query = '\n'.join(base_query)
-
- # Go through the query and rewrite all of the ones with the
- # @:name syntax.
- rewrite = _RewriteQueryForArray(params)
- expr = re.compile("@%\(([a-zA-Z][a-zA-Z0-9_-]*)\)s")
- full_query = expr.sub(rewrite.operate, full_query)
- params.update(rewrite.new_params)
-
- # build out the params for like. We only have to do this
- # parameters which were detected to have ued the where syntax
- # during load.
- #
- # * treat the incoming string as utf-8
- # * strip wildcards
- # * append or prepend % as appropriate
- new_params = {}
- for key in params:
- if key in self._around:
- new_value = ['%']
- new_value.extend(self._strip_wildcards_to_list(params[key]))
- new_value.append('%')
- new_params[self._build_around_key(key)] = ''.join(new_value)
- if key in self._append:
- new_value = self._strip_wildcards_to_list(params[key])
- new_value.append('%')
- new_params[self._build_append_key(key)] = ''.join(new_value)
- if key in self._integer:
- new_params[self._build_integer_key(key)] = int(params[key])
- params.update(new_params)
-
- return full_query, params
-
- def sql(self, connection, params):
- """ Generates an SQL statement from the named query document
- and a dictionary of parameters.
-
- *NOTE: Only use for debugging, because it uses the
- non-standard MySQLdb 'literal' method.
- """
- if not DEBUG:
- import warnings
- warnings.warn("Don't use named_query.sql() when not debugging. Used on %s" % self._location)
- # do substitution using the mysql (non-standard) 'literal'
- # function to do the escaping.
- full_query, params = self._construct_sql(params)
- return full_query % connection.literal(params)
-
-
- def refresh(self):
- """ Refresh self from the file on the filesystem.
-
- This is optimized to be callable as frequently as you wish,
- without adding too much load. It does so by only stat-ing the
- file every N seconds, where N defaults to 5 and is
- configurable through the member _stat_interval_seconds. If the stat
- reveals that the file has changed, refresh will re-parse the
- contents of the file and use them to update the named query
- instance. If the stat reveals that the file has been deleted,
- refresh will call self.delete to make the in-memory
- representation unusable."""
- now = time.time()
- if(now - self._last_check_time > self._stat_interval_seconds):
- self._last_check_time = now
- try:
- modtime = self.get_modtime()
- if(modtime > self._last_mod_time):
- self.load_contents()
- except OSError, e:
- if e.errno == errno.ENOENT: # file not found
- self.delete() # clean up self
- raise # pass the exception along to the caller so they know that this query disappeared
-
-class NamedQueryManager(object):
- """ Manages the lifespan of NamedQuery objects, drawing from a
- directory hierarchy of named query documents.
-
- In practice this amounts to a memory cache of NamedQuery objects."""
-
- def __init__(self, named_queries_dir):
- """ Initializes a manager to look for named queries in a
- directory."""
- self._dir = os.path.abspath(os.path.realpath(named_queries_dir))
- self._cached_queries = {}
-
- def sql(self, connection, name, params):
- nq = self.get(name)
- return nq.sql(connection, params)
-
- def get(self, name):
- """ Returns a NamedQuery instance based on the name, either
- from memory cache, or by parsing from disk.
-
- The name is simply a relative path to the directory associated
- with the manager object. Before returning the instance, the
- NamedQuery object is cached in memory, so that subsequent
- accesses don't have to read from disk or do any parsing. This
- means that NamedQuery objects returned by this method are
- shared across all users of the manager object.
- NamedQuery.refresh is used to bring the NamedQuery objects in
- sync with the actual files on disk."""
- nq = self._cached_queries.get(name)
- if nq is None:
- nq = NamedQuery(name, os.path.join(self._dir, name))
- self._cached_queries[name] = nq
- else:
- try:
- nq.refresh()
- except OSError, e:
- if e.errno == errno.ENOENT: # file not found
- del self._cached_queries[name]
- raise # pass exception along to caller so they know that the query disappeared
-
- return nq
-
-class _RewriteQueryForArray(object):
- "Helper class for rewriting queries with the @:name syntax"
- def __init__(self, params):
- self.params = params
- self.new_params = dict()
-
- def operate(self, match):
- "Given a match, return the string that should be in use"
- key = match.group(1)
- value = self.params[key]
- if type(value) in (list,tuple):
- rv = []
- for idx in range(len(value)):
- # if the value@idx is array-like, we are
- # probably dealing with a VALUES
- new_key = "_%s_%s"%(key, str(idx))
- val_item = value[idx]
- if type(val_item) in (list, tuple, dict):
- if type(val_item) is dict:
- # this is because in Python, the order of
- # key, value retrieval from the dict is not
- # guaranteed to match what the input intended
- # and for VALUES, order is important.
- # TODO: Implemented ordered dict in LLSD parser?
- raise ExpectationFailed('Only lists/tuples allowed,\
- received dict')
- values_keys = []
- for value_idx, item in enumerate(val_item):
- # we want a key of the format :
- # key_#replacement_#value_row_#value_col
- # ugh... so if we are replacing 10 rows in user_note,
- # the first values clause would read (for @:user_notes) :-
- # ( :_user_notes_0_1_1, :_user_notes_0_1_2, :_user_notes_0_1_3 )
- # the input LLSD for VALUES will look like:
- # <llsd>...
- # <map>
- # <key>user_notes</key>
- # <array>
- # <array> <!-- row 1 for VALUES -->
- # <string>...</string>
- # <string>...</string>
- # <string>...</string>
- # </array>
- # ...
- # </array>
- # </map>
- # ... </llsd>
- values_key = "%s_%s"%(new_key, value_idx)
- self.new_params[values_key] = item
- values_keys.append("%%(%s)s"%values_key)
- # now collapse all these new place holders enclosed in ()
- # from [':_key_0_1_1', ':_key_0_1_2', ':_key_0_1_3,...]
- # rv will have [ '(:_key_0_1_1, :_key_0_1_2, :_key_0_1_3)', ]
- # which is flattened a few lines below join(rv)
- rv.append('(%s)' % ','.join(values_keys))
- else:
- self.new_params[new_key] = val_item
- rv.append("%%(%s)s"%new_key)
- return ','.join(rv)
- else:
- # not something that can be expanded, so just drop the
- # leading @ in the front of the match. This will mean that
- # the single value we have, be it a string, int, whatever
- # (other than dict) will correctly show up, eg:
- #
- # where foo in (@:foobar) -- foobar is a string, so we get
- # where foo in (:foobar)
- return match.group(0)[1:]
diff --git a/indra/lib/python/indra/util/shutil2.py b/indra/lib/python/indra/util/shutil2.py
deleted file mode 100755
index 9e2e7a6ded..0000000000
--- a/indra/lib/python/indra/util/shutil2.py
+++ /dev/null
@@ -1,84 +0,0 @@
-'''
-@file shutil2.py
-@brief a better shutil.copytree replacement
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-'''
-
-#
-# shutil2.py
-# Taken from http://www.scons.org/wiki/AccumulateBuilder
-# the stock copytree sucks because it insists that the
-# target dir not exist
-#
-
-import os.path
-import shutil
-
-def copytree(src, dest, symlinks=False):
- """My own copyTree which does not fail if the directory exists.
-
- Recursively copy a directory tree using copy2().
-
- If the optional symlinks flag is true, symbolic links in the
- source tree result in symbolic links in the destination tree; if
- it is false, the contents of the files pointed to by symbolic
- links are copied.
-
- Behavior is meant to be identical to GNU 'cp -R'.
- """
- def copyItems(src, dest, symlinks=False):
- """Function that does all the work.
-
- It is necessary to handle the two 'cp' cases:
- - destination does exist
- - destination does not exist
-
- See 'cp -R' documentation for more details
- """
- for item in os.listdir(src):
- srcPath = os.path.join(src, item)
- if os.path.isdir(srcPath):
- srcBasename = os.path.basename(srcPath)
- destDirPath = os.path.join(dest, srcBasename)
- if not os.path.exists(destDirPath):
- os.makedirs(destDirPath)
- copyItems(srcPath, destDirPath)
- elif os.path.islink(item) and symlinks:
- linkto = os.readlink(item)
- os.symlink(linkto, dest)
- else:
- shutil.copy2(srcPath, dest)
-
- # case 'cp -R src/ dest/' where dest/ already exists
- if os.path.exists(dest):
- destPath = os.path.join(dest, os.path.basename(src))
- if not os.path.exists(destPath):
- os.makedirs(destPath)
- # case 'cp -R src/ dest/' where dest/ does not exist
- else:
- os.makedirs(dest)
- destPath = dest
- # actually copy the files
- copyItems(src, destPath)
diff --git a/indra/lib/python/indra/util/simperf_host_xml_parser.py b/indra/lib/python/indra/util/simperf_host_xml_parser.py
deleted file mode 100755
index 672c1050c2..0000000000
--- a/indra/lib/python/indra/util/simperf_host_xml_parser.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file simperf_host_xml_parser.py
-@brief Digest collector's XML dump and convert to simple dict/list structure
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys, os, getopt, time
-import simplejson
-from xml import sax
-
-
-def usage():
- print "Usage:"
- print sys.argv[0] + " [options]"
- print " Convert RRD's XML dump to JSON. Script to convert the simperf_host_collector-"
- print " generated RRD dump into JSON. Steps include converting selected named"
- print " fields from GAUGE type to COUNTER type by computing delta with preceding"
- print " values. Top-level named fields are:"
- print
- print " lastupdate Time (javascript timestamp) of last data sample"
- print " step Time in seconds between samples"
- print " ds Data specification (name/type) for each column"
- print " database Table of data samples, one time step per row"
- print
- print "Options:"
- print " -i, --in Input settings filename. (Default: stdin)"
- print " -o, --out Output settings filename. (Default: stdout)"
- print " -h, --help Print this message and exit."
- print
- print "Example: %s -i rrddump.xml -o rrddump.json" % sys.argv[0]
- print
- print "Interfaces:"
- print " class SimPerfHostXMLParser() # SAX content handler"
- print " def simperf_host_xml_fixup(parser) # post-parse value fixup"
-
-class SimPerfHostXMLParser(sax.handler.ContentHandler):
-
- def __init__(self):
- pass
-
- def startDocument(self):
- self.rrd_last_update = 0 # public
- self.rrd_step = 0 # public
- self.rrd_ds = [] # public
- self.rrd_records = [] # public
- self._rrd_level = 0
- self._rrd_parse_state = 0
- self._rrd_chars = ""
- self._rrd_capture = False
- self._rrd_ds_val = {}
- self._rrd_data_row = []
- self._rrd_data_row_has_nan = False
-
- def endDocument(self):
- pass
-
- # Nasty little ad-hoc state machine to extract the elements that are
- # necessary from the 'rrdtool dump' XML output. The same element
- # name '<ds>' is used for two different data sets so we need to pay
- # some attention to the actual structure to get the ones we want
- # and ignore the ones we don't.
-
- def startElement(self, name, attrs):
- self._rrd_level = self._rrd_level + 1
- self._rrd_capture = False
- if self._rrd_level == 1:
- if name == "rrd" and self._rrd_parse_state == 0:
- self._rrd_parse_state = 1 # In <rrd>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif self._rrd_level == 2:
- if self._rrd_parse_state == 1:
- if name == "lastupdate":
- self._rrd_parse_state = 2 # In <rrd><lastupdate>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif name == "step":
- self._rrd_parse_state = 3 # In <rrd><step>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif name == "ds":
- self._rrd_parse_state = 4 # In <rrd><ds>
- self._rrd_ds_val = {}
- self._rrd_chars = ""
- elif name == "rra":
- self._rrd_parse_state = 5 # In <rrd><rra>
- elif self._rrd_level == 3:
- if self._rrd_parse_state == 4:
- if name == "name":
- self._rrd_parse_state = 6 # In <rrd><ds><name>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif name == "type":
- self._rrd_parse_state = 7 # In <rrd><ds><type>
- self._rrd_capture = True
- self._rrd_chars = ""
- elif self._rrd_parse_state == 5:
- if name == "database":
- self._rrd_parse_state = 8 # In <rrd><rra><database>
- elif self._rrd_level == 4:
- if self._rrd_parse_state == 8:
- if name == "row":
- self._rrd_parse_state = 9 # In <rrd><rra><database><row>
- self._rrd_data_row = []
- self._rrd_data_row_has_nan = False
- elif self._rrd_level == 5:
- if self._rrd_parse_state == 9:
- if name == "v":
- self._rrd_parse_state = 10 # In <rrd><rra><database><row><v>
- self._rrd_capture = True
- self._rrd_chars = ""
-
- def endElement(self, name):
- self._rrd_capture = False
- if self._rrd_parse_state == 10:
- self._rrd_capture = self._rrd_level == 6
- if self._rrd_level == 5:
- if self._rrd_chars == "NaN":
- self._rrd_data_row_has_nan = True
- else:
- self._rrd_data_row.append(self._rrd_chars)
- self._rrd_parse_state = 9 # In <rrd><rra><database><row>
- elif self._rrd_parse_state == 9:
- if self._rrd_level == 4:
- if not self._rrd_data_row_has_nan:
- self.rrd_records.append(self._rrd_data_row)
- self._rrd_parse_state = 8 # In <rrd><rra><database>
- elif self._rrd_parse_state == 8:
- if self._rrd_level == 3:
- self._rrd_parse_state = 5 # In <rrd><rra>
- elif self._rrd_parse_state == 7:
- if self._rrd_level == 3:
- self._rrd_ds_val["type"] = self._rrd_chars
- self._rrd_parse_state = 4 # In <rrd><ds>
- elif self._rrd_parse_state == 6:
- if self._rrd_level == 3:
- self._rrd_ds_val["name"] = self._rrd_chars
- self._rrd_parse_state = 4 # In <rrd><ds>
- elif self._rrd_parse_state == 5:
- if self._rrd_level == 2:
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 4:
- if self._rrd_level == 2:
- self.rrd_ds.append(self._rrd_ds_val)
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 3:
- if self._rrd_level == 2:
- self.rrd_step = long(self._rrd_chars)
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 2:
- if self._rrd_level == 2:
- self.rrd_last_update = long(self._rrd_chars)
- self._rrd_parse_state = 1 # In <rrd>
- elif self._rrd_parse_state == 1:
- if self._rrd_level == 1:
- self._rrd_parse_state = 0 # At top
-
- if self._rrd_level:
- self._rrd_level = self._rrd_level - 1
-
- def characters(self, content):
- if self._rrd_capture:
- self._rrd_chars = self._rrd_chars + content.strip()
-
-def _make_numeric(value):
- try:
- value = float(value)
- except:
- value = ""
- return value
-
-def simperf_host_xml_fixup(parser, filter_start_time = None, filter_end_time = None):
- # Fixup for GAUGE fields that are really COUNTS. They
- # were forced to GAUGE to try to disable rrdtool's
- # data interpolation/extrapolation for non-uniform time
- # samples.
- fixup_tags = [ "cpu_user",
- "cpu_nice",
- "cpu_sys",
- "cpu_idle",
- "cpu_waitio",
- "cpu_intr",
- # "file_active",
- # "file_free",
- # "inode_active",
- # "inode_free",
- "netif_in_kb",
- "netif_in_pkts",
- "netif_in_errs",
- "netif_in_drop",
- "netif_out_kb",
- "netif_out_pkts",
- "netif_out_errs",
- "netif_out_drop",
- "vm_page_in",
- "vm_page_out",
- "vm_swap_in",
- "vm_swap_out",
- #"vm_mem_total",
- #"vm_mem_used",
- #"vm_mem_active",
- #"vm_mem_inactive",
- #"vm_mem_free",
- #"vm_mem_buffer",
- #"vm_swap_cache",
- #"vm_swap_total",
- #"vm_swap_used",
- #"vm_swap_free",
- "cpu_interrupts",
- "cpu_switches",
- "cpu_forks" ]
-
- col_count = len(parser.rrd_ds)
- row_count = len(parser.rrd_records)
-
- # Process the last row separately, just to make all values numeric.
- for j in range(col_count):
- parser.rrd_records[row_count - 1][j] = _make_numeric(parser.rrd_records[row_count - 1][j])
-
- # Process all other row/columns.
- last_different_row = row_count - 1
- current_row = row_count - 2
- while current_row >= 0:
- # Check for a different value than the previous row. If everything is the same
- # then this is probably just a filler/bogus entry.
- is_different = False
- for j in range(col_count):
- parser.rrd_records[current_row][j] = _make_numeric(parser.rrd_records[current_row][j])
- if parser.rrd_records[current_row][j] != parser.rrd_records[last_different_row][j]:
- # We're good. This is a different row.
- is_different = True
-
- if not is_different:
- # This is a filler/bogus entry. Just ignore it.
- for j in range(col_count):
- parser.rrd_records[current_row][j] = float('nan')
- else:
- # Some tags need to be converted into deltas.
- for j in range(col_count):
- if parser.rrd_ds[j]["name"] in fixup_tags:
- parser.rrd_records[last_different_row][j] = \
- parser.rrd_records[last_different_row][j] - parser.rrd_records[current_row][j]
- last_different_row = current_row
-
- current_row -= 1
-
- # Set fixup_tags in the first row to 'nan' since they aren't useful anymore.
- for j in range(col_count):
- if parser.rrd_ds[j]["name"] in fixup_tags:
- parser.rrd_records[0][j] = float('nan')
-
- # Add a timestamp to each row and to the catalog. Format and name
- # chosen to match other simulator logging (hopefully).
- start_time = parser.rrd_last_update - (parser.rrd_step * (row_count - 1))
- # Build a filtered list of rrd_records if we are limited to a time range.
- filter_records = False
- if filter_start_time is not None or filter_end_time is not None:
- filter_records = True
- filtered_rrd_records = []
- if filter_start_time is None:
- filter_start_time = start_time * 1000
- if filter_end_time is None:
- filter_end_time = parser.rrd_last_update * 1000
-
- for i in range(row_count):
- record_timestamp = (start_time + (i * parser.rrd_step)) * 1000
- parser.rrd_records[i].insert(0, record_timestamp)
- if filter_records:
- if filter_start_time <= record_timestamp and record_timestamp <= filter_end_time:
- filtered_rrd_records.append(parser.rrd_records[i])
-
- if filter_records:
- parser.rrd_records = filtered_rrd_records
-
- parser.rrd_ds.insert(0, {"type": "GAUGE", "name": "javascript_timestamp"})
-
-
-def main(argv=None):
- opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"])
- input_file = sys.stdin
- output_file = sys.stdout
- for o, a in opts:
- if o in ("-i", "--in"):
- input_file = open(a, 'r')
- if o in ("-o", "--out"):
- output_file = open(a, 'w')
- if o in ("-h", "--help"):
- usage()
- sys.exit(0)
-
- # Using the SAX parser as it is at least 4X faster and far, far
- # smaller on this dataset than the DOM-based interface in xml.dom.minidom.
- # With SAX and a 5.4MB xml file, this requires about seven seconds of
- # wall-clock time and 32MB VSZ. With the DOM interface, about 22 seconds
- # and over 270MB VSZ.
-
- handler = SimPerfHostXMLParser()
- sax.parse(input_file, handler)
- if input_file != sys.stdin:
- input_file.close()
-
- # Various format fixups: string-to-num, gauge-to-counts, add
- # a time stamp, etc.
- simperf_host_xml_fixup(handler)
-
- # Create JSONable dict with interesting data and format/print it
- print >>output_file, simplejson.dumps({ "step" : handler.rrd_step,
- "lastupdate": handler.rrd_last_update * 1000,
- "ds" : handler.rrd_ds,
- "database" : handler.rrd_records })
-
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/indra/lib/python/indra/util/simperf_oprof_interface.py b/indra/lib/python/indra/util/simperf_oprof_interface.py
deleted file mode 100755
index 547d2f9980..0000000000
--- a/indra/lib/python/indra/util/simperf_oprof_interface.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file simperf_oprof_interface.py
-@brief Manage OProfile data collection on a host
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-import sys, os, getopt
-import simplejson
-
-
-def usage():
- print "Usage:"
- print sys.argv[0] + " [options]"
- print " Digest the OProfile report forms that come out of the"
- print " simperf_oprof_ctl program's -r/--report command. The result"
- print " is an array of dictionaires with the following keys:"
- print
- print " symbol Name of sampled, calling, or called procedure"
- print " file Executable or library where symbol resides"
- print " percentage Percentage contribution to profile, calls or called"
- print " samples Sample count"
- print " calls Methods called by the method in question (full only)"
- print " called_by Methods calling the method (full only)"
- print
- print " For 'full' reports the two keys 'calls' and 'called_by' are"
- print " themselves arrays of dictionaries based on the first four keys."
- print
- print "Return Codes:"
- print " None. Aggressively digests everything. Will likely mung results"
- print " if a program or library has whitespace in its name."
- print
- print "Options:"
- print " -i, --in Input settings filename. (Default: stdin)"
- print " -o, --out Output settings filename. (Default: stdout)"
- print " -h, --help Print this message and exit."
- print
- print "Interfaces:"
- print " class SimPerfOProfileInterface()"
-
-class SimPerfOProfileInterface:
- def __init__(self):
- self.isBrief = True # public
- self.isValid = False # public
- self.result = [] # public
-
- def parse(self, input):
- in_samples = False
- for line in input:
- if in_samples:
- if line[0:6] == "------":
- self.isBrief = False
- self._parseFull(input)
- else:
- self._parseBrief(input, line)
- self.isValid = True
- return
- try:
- hd1, remain = line.split(None, 1)
- if hd1 == "samples":
- in_samples = True
- except ValueError:
- pass
-
- def _parseBrief(self, input, line1):
- try:
- fld1, fld2, fld3, fld4 = line1.split(None, 3)
- self.result.append({"samples" : fld1,
- "percentage" : fld2,
- "file" : fld3,
- "symbol" : fld4.strip("\n")})
- except ValueError:
- pass
- for line in input:
- try:
- fld1, fld2, fld3, fld4 = line.split(None, 3)
- self.result.append({"samples" : fld1,
- "percentage" : fld2,
- "file" : fld3,
- "symbol" : fld4.strip("\n")})
- except ValueError:
- pass
-
- def _parseFull(self, input):
- state = 0 # In 'called_by' section
- calls = []
- called_by = []
- current = {}
- for line in input:
- if line[0:6] == "------":
- if len(current):
- current["calls"] = calls
- current["called_by"] = called_by
- self.result.append(current)
- state = 0
- calls = []
- called_by = []
- current = {}
- else:
- try:
- fld1, fld2, fld3, fld4 = line.split(None, 3)
- tmp = {"samples" : fld1,
- "percentage" : fld2,
- "file" : fld3,
- "symbol" : fld4.strip("\n")}
- except ValueError:
- continue
- if line[0] != " ":
- current = tmp
- state = 1 # In 'calls' section
- elif state == 0:
- called_by.append(tmp)
- else:
- calls.append(tmp)
- if len(current):
- current["calls"] = calls
- current["called_by"] = called_by
- self.result.append(current)
-
-
-def main(argv=None):
- opts, args = getopt.getopt(sys.argv[1:], "i:o:h", ["in=", "out=", "help"])
- input_file = sys.stdin
- output_file = sys.stdout
- for o, a in opts:
- if o in ("-i", "--in"):
- input_file = open(a, 'r')
- if o in ("-o", "--out"):
- output_file = open(a, 'w')
- if o in ("-h", "--help"):
- usage()
- sys.exit(0)
-
- oprof = SimPerfOProfileInterface()
- oprof.parse(input_file)
- if input_file != sys.stdin:
- input_file.close()
-
- # Create JSONable dict with interesting data and format/print it
- print >>output_file, simplejson.dumps(oprof.result)
-
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/indra/lib/python/indra/util/simperf_proc_interface.py b/indra/lib/python/indra/util/simperf_proc_interface.py
deleted file mode 100755
index de061f68cc..0000000000
--- a/indra/lib/python/indra/util/simperf_proc_interface.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file simperf_proc_interface.py
-@brief Utility to extract log messages from *.<pid>.llsd files containing performance statistics.
-
-$LicenseInfo:firstyear=2008&license=mit$
-
-Copyright (c) 2008-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-"""
-
-# ----------------------------------------------------
-# Utility to extract log messages from *.<pid>.llsd
-# files that contain performance statistics.
-
-# ----------------------------------------------------
-import sys, os
-
-if os.path.exists("setup-path.py"):
- execfile("setup-path.py")
-
-from indra.base import llsd
-
-DEFAULT_PATH="/dev/shm/simperf/"
-
-
-# ----------------------------------------------------
-# Pull out the stats and return a single document
-def parse_logfile(filename, target_column=None, verbose=False):
- full_doc = []
- # Open source temp log file. Let exceptions percolate up.
- sourcefile = open( filename,'r')
-
- if verbose:
- print "Reading " + filename
-
- # Parse and output all lines from the temp file
- for line in sourcefile.xreadlines():
- partial_doc = llsd.parse(line)
- if partial_doc is not None:
- if target_column is None:
- full_doc.append(partial_doc)
- else:
- trim_doc = { target_column: partial_doc[target_column] }
- if target_column != "fps":
- trim_doc[ 'fps' ] = partial_doc[ 'fps' ]
- trim_doc[ '/total_time' ] = partial_doc[ '/total_time' ]
- trim_doc[ 'utc_time' ] = partial_doc[ 'utc_time' ]
- full_doc.append(trim_doc)
-
- sourcefile.close()
- return full_doc
-
-# Extract just the meta info line, and the timestamp of the first/last frame entry.
-def parse_logfile_info(filename, verbose=False):
- # Open source temp log file. Let exceptions percolate up.
- sourcefile = open(filename, 'rU') # U is to open with Universal newline support
-
- if verbose:
- print "Reading " + filename
-
- # The first line is the meta info line.
- info_line = sourcefile.readline()
- if not info_line:
- sourcefile.close()
- return None
-
- # The rest of the lines are frames. Read the first and last to get the time range.
- info = llsd.parse( info_line )
- info['start_time'] = None
- info['end_time'] = None
- first_frame = sourcefile.readline()
- if first_frame:
- try:
- info['start_time'] = int(llsd.parse(first_frame)['timestamp'])
- except:
- pass
-
- # Read the file backwards to find the last two lines.
- sourcefile.seek(0, 2)
- file_size = sourcefile.tell()
- offset = 1024
- num_attempts = 0
- end_time = None
- if file_size < offset:
- offset = file_size
- while 1:
- sourcefile.seek(-1*offset, 2)
- read_str = sourcefile.read(offset)
- # Remove newline at the end
- if read_str[offset - 1] == '\n':
- read_str = read_str[0:-1]
- lines = read_str.split('\n')
- full_line = None
- if len(lines) > 2: # Got two line
- try:
- end_time = llsd.parse(lines[-1])['timestamp']
- except:
- # We couldn't parse this line. Try once more.
- try:
- end_time = llsd.parse(lines[-2])['timestamp']
- except:
- # Nope. Just move on.
- pass
- break
- if len(read_str) == file_size: # Reached the beginning
- break
- offset += 1024
-
- info['end_time'] = int(end_time)
-
- sourcefile.close()
- return info
-
-
-def parse_proc_filename(filename):
- try:
- name_as_list = filename.split(".")
- cur_stat_type = name_as_list[0].split("_")[0]
- cur_pid = name_as_list[1]
- except IndexError, ValueError:
- return (None, None)
- return (cur_pid, cur_stat_type)
-
-# ----------------------------------------------------
-def get_simstats_list(path=None):
- """ Return stats (pid, type) listed in <type>_proc.<pid>.llsd """
- if path is None:
- path = DEFAULT_PATH
- simstats_list = []
- for file_name in os.listdir(path):
- if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd":
- simstats_info = parse_logfile_info(path + file_name)
- if simstats_info is not None:
- simstats_list.append(simstats_info)
- return simstats_list
-
-def get_log_info_list(pid=None, stat_type=None, path=None, target_column=None, verbose=False):
- """ Return data from all llsd files matching the pid and stat type """
- if path is None:
- path = DEFAULT_PATH
- log_info_list = {}
- for file_name in os.listdir ( path ):
- if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd":
- (cur_pid, cur_stat_type) = parse_proc_filename(file_name)
- if cur_pid is None:
- continue
- if pid is not None and pid != cur_pid:
- continue
- if stat_type is not None and stat_type != cur_stat_type:
- continue
- log_info_list[cur_pid] = parse_logfile(path + file_name, target_column, verbose)
- return log_info_list
-
-def delete_simstats_files(pid=None, stat_type=None, path=None):
- """ Delete *.<pid>.llsd files """
- if path is None:
- path = DEFAULT_PATH
- del_list = []
- for file_name in os.listdir(path):
- if file_name.endswith(".llsd") and file_name != "simperf_proc_config.llsd":
- (cur_pid, cur_stat_type) = parse_proc_filename(file_name)
- if cur_pid is None:
- continue
- if pid is not None and pid != cur_pid:
- continue
- if stat_type is not None and stat_type != cur_stat_type:
- continue
- del_list.append(cur_pid)
- # Allow delete related exceptions to percolate up if this fails.
- os.unlink(os.path.join(DEFAULT_PATH, file_name))
- return del_list
-
diff --git a/indra/lib/python/indra/util/term.py b/indra/lib/python/indra/util/term.py
deleted file mode 100755
index 8c316a1f12..0000000000
--- a/indra/lib/python/indra/util/term.py
+++ /dev/null
@@ -1,222 +0,0 @@
-'''
-@file term.py
-@brief a better shutil.copytree replacement
-
-$LicenseInfo:firstyear=2007&license=mit$
-
-Copyright (c) 2007-2009, Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-$/LicenseInfo$
-'''
-
-#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116
-
-import sys, re
-
-class TerminalController:
- """
- A class that can be used to portably generate formatted output to
- a terminal.
-
- `TerminalController` defines a set of instance variables whose
- values are initialized to the control sequence necessary to
- perform a given action. These can be simply included in normal
- output to the terminal:
-
- >>> term = TerminalController()
- >>> print 'This is '+term.GREEN+'green'+term.NORMAL
-
- Alternatively, the `render()` method can used, which replaces
- '${action}' with the string required to perform 'action':
-
- >>> term = TerminalController()
- >>> print term.render('This is ${GREEN}green${NORMAL}')
-
- If the terminal doesn't support a given action, then the value of
- the corresponding instance variable will be set to ''. As a
- result, the above code will still work on terminals that do not
- support color, except that their output will not be colored.
- Also, this means that you can test whether the terminal supports a
- given action by simply testing the truth value of the
- corresponding instance variable:
-
- >>> term = TerminalController()
- >>> if term.CLEAR_SCREEN:
- ... print 'This terminal supports clearning the screen.'
-
- Finally, if the width and height of the terminal are known, then
- they will be stored in the `COLS` and `LINES` attributes.
- """
- # Cursor movement:
- BOL = '' #: Move the cursor to the beginning of the line
- UP = '' #: Move the cursor up one line
- DOWN = '' #: Move the cursor down one line
- LEFT = '' #: Move the cursor left one char
- RIGHT = '' #: Move the cursor right one char
-
- # Deletion:
- CLEAR_SCREEN = '' #: Clear the screen and move to home position
- CLEAR_EOL = '' #: Clear to the end of the line.
- CLEAR_BOL = '' #: Clear to the beginning of the line.
- CLEAR_EOS = '' #: Clear to the end of the screen
-
- # Output modes:
- BOLD = '' #: Turn on bold mode
- BLINK = '' #: Turn on blink mode
- DIM = '' #: Turn on half-bright mode
- REVERSE = '' #: Turn on reverse-video mode
- NORMAL = '' #: Turn off all modes
-
- # Cursor display:
- HIDE_CURSOR = '' #: Make the cursor invisible
- SHOW_CURSOR = '' #: Make the cursor visible
-
- # Terminal size:
- COLS = None #: Width of the terminal (None for unknown)
- LINES = None #: Height of the terminal (None for unknown)
-
- # Foreground colors:
- BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
-
- # Background colors:
- BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ''
- BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ''
-
- _STRING_CAPABILITIES = """
- BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
- CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
- BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
- HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
- _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
- _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
-
- def __init__(self, term_stream=sys.stdout):
- """
- Create a `TerminalController` and initialize its attributes
- with appropriate values for the current terminal.
- `term_stream` is the stream that will be used for terminal
- output; if this stream is not a tty, then the terminal is
- assumed to be a dumb terminal (i.e., have no capabilities).
- """
- # Curses isn't available on all platforms
- try: import curses
- except: return
-
- # If the stream isn't a tty, then assume it has no capabilities.
- if not term_stream.isatty(): return
-
- # Check the terminal type. If we fail, then assume that the
- # terminal has no capabilities.
- try: curses.setupterm()
- except: return
-
- # Look up numeric capabilities.
- self.COLS = curses.tigetnum('cols')
- self.LINES = curses.tigetnum('lines')
-
- # Look up string capabilities.
- for capability in self._STRING_CAPABILITIES:
- (attrib, cap_name) = capability.split('=')
- setattr(self, attrib, self._tigetstr(cap_name) or '')
-
- # Colors
- set_fg = self._tigetstr('setf')
- if set_fg:
- for i,color in zip(range(len(self._COLORS)), self._COLORS):
- setattr(self, color, curses.tparm(set_fg, i) or '')
- set_fg_ansi = self._tigetstr('setaf')
- if set_fg_ansi:
- for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
- setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
- set_bg = self._tigetstr('setb')
- if set_bg:
- for i,color in zip(range(len(self._COLORS)), self._COLORS):
- setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '')
- set_bg_ansi = self._tigetstr('setab')
- if set_bg_ansi:
- for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
- setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '')
-
- def _tigetstr(self, cap_name):
- # String capabilities can include "delays" of the form "$<2>".
- # For any modern terminal, we should be able to just ignore
- # these, so strip them out.
- import curses
- cap = curses.tigetstr(cap_name) or ''
- return re.sub(r'\$<\d+>[/*]?', '', cap)
-
- def render(self, template):
- """
- Replace each $-substitutions in the given template string with
- the corresponding terminal control string (if it's defined) or
- '' (if it's not).
- """
- return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
-
- def _render_sub(self, match):
- s = match.group()
- if s == '$$': return s
- else: return getattr(self, s[2:-1])
-
-#######################################################################
-# Example use case: progress bar
-#######################################################################
-
-class ProgressBar:
- """
- A 3-line progress bar, which looks like::
-
- Header
- 20% [===========----------------------------------]
- progress message
-
- The progress bar is colored, if the terminal supports color
- output; and adjusts to the width of the terminal.
- """
- BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
- HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
-
- def __init__(self, term, header):
- self.term = term
- if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
- raise ValueError("Terminal isn't capable enough -- you "
- "should use a simpler progress dispaly.")
- self.width = self.term.COLS or 75
- self.bar = term.render(self.BAR)
- self.header = self.term.render(self.HEADER % header.center(self.width))
- self.cleared = 1 #: true if we haven't drawn the bar yet.
- self.update(0, '')
-
- def update(self, percent, message):
- if self.cleared:
- sys.stdout.write(self.header)
- self.cleared = 0
- n = int((self.width-10)*percent)
- sys.stdout.write(
- self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
- (self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
- self.term.CLEAR_EOL + message.center(self.width))
-
- def clear(self):
- if not self.cleared:
- sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
- self.term.UP + self.term.CLEAR_EOL +
- self.term.UP + self.term.CLEAR_EOL)
- self.cleared = 1
diff --git a/indra/lib/python/uuid.py b/indra/lib/python/uuid.py
deleted file mode 100755
index e956383cca..0000000000
--- a/indra/lib/python/uuid.py
+++ /dev/null
@@ -1,508 +0,0 @@
-#!/usr/bin/python
-## $LicenseInfo:firstyear=2011&license=viewerlgpl$
-## Second Life Viewer Source Code
-## Copyright (C) 2011, Linden Research, Inc.
-##
-## This library is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation;
-## version 2.1 of the License only.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with this library; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-## $/LicenseInfo$
-r"""UUID objects (universally unique identifiers) according to RFC 4122.
-
-This module provides immutable UUID objects (class UUID) and the functions
-uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
-UUIDs as specified in RFC 4122.
-
-If all you want is a unique ID, you should probably call uuid1() or uuid4().
-Note that uuid1() may compromise privacy since it creates a UUID containing
-the computer's network address. uuid4() creates a random UUID.
-
-Typical usage:
-
- >>> import uuid
-
- # make a UUID based on the host ID and current time
- >>> uuid.uuid1()
- UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
-
- # make a UUID using an MD5 hash of a namespace UUID and a name
- >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
- UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
-
- # make a random UUID
- >>> uuid.uuid4()
- UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
-
- # make a UUID using a SHA-1 hash of a namespace UUID and a name
- >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
- UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
-
- # make a UUID from a string of hex digits (braces and hyphens ignored)
- >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
-
- # convert a UUID to a string of hex digits in standard form
- >>> str(x)
- '00010203-0405-0607-0809-0a0b0c0d0e0f'
-
- # get the raw 16 bytes of the UUID
- >>> x.bytes
- '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
-
- # make a UUID from a 16-byte string
- >>> uuid.UUID(bytes=x.bytes)
- UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
-
-This module works with Python 2.3 or higher."""
-
-__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
-__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
-__version__ = '$Revision: 1.30 $'.split()[1]
-
-RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
- 'reserved for NCS compatibility', 'specified in RFC 4122',
- 'reserved for Microsoft compatibility', 'reserved for future definition']
-
-class UUID(object):
- """Instances of the UUID class represent UUIDs as specified in RFC 4122.
- UUID objects are immutable, hashable, and usable as dictionary keys.
- Converting a UUID to a string with str() yields something in the form
- '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
- four possible forms: a similar string of hexadecimal digits, or a
- string of 16 raw bytes as an argument named 'bytes', or a tuple of
- six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
- 48-bit values respectively) as an argument named 'fields', or a single
- 128-bit integer as an argument named 'int'.
-
- UUIDs have these read-only attributes:
-
- bytes the UUID as a 16-byte string
-
- fields a tuple of the six integer fields of the UUID,
- which are also available as six individual attributes
- and two derived attributes:
-
- time_low the first 32 bits of the UUID
- time_mid the next 16 bits of the UUID
- time_hi_version the next 16 bits of the UUID
- clock_seq_hi_variant the next 8 bits of the UUID
- clock_seq_low the next 8 bits of the UUID
- node the last 48 bits of the UUID
-
- time the 60-bit timestamp
- clock_seq the 14-bit sequence number
-
- hex the UUID as a 32-character hexadecimal string
-
- int the UUID as a 128-bit integer
-
- urn the UUID as a URN as specified in RFC 4122
-
- variant the UUID variant (one of the constants RESERVED_NCS,
- RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
-
- version the UUID version number (1 through 5, meaningful only
- when the variant is RFC_4122)
- """
-
- def __init__(self, hex=None, bytes=None, fields=None, int=None,
- version=None):
- r"""Create a UUID from either a string of 32 hexadecimal digits,
- a string of 16 bytes as the 'bytes' argument, a tuple of six
- integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
- 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
- the 'fields' argument, or a single 128-bit integer as the 'int'
- argument. When a string of hex digits is given, curly braces,
- hyphens, and a URN prefix are all optional. For example, these
- expressions all yield the same UUID:
-
- UUID('{12345678-1234-5678-1234-567812345678}')
- UUID('12345678123456781234567812345678')
- UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
- UUID(bytes='\x12\x34\x56\x78'*4)
- UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
- UUID(int=0x12345678123456781234567812345678)
-
- Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
- The 'version' argument is optional; if given, the resulting UUID
- will have its variant and version number set according to RFC 4122,
- overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
- """
-
- if [hex, bytes, fields, int].count(None) != 3:
- raise TypeError('need just one of hex, bytes, fields, or int')
- if hex is not None:
- hex = hex.replace('urn:', '').replace('uuid:', '')
- hex = hex.strip('{}').replace('-', '')
- if len(hex) != 32:
- raise ValueError('badly formed hexadecimal UUID string')
- int = long(hex, 16)
- if bytes is not None:
- if len(bytes) != 16:
- raise ValueError('bytes is not a 16-char string')
- int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
- if fields is not None:
- if len(fields) != 6:
- raise ValueError('fields is not a 6-tuple')
- (time_low, time_mid, time_hi_version,
- clock_seq_hi_variant, clock_seq_low, node) = fields
- if not 0 <= time_low < 1<<32L:
- raise ValueError('field 1 out of range (need a 32-bit value)')
- if not 0 <= time_mid < 1<<16L:
- raise ValueError('field 2 out of range (need a 16-bit value)')
- if not 0 <= time_hi_version < 1<<16L:
- raise ValueError('field 3 out of range (need a 16-bit value)')
- if not 0 <= clock_seq_hi_variant < 1<<8L:
- raise ValueError('field 4 out of range (need an 8-bit value)')
- if not 0 <= clock_seq_low < 1<<8L:
- raise ValueError('field 5 out of range (need an 8-bit value)')
- if not 0 <= node < 1<<48L:
- raise ValueError('field 6 out of range (need a 48-bit value)')
- clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
- int = ((time_low << 96L) | (time_mid << 80L) |
- (time_hi_version << 64L) | (clock_seq << 48L) | node)
- if int is not None:
- if not 0 <= int < 1<<128L:
- raise ValueError('int is out of range (need a 128-bit value)')
- if version is not None:
- if not 1 <= version <= 5:
- raise ValueError('illegal version number')
- # Set the variant to RFC 4122.
- int &= ~(0xc000 << 48L)
- int |= 0x8000 << 48L
- # Set the version number.
- int &= ~(0xf000 << 64L)
- int |= version << 76L
- self.__dict__['int'] = int
-
- def __cmp__(self, other):
- if isinstance(other, UUID):
- return cmp(self.int, other.int)
- return NotImplemented
-
- def __hash__(self):
- return hash(self.int)
-
- def __int__(self):
- return self.int
-
- def __repr__(self):
- return 'UUID(%r)' % str(self)
-
- def __setattr__(self, name, value):
- raise TypeError('UUID objects are immutable')
-
- def __str__(self):
- hex = '%032x' % self.int
- return '%s-%s-%s-%s-%s' % (
- hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
-
- def get_bytes(self):
- bytes = ''
- for shift in range(0, 128, 8):
- bytes = chr((self.int >> shift) & 0xff) + bytes
- return bytes
-
- bytes = property(get_bytes)
-
- def get_fields(self):
- return (self.time_low, self.time_mid, self.time_hi_version,
- self.clock_seq_hi_variant, self.clock_seq_low, self.node)
-
- fields = property(get_fields)
-
- def get_time_low(self):
- return self.int >> 96L
-
- time_low = property(get_time_low)
-
- def get_time_mid(self):
- return (self.int >> 80L) & 0xffff
-
- time_mid = property(get_time_mid)
-
- def get_time_hi_version(self):
- return (self.int >> 64L) & 0xffff
-
- time_hi_version = property(get_time_hi_version)
-
- def get_clock_seq_hi_variant(self):
- return (self.int >> 56L) & 0xff
-
- clock_seq_hi_variant = property(get_clock_seq_hi_variant)
-
- def get_clock_seq_low(self):
- return (self.int >> 48L) & 0xff
-
- clock_seq_low = property(get_clock_seq_low)
-
- def get_time(self):
- return (((self.time_hi_version & 0x0fffL) << 48L) |
- (self.time_mid << 32L) | self.time_low)
-
- time = property(get_time)
-
- def get_clock_seq(self):
- return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
- self.clock_seq_low)
-
- clock_seq = property(get_clock_seq)
-
- def get_node(self):
- return self.int & 0xffffffffffff
-
- node = property(get_node)
-
- def get_hex(self):
- return '%032x' % self.int
-
- hex = property(get_hex)
-
- def get_urn(self):
- return 'urn:uuid:' + str(self)
-
- urn = property(get_urn)
-
- def get_variant(self):
- if not self.int & (0x8000 << 48L):
- return RESERVED_NCS
- elif not self.int & (0x4000 << 48L):
- return RFC_4122
- elif not self.int & (0x2000 << 48L):
- return RESERVED_MICROSOFT
- else:
- return RESERVED_FUTURE
-
- variant = property(get_variant)
-
- def get_version(self):
- # The version bits are only meaningful for RFC 4122 UUIDs.
- if self.variant == RFC_4122:
- return int((self.int >> 76L) & 0xf)
-
- version = property(get_version)
-
-def _ifconfig_getnode():
- """Get the hardware address on Unix by running ifconfig."""
- import os
- for dir in ['', '/sbin/', '/usr/sbin']:
- try:
- path = os.path.join(dir, 'ifconfig')
- if os.path.exists(path):
- pipe = os.popen(path)
- else:
- continue
- except IOError:
- continue
- for line in pipe:
- words = line.lower().split()
- for i in range(len(words)):
- if words[i] in ['hwaddr', 'ether']:
- return int(words[i + 1].replace(':', ''), 16)
-
-def _ipconfig_getnode():
- """Get the hardware address on Windows by running ipconfig.exe."""
- import os, re
- dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
- try:
- import ctypes
- buffer = ctypes.create_string_buffer(300)
- ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
- dirs.insert(0, buffer.value.decode('mbcs'))
- except:
- pass
- for dir in dirs:
- try:
- pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')
- except IOError:
- continue
- for line in pipe:
- value = line.split(':')[-1].strip().lower()
- if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
- return int(value.replace('-', ''), 16)
-
-def _netbios_getnode():
- """Get the hardware address on Windows using NetBIOS calls.
- See http://support.microsoft.com/kb/118623 for details."""
- import win32wnet, netbios
- ncb = netbios.NCB()
- ncb.Command = netbios.NCBENUM
- ncb.Buffer = adapters = netbios.LANA_ENUM()
- adapters._pack()
- if win32wnet.Netbios(ncb) != 0:
- return
- adapters._unpack()
- for i in range(adapters.length):
- ncb.Reset()
- ncb.Command = netbios.NCBRESET
- ncb.Lana_num = ord(adapters.lana[i])
- if win32wnet.Netbios(ncb) != 0:
- continue
- ncb.Reset()
- ncb.Command = netbios.NCBASTAT
- ncb.Lana_num = ord(adapters.lana[i])
- ncb.Callname = '*'.ljust(16)
- ncb.Buffer = status = netbios.ADAPTER_STATUS()
- if win32wnet.Netbios(ncb) != 0:
- continue
- status._unpack()
- bytes = map(ord, status.adapter_address)
- return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
- (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
-
-# Thanks to Thomas Heller for ctypes and for his help with its use here.
-
-# If ctypes is available, use it to find system routines for UUID generation.
-_uuid_generate_random = _uuid_generate_time = _UuidCreate = None
-try:
- import ctypes, ctypes.util
- _buffer = ctypes.create_string_buffer(16)
-
- # The uuid_generate_* routines are provided by libuuid on at least
- # Linux and FreeBSD, and provided by libc on Mac OS X.
- for libname in ['uuid', 'c']:
- try:
- lib = ctypes.CDLL(ctypes.util.find_library(libname))
- except:
- continue
- if hasattr(lib, 'uuid_generate_random'):
- _uuid_generate_random = lib.uuid_generate_random
- if hasattr(lib, 'uuid_generate_time'):
- _uuid_generate_time = lib.uuid_generate_time
-
- # On Windows prior to 2000, UuidCreate gives a UUID containing the
- # hardware address. On Windows 2000 and later, UuidCreate makes a
- # random UUID and UuidCreateSequential gives a UUID containing the
- # hardware address. These routines are provided by the RPC runtime.
- try:
- lib = ctypes.windll.rpcrt4
- except:
- lib = None
- _UuidCreate = getattr(lib, 'UuidCreateSequential',
- getattr(lib, 'UuidCreate', None))
-except:
- pass
-
-def _unixdll_getnode():
- """Get the hardware address on Unix using ctypes."""
- _uuid_generate_time(_buffer)
- return UUID(bytes=_buffer.raw).node
-
-def _windll_getnode():
- """Get the hardware address on Windows using ctypes."""
- if _UuidCreate(_buffer) == 0:
- return UUID(bytes=_buffer.raw).node
-
-def _random_getnode():
- """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
- import random
- return random.randrange(0, 1<<48L) | 0x010000000000L
-
-_node = None
-
-def getnode():
- """Get the hardware address as a 48-bit integer. The first time this
- runs, it may launch a separate program, which could be quite slow. If
- all attempts to obtain the hardware address fail, we choose a random
- 48-bit number with its eighth bit set to 1 as recommended in RFC 4122."""
-
- global _node
- if _node is not None:
- return _node
-
- import sys
- if sys.platform == 'win32':
- getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
- else:
- getters = [_unixdll_getnode, _ifconfig_getnode]
-
- for getter in getters + [_random_getnode]:
- try:
- _node = getter()
- except:
- continue
- if _node is not None:
- return _node
-
-def uuid1(node=None, clock_seq=None):
- """Generate a UUID from a host ID, sequence number, and the current time.
- If 'node' is not given, getnode() is used to obtain the hardware
- address. If 'clock_seq' is given, it is used as the sequence number;
- otherwise a random 14-bit sequence number is chosen."""
-
- # When the system provides a version-1 UUID generator, use it (but don't
- # use UuidCreate here because its UUIDs don't conform to RFC 4122).
- if _uuid_generate_time and node is clock_seq is None:
- _uuid_generate_time(_buffer)
- return UUID(bytes=_buffer.raw)
-
- import time
- nanoseconds = int(time.time() * 1e9)
- # 0x01b21dd213814000 is the number of 100-ns intervals between the
- # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
- timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
- if clock_seq is None:
- import random
- clock_seq = random.randrange(1<<14L) # instead of stable storage
- time_low = timestamp & 0xffffffffL
- time_mid = (timestamp >> 32L) & 0xffffL
- time_hi_version = (timestamp >> 48L) & 0x0fffL
- clock_seq_low = clock_seq & 0xffL
- clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
- if node is None:
- node = getnode()
- return UUID(fields=(time_low, time_mid, time_hi_version,
- clock_seq_hi_variant, clock_seq_low, node), version=1)
-
-def uuid3(namespace, name):
- """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
- try:
- # Python 2.6
- from hashlib import md5
- except ImportError:
- # Python 2.5 and earlier
- from md5 import new as md5
-
- hash = md5(namespace.bytes + name).digest()
- return UUID(bytes=hash[:16], version=3)
-
-def uuid4():
- """Generate a random UUID."""
-
- # When the system provides a version-4 UUID generator, use it.
- if _uuid_generate_random:
- _uuid_generate_random(_buffer)
- return UUID(bytes=_buffer.raw)
-
- # Otherwise, get randomness from urandom or the 'random' module.
- try:
- import os
- return UUID(bytes=os.urandom(16), version=4)
- except:
- import random
- bytes = [chr(random.randrange(256)) for i in range(16)]
- return UUID(bytes=bytes, version=4)
-
-def uuid5(namespace, name):
- """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
- import sha
- hash = sha.sha(namespace.bytes + name).digest()
- return UUID(bytes=hash[:16], version=5)
-
-# The following standard UUIDs are for use with uuid3() or uuid5().
-
-NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
-NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
-NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
-NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
diff --git a/indra/linux_crash_logger/linux_crash_logger.cpp b/indra/linux_crash_logger/linux_crash_logger.cpp
index 9d5ec33fed..63e5409876 100644
--- a/indra/linux_crash_logger/linux_crash_logger.cpp
+++ b/indra/linux_crash_logger/linux_crash_logger.cpp
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
return 1;
}
- app.mainLoop();
+ app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
return 0;
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp
index e2d2e7ff26..4092d43fc5 100644
--- a/indra/linux_crash_logger/llcrashloggerlinux.cpp
+++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp
@@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
{
}
-bool LLCrashLoggerLinux::mainLoop()
+bool LLCrashLoggerLinux::frame()
{
bool send_logs = true;
if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.h b/indra/linux_crash_logger/llcrashloggerlinux.h
index dae6c46651..789f6f03f5 100644
--- a/indra/linux_crash_logger/llcrashloggerlinux.h
+++ b/indra/linux_crash_logger/llcrashloggerlinux.h
@@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger
public:
LLCrashLoggerLinux(void);
~LLCrashLoggerLinux(void);
- virtual bool mainLoop();
+ virtual bool frame();
virtual void updateApplication(const std::string& = LLStringUtil::null);
virtual void gatherPlatformSpecificFiles();
virtual bool cleanup();
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index cd201a65b4..e786dfff86 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -2149,7 +2149,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
LLCharacter* character = *char_iter;
// look for an existing instance of this motion
- LLKeyframeMotion* motionp = (LLKeyframeMotion*) character->findMotion(asset_uuid);
+ LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
if (motionp)
{
if (0 == status)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 907dbab8f8..0468015bfa 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -10,7 +10,6 @@ include(Boost)
include(LLSharedLibs)
include(JsonCpp)
include(GoogleBreakpad)
-include(GooglePerfTools)
include(Copy3rdPartyLibs)
include(ZLIB)
include(URIPARSER)
@@ -58,6 +57,7 @@ set(llcommon_SOURCE_FILES
lleventfilter.cpp
llevents.cpp
lleventtimer.cpp
+ llexception.cpp
llfasttimer.cpp
llfile.cpp
llfindlocale.cpp
@@ -157,6 +157,7 @@ set(llcommon_HEADER_FILES
lleventfilter.h
llevents.h
lleventemitter.h
+ llexception.h
llfasttimer.h
llfile.h
llfindlocale.h
@@ -244,13 +245,13 @@ list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
if(LLCOMMON_LINK_SHARED)
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
- if(NOT WORD_SIZE EQUAL 32)
+ if(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ ##add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
- endif(NOT WORD_SIZE EQUAL 32)
+ endif(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
# always generate llcommon.pdb, even for "Release" builds
set_target_properties(llcommon PROPERTIES LINK_FLAGS "/DEBUG")
@@ -315,7 +316,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
- LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
@@ -328,8 +329,9 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
- # *TODO - reenable these once tcmalloc libs no longer break the build.
- #ADD_BUILD_TEST(llallocator llcommon)
- #ADD_BUILD_TEST(llallocator_heap_profile llcommon)
- #ADD_BUILD_TEST(llmemtype llcommon)
+## llexception_test.cpp isn't a regression test, and doesn't need to be run
+## every build. It's to help a developer make implementation choices about
+## throwing and catching exceptions.
+##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}")
+
endif (LL_TESTS)
diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp
index 34fc28d8cc..ac97fb71dd 100644
--- a/indra/llcommon/llallocator.cpp
+++ b/indra/llcommon/llallocator.cpp
@@ -27,47 +27,6 @@
#include "linden_common.h"
#include "llallocator.h"
-#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER)
-
-#include "google/heap-profiler.h"
-#include "google/commandlineflags_public.h"
-
-DECLARE_bool(heap_profile_use_stack_trace);
-//DECLARE_double(tcmalloc_release_rate);
-
-void LLAllocator::setProfilingEnabled(bool should_enable)
-{
- // NULL disables dumping to disk
- static char const * const PREFIX = NULL;
- if(should_enable)
- {
- HeapProfilerSetUseStackTrace(false);
- HeapProfilerStart(PREFIX);
- }
- else
- {
- HeapProfilerStop();
- }
-}
-
-// static
-bool LLAllocator::isProfiling()
-{
- return IsHeapProfilerRunning();
-}
-
-std::string LLAllocator::getRawProfile()
-{
- // *TODO - fix google-perftools to accept an buffer to avoid this
- // malloc-copy-free cycle.
- char * buffer = GetHeapProfile();
- std::string ret = buffer;
- free(buffer);
- return ret;
-}
-
-#else // LL_USE_TCMALLOC
-
//
// stub implementations for when tcmalloc is disabled
//
@@ -87,8 +46,6 @@ std::string LLAllocator::getRawProfile()
return std::string();
}
-#endif // LL_USE_TCMALLOC
-
LLAllocatorHeapProfile const & LLAllocator::getProfile()
{
mProf.mLines.clear();
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index d9933b3d36..ff9a92b45f 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -172,12 +172,12 @@ public:
virtual bool cleanup() = 0; // Override to do application cleanup
//
- // mainLoop()
+ // frame()
//
- // Runs the application main loop. It's assumed that when you exit
- // this method, the application is in one of the cleanup states, either QUITTING or ERROR
+ // Pass control to the application for a single frame. Returns 'done'
+ // flag: if frame() returns false, it expects to be called again.
//
- virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
+ virtual bool frame() = 0; // Override for application body logic
//
// Crash logging
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index a548c96002..86f407cdb0 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -294,9 +294,11 @@ void LLScopedLock::unlock()
bool ll_apr_warn_status(apr_status_t status)
{
if(APR_SUCCESS == status) return false;
+#if !LL_LINUX
char buf[MAX_STRING]; /* Flawfinder: ignore */
apr_strerror(status, buf, sizeof(buf));
LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
+#endif
return true;
}
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index d16bf0160b..bc72faca5d 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -38,6 +38,7 @@
#include "llevents.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
// do nothing, when we need nothing done
void LLCoros::no_cleanup(CoroData*) {}
@@ -100,7 +101,11 @@ LLCoros::LLCoros():
// Previously we used
// boost::context::guarded_stack_allocator::default_stacksize();
// empirically this is 64KB on Windows and Linux. Try quadrupling.
+#if ADDRESS_SIZE == 64
+ mStackSize(512*1024)
+#else
mStackSize(256*1024)
+#endif
{
// Register our cleanup() method for "mainloop" ticks
LLEventPumps::instance().obtain("mainloop").listen(
@@ -131,9 +136,9 @@ bool LLCoros::cleanup(const LLSD&)
if ((previousCount < 5) || !(previousCount % 50))
{
if (previousCount < 5)
- LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
else
- LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
}
// The erase() call will invalidate its passed iterator value --
@@ -185,9 +190,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
if ((previousCount < 5) || !(previousCount % 50))
{
if (previousCount < 5)
- LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
else
- LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
}
@@ -223,7 +228,7 @@ std::string LLCoros::getName() const
void LLCoros::setStackSize(S32 stacksize)
{
- LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
+ LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
mStackSize = stacksize;
}
@@ -235,7 +240,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
// capture the 'self' param in CoroData
data->mSelf = &self;
// run the code the caller actually wants in the coroutine
- callable();
+ try
+ {
+ callable();
+ }
+ catch (const LLContinueError&)
+ {
+ // Any uncaught exception derived from LLContinueError will be caught
+ // here and logged. This coroutine will terminate but the rest of the
+ // viewer will carry on.
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
+ catch (...)
+ {
+ // Any OTHER kind of uncaught exception will cause the viewer to
+ // crash, hopefully informatively.
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
// This cleanup isn't perfectly symmetrical with the way we initially set
// data->mPrev, but this is our last chance to reset mCurrentCoro.
sCurrentCoro.reset(data->mPrev);
diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp
index 0e72c175cb..0d5757effd 100644
--- a/indra/llcommon/lldependencies.cpp
+++ b/indra/llcommon/lldependencies.cpp
@@ -40,6 +40,7 @@
#include <boost/graph/topological_sort.hpp>
#include <boost/graph/exception.hpp>
// other Linden headers
+#include "llexception.h"
LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
{
@@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const
// Omit independent nodes: display only those that might contribute to
// the cycle.
describe(out, false);
- throw Cycle(out.str());
+ LLTHROW(Cycle(out.str()));
}
// A peculiarity of boost::topological_sort() is that it emits results in
// REVERSE topological order: to get the result you want, you must
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
index e0294e271b..db2bbab8b0 100644
--- a/indra/llcommon/lldependencies.h
+++ b/indra/llcommon/lldependencies.h
@@ -34,13 +34,13 @@
#include <vector>
#include <set>
#include <map>
-#include <stdexcept>
#include <iosfwd>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
+#include "llexception.h"
/*****************************************************************************
* Utilities
@@ -106,9 +106,9 @@ public:
/**
* Exception thrown by sort() if there's a cycle
*/
- struct Cycle: public std::runtime_error
+ struct Cycle: public LLException
{
- Cycle(const std::string& what): std::runtime_error(what) {}
+ Cycle(const std::string& what): LLException(what) {}
};
/**
@@ -124,8 +124,8 @@ public:
virtual std::string describe(bool full=true) const;
protected:
- typedef std::vector< std::pair<int, int> > EdgeList;
- typedef std::vector<int> VertexList;
+ typedef std::vector< std::pair<std::size_t, std::size_t> > EdgeList;
+ typedef std::vector<std::size_t> VertexList;
VertexList topo_sort(int vertices, const EdgeList& edges) const;
/**
@@ -508,7 +508,7 @@ public:
// been explicitly added. Rely on std::map rejecting a second attempt
// to insert the same key. Use the map's size() as the vertex number
// to get a distinct value for each successful insertion.
- typedef std::map<KEY, int> VertexMap;
+ typedef std::map<KEY, std::size_t> VertexMap;
VertexMap vmap;
// Nest each of these loops because !@#$%? MSVC warns us that its
// former broken behavior has finally been fixed -- and our builds
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 5ed348e13c..6a62860c3f 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -921,11 +921,6 @@ namespace
std::ostringstream message_stream;
- if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
- {
- message_stream << site.mLocationString << " ";
- }
-
if (show_time && r->wantsTime() && s->mTimeFunction != NULL)
{
message_stream << s->mTimeFunction() << " ";
@@ -933,17 +928,17 @@ namespace
if (show_level && r->wantsLevel())
{
- message_stream << site.mLevelString;
+ message_stream << site.mLevelString << " ";
}
if (show_tags && r->wantsTags())
{
message_stream << site.mTagString;
}
- if ((show_level && r->wantsLevel())||
- (show_tags && r->wantsTags()))
+
+ if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
{
- message_stream << " ";
+ message_stream << site.mLocationString << " ";
}
if (show_function && r->wantsFunctionName())
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 3beef65723..7cbe4334b3 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -174,7 +174,8 @@ namespace LLError
// not really a level
// used to indicate that no messages should be logged
};
-
+ // If you change ELevel, please update llvlog() macro below.
+
/* Macro support
The classes CallSite and Log are used by the logging macros below.
They are not intended for general use.
@@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
/////////////////////////////////
// Error Logging Macros
-// See top of file for common usage.
+// See top of file for common usage.
/////////////////////////////////
-// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements
-// without braces:
-// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL
-
-#define lllog(level, once, ...) \
- do { \
- const char* tags[] = {"", ##__VA_ARGS__}; \
- ::size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \
- static LLError::CallSite _site( \
- level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
- if (LL_UNLIKELY(_site.shouldLog())) \
- { \
- std::ostringstream* _out = LLError::Log::out(); \
+// Instead of using LL_DEBUGS(), LL_INFOS() et al., it may be tempting to
+// directly code the lllog() macro so you can pass in the LLError::ELevel as a
+// variable. DON'T DO IT! The reason is that the first time control passes
+// through lllog(), it initializes a local static LLError::CallSite with that
+// *first* ELevel value. All subsequent visits will decide whether or not to
+// emit output based on the *first* ELevel value bound into that static
+// CallSite instance. Use LL_VLOGS() instead. lllog() assumes its ELevel
+// argument never varies.
+
+// this macro uses a one-shot do statement to avoid parsing errors when
+// writing control flow statements without braces:
+// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL;
+
+#define lllog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
+ lllog_test_()
+
+#define lllog_test_() \
+ if (LL_UNLIKELY(_site.shouldLog())) \
+ { \
+ std::ostringstream* _out = LLError::Log::out(); \
(*_out)
+#define lllog_site_args_(level, once, tags) \
+ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
+ __FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
+
//Use this construct if you need to do computation in the middle of a
//message:
//
@@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
+// Use this if you need to pass LLError::ELevel as a variable.
+#define LL_VLOGS(level, ...) llvlog(level, false, ##__VA_ARGS__)
+#define LL_VLOGS_ONCE(level, ...) llvlog(level, true, ##__VA_ARGS__)
+
+// The problem with using lllog() with a variable level is that the first time
+// through, it initializes a static CallSite instance with whatever level you
+// pass. That first level is bound into the CallSite; the level parameter is
+// never again examined. One approach to variable level would be to
+// dynamically construct a CallSite instance every call -- which could get
+// expensive, depending on context. So instead, initialize a static CallSite
+// for each level value we support, then dynamically select the CallSite
+// instance for the passed level value.
+// Compare implementation to lllog() above.
+#define llvlog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ /* Need a static CallSite instance per expected ELevel value. */ \
+ /* Since we intend to index this array with the ELevel, */ \
+ /* _sites[0] should be ELevel(0), and so on -- avoid using */ \
+ /* ELevel symbolic names when initializing -- except for */ \
+ /* the last entry, which handles anything beyond the end. */ \
+ /* (Commented ELevel value names are from 2016-09-01.) */ \
+ /* Passing an ELevel past the end of this array is itself */ \
+ /* a fatal error, so ensure the last is LEVEL_ERROR. */ \
+ static LLError::CallSite _sites[] = \
+ { \
+ /* LEVEL_DEBUG */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
+ /* LEVEL_INFO */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
+ /* LEVEL_WARN */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
+ /* LEVEL_ERROR */ \
+ LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
+ }; \
+ /* Clamp the passed 'level' to at most last entry */ \
+ std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
+ (LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
+ /* selected CallSite *must* be named _site for LL_ENDL */ \
+ LLError::CallSite& _site(_sites[which]); \
+ lllog_test_()
+
#endif // LL_LLERROR_H
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 2d5f964deb..56367b8f54 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -39,6 +39,7 @@
#include "llerror.h"
#include "llcoros.h"
#include "llmake.h"
+#include "llexception.h"
#include "lleventfilter.h"
@@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)
// returning it, deliver it via exception.
if (result.second)
{
- throw LLErrorEvent(desc, result.first);
+ LLTHROW(LLErrorEvent(desc, result.first));
}
// That way, our caller knows a simple return must be from the reply
// pump (pump 0).
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index 87926c692d..84827aab4a 100644
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -31,10 +31,10 @@
#include <boost/optional.hpp>
#include <string>
-#include <stdexcept>
#include <utility> // std::pair
#include "llevents.h"
#include "llerror.h"
+#include "llexception.h"
/**
* Like LLListenerOrPumpName, this is a class intended for parameter lists:
@@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc);
* because it's not an error in event processing: rather, this exception
* announces an event that bears error information (for some other API).
*/
-class LL_COMMON_API LLErrorEvent: public std::runtime_error
+class LL_COMMON_API LLErrorEvent: public LLException
{
public:
LLErrorEvent(const std::string& what, const LLSD& data):
- std::runtime_error(what),
+ LLException(what),
mData(data)
{}
virtual ~LLErrorEvent() throw() {}
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 645c29d770..97270e4931 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -57,6 +57,7 @@
#include "stringize.h"
#include "llerror.h"
#include "llsdutil.h"
+#include "llexception.h"
#if LL_MSVC
#pragma warning (disable : 4702)
#endif
@@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string
// Unless we're permitted to tweak it, that's Bad.
if (! tweak)
{
- throw LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'");
+ LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'"));
}
// The passed name isn't unique, but we're permitted to tweak it. Find the
// first decimal-integer suffix not already taken. The insert() attempt
@@ -275,6 +276,8 @@ LLEventPumps::~LLEventPumps()
#pragma warning (push)
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
+const std::string LLEventPump::ANONYMOUS = std::string();
+
LLEventPump::LLEventPump(const std::string& name, bool tweak):
// Register every new instance with LLEventPumps
@@ -313,145 +316,162 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
const NameList& after,
const NameList& before)
{
- // Check for duplicate name before connecting listener to mSignal
- ConnectionMap::const_iterator found = mConnections.find(name);
- // In some cases the user might disconnect a connection explicitly -- or
- // might use LLEventTrackable to disconnect implicitly. Either way, we can
- // end up retaining in mConnections a zombie connection object that's
- // already been disconnected. Such a connection object can't be
- // reconnected -- nor, in the case of LLEventTrackable, would we want to
- // try, since disconnection happens with the destruction of the listener
- // object. That means it's safe to overwrite a disconnected connection
- // object with the new one we're attempting. The case we want to prevent
- // is only when the existing connection object is still connected.
- if (found != mConnections.end() && found->second.connected())
- {
- throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
- "' on " + typeid(*this).name() + " '" + getName() + "'");
- }
- // Okay, name is unique, try to reconcile its dependencies. Specify a new
- // "node" value that we never use for an mSignal placement; we'll fix it
- // later.
- DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before);
- // What if this listener has been added, removed and re-added? In that
- // case newNode already has a non-negative value because we never remove a
- // listener from mDeps. But keep processing uniformly anyway in case the
- // listener was added back with different dependencies. Then mDeps.sort()
- // would put it in a different position, and the old newNode placement
- // value would be wrong, so we'd have to reassign it anyway. Trust that
- // re-adding a listener with the same dependencies is the trivial case for
- // mDeps.sort(): it can just replay its cache.
- DependencyMap::sorted_range sorted_range;
- try
- {
- // Can we pick an order that works including this new entry?
- sorted_range = mDeps.sort();
- }
- catch (const DependencyMap::Cycle& e)
- {
- // No: the new node's after/before dependencies have made mDeps
- // unsortable. If we leave the new node in mDeps, it will continue
- // to screw up all future attempts to sort()! Pull it out.
- mDeps.remove(name);
- throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
- " '" + getName() + "' would cause cycle: " + e.what());
- }
- // Walk the list to verify that we haven't changed the order.
- float previous = 0.0, myprev = 0.0;
- DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop
- for (DependencyMap::sorted_iterator dmi = sorted_range.begin();
- dmi != sorted_range.end(); ++dmi)
+ float nodePosition = 1.0;
+
+ // if the supplied name is empty we are not interested in the ordering mechanism
+ // and can bypass attempting to find the optimal location to insert the new
+ // listener. We'll just tack it on to the end.
+ if (!name.empty()) // should be the same as testing against ANONYMOUS
{
- // Since we've added the new entry with an invalid placement,
- // recognize it and skip it.
- if (dmi->first == name)
+ // Check for duplicate name before connecting listener to mSignal
+ ConnectionMap::const_iterator found = mConnections.find(name);
+ // In some cases the user might disconnect a connection explicitly -- or
+ // might use LLEventTrackable to disconnect implicitly. Either way, we can
+ // end up retaining in mConnections a zombie connection object that's
+ // already been disconnected. Such a connection object can't be
+ // reconnected -- nor, in the case of LLEventTrackable, would we want to
+ // try, since disconnection happens with the destruction of the listener
+ // object. That means it's safe to overwrite a disconnected connection
+ // object with the new one we're attempting. The case we want to prevent
+ // is only when the existing connection object is still connected.
+ if (found != mConnections.end() && found->second.connected())
{
- // Remember the iterator belonging to our new node, and which
- // placement value was 'previous' at that point.
- mydmi = dmi;
- myprev = previous;
- continue;
+ LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name +
+ "' on " + typeid(*this).name() + " '" + getName() + "'"));
}
- // If the new node has rearranged the existing nodes, we'll find
- // that their placement values are no longer in increasing order.
- if (dmi->second < previous)
+ // Okay, name is unique, try to reconcile its dependencies. Specify a new
+ // "node" value that we never use for an mSignal placement; we'll fix it
+ // later.
+ DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before);
+ // What if this listener has been added, removed and re-added? In that
+ // case newNode already has a non-negative value because we never remove a
+ // listener from mDeps. But keep processing uniformly anyway in case the
+ // listener was added back with different dependencies. Then mDeps.sort()
+ // would put it in a different position, and the old newNode placement
+ // value would be wrong, so we'd have to reassign it anyway. Trust that
+ // re-adding a listener with the same dependencies is the trivial case for
+ // mDeps.sort(): it can just replay its cache.
+ DependencyMap::sorted_range sorted_range;
+ try
{
- // This is another scenario in which we'd better back out the
- // newly-added node from mDeps -- but don't do it yet, we want to
- // traverse the existing mDeps to report on it!
- // Describe the change to the order of our listeners. Copy
- // everything but the newest listener to a vector we can sort to
- // obtain the old order.
- typedef std::vector< std::pair<float, std::string> > SortNameList;
- SortNameList sortnames;
- for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end());
- cdmi != cdmend; ++cdmi)
+ // Can we pick an order that works including this new entry?
+ sorted_range = mDeps.sort();
+ }
+ catch (const DependencyMap::Cycle& e)
+ {
+ // No: the new node's after/before dependencies have made mDeps
+ // unsortable. If we leave the new node in mDeps, it will continue
+ // to screw up all future attempts to sort()! Pull it out.
+ mDeps.remove(name);
+ LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() +
+ " '" + getName() + "' would cause cycle: " + e.what()));
+ }
+ // Walk the list to verify that we haven't changed the order.
+ float previous = 0.0, myprev = 0.0;
+ DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop
+ for (DependencyMap::sorted_iterator dmi = sorted_range.begin();
+ dmi != sorted_range.end(); ++dmi)
+ {
+ // Since we've added the new entry with an invalid placement,
+ // recognize it and skip it.
+ if (dmi->first == name)
{
- if (cdmi->first != name)
- {
- sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first));
- }
+ // Remember the iterator belonging to our new node, and which
+ // placement value was 'previous' at that point.
+ mydmi = dmi;
+ myprev = previous;
+ continue;
}
- std::sort(sortnames.begin(), sortnames.end());
- std::ostringstream out;
- out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName()
- << "' would move previous listener '" << dmi->first << "'\nwas: ";
- SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end());
- if (sni != snend)
+ // If the new node has rearranged the existing nodes, we'll find
+ // that their placement values are no longer in increasing order.
+ if (dmi->second < previous)
{
- out << sni->second;
- while (++sni != snend)
+ // This is another scenario in which we'd better back out the
+ // newly-added node from mDeps -- but don't do it yet, we want to
+ // traverse the existing mDeps to report on it!
+ // Describe the change to the order of our listeners. Copy
+ // everything but the newest listener to a vector we can sort to
+ // obtain the old order.
+ typedef std::vector< std::pair<float, std::string> > SortNameList;
+ SortNameList sortnames;
+ for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end());
+ cdmi != cdmend; ++cdmi)
{
- out << ", " << sni->second;
+ if (cdmi->first != name)
+ {
+ sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first));
+ }
}
- }
- out << "\nnow: ";
- DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end());
- if (ddmi != ddmend)
- {
- out << ddmi->first;
- while (++ddmi != ddmend)
+ std::sort(sortnames.begin(), sortnames.end());
+ std::ostringstream out;
+ out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName()
+ << "' would move previous listener '" << dmi->first << "'\nwas: ";
+ SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end());
+ if (sni != snend)
{
- out << ", " << ddmi->first;
+ out << sni->second;
+ while (++sni != snend)
+ {
+ out << ", " << sni->second;
+ }
}
+ out << "\nnow: ";
+ DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end());
+ if (ddmi != ddmend)
+ {
+ out << ddmi->first;
+ while (++ddmi != ddmend)
+ {
+ out << ", " << ddmi->first;
+ }
+ }
+ // NOW remove the offending listener node.
+ mDeps.remove(name);
+ // Having constructed a description of the order change, inform caller.
+ LLTHROW(OrderChange(out.str()));
}
- // NOW remove the offending listener node.
- mDeps.remove(name);
- // Having constructed a description of the order change, inform caller.
- throw OrderChange(out.str());
+ // This node becomes the previous one.
+ previous = dmi->second;
}
- // This node becomes the previous one.
- previous = dmi->second;
- }
- // We just got done with a successful mDeps.add(name, ...) call. We'd
- // better have found 'name' somewhere in that sorted list!
- assert(mydmi != sorted_range.end());
- // Four cases:
- // 0. name is the only entry: placement 1.0
- // 1. name is the first of several entries: placement (next placement)/2
- // 2. name is between two other entries: placement (myprev + (next placement))/2
- // 3. name is the last entry: placement ceil(myprev) + 1.0
- // Since we've cleverly arranged for myprev to be 0.0 if name is the
- // first entry, this folds down to two cases. Case 1 is subsumed by
- // case 2, and case 0 is subsumed by case 3. So we need only handle
- // cases 2 and 3, which means we need only detect whether name is the
- // last entry. Increment mydmi to see if there's anything beyond.
- if (++mydmi != sorted_range.end())
- {
- // The new node isn't last. Place it between the previous node and
- // the successor.
- newNode = (myprev + mydmi->second)/2.f;
- }
- else
- {
- // The new node is last. Bump myprev up to the next integer, add
- // 1.0 and use that.
- newNode = std::ceil(myprev) + 1.f;
+ // We just got done with a successful mDeps.add(name, ...) call. We'd
+ // better have found 'name' somewhere in that sorted list!
+ assert(mydmi != sorted_range.end());
+ // Four cases:
+ // 0. name is the only entry: placement 1.0
+ // 1. name is the first of several entries: placement (next placement)/2
+ // 2. name is between two other entries: placement (myprev + (next placement))/2
+ // 3. name is the last entry: placement ceil(myprev) + 1.0
+ // Since we've cleverly arranged for myprev to be 0.0 if name is the
+ // first entry, this folds down to two cases. Case 1 is subsumed by
+ // case 2, and case 0 is subsumed by case 3. So we need only handle
+ // cases 2 and 3, which means we need only detect whether name is the
+ // last entry. Increment mydmi to see if there's anything beyond.
+ if (++mydmi != sorted_range.end())
+ {
+ // The new node isn't last. Place it between the previous node and
+ // the successor.
+ newNode = (myprev + mydmi->second) / 2.f;
+ }
+ else
+ {
+ // The new node is last. Bump myprev up to the next integer, add
+ // 1.0 and use that.
+ newNode = std::ceil(myprev) + 1.f;
+ }
+
+ nodePosition = newNode;
}
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.
- LLBoundListener bound = mSignal->connect(newNode, listener);
- mConnections[name] = bound;
+ LLBoundListener bound = mSignal->connect(nodePosition, listener);
+
+ if (!name.empty())
+ { // note that we are not tracking anonymous listeners here either.
+ // This means that it is the caller's responsibility to either assign
+ // to a TempBoundListerer (scoped_connection) or manually disconnect
+ // when done.
+ mConnections[name] = bound;
+ }
return bound;
}
@@ -608,7 +628,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
{
if (! mListener)
{
- throw Empty("attempting to call uninitialized");
+ LLTHROW(Empty("attempting to call uninitialized"));
}
return (*mListener)(event);
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index ba4fcd766e..a3b9ec02e0 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -37,7 +37,6 @@
#include <set>
#include <vector>
#include <deque>
-#include <stdexcept>
#if LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
@@ -62,6 +61,7 @@
#include "llsingleton.h"
#include "lldependencies.h"
#include "llstl.h"
+#include "llexception.h"
/*==========================================================================*|
// override this to allow binding free functions with more parameters
@@ -95,12 +95,32 @@ struct LLStopWhenHandled
result_type operator()(InputIterator first, InputIterator last) const
{
for (InputIterator si = first; si != last; ++si)
- {
- if (*si)
- {
- return true;
- }
- }
+ {
+ try
+ {
+ if (*si)
+ {
+ return true;
+ }
+ }
+ catch (const LLContinueError&)
+ {
+ // We catch LLContinueError here because an LLContinueError-
+ // based exception means the viewer as a whole should carry on
+ // to the best of our ability. Therefore subsequent listeners
+ // on the same LLEventPump should still receive this event.
+
+ // The iterator passed to a boost::signals2 Combiner is very
+ // clever, but provides no contextual information. We would
+ // very much like to be able to log the name of the LLEventPump
+ // plus the name of this particular listener, but alas.
+ LOG_UNHANDLED_EXCEPTION("LLEventPump");
+ }
+ // We do NOT catch (...) here because we might as well let it
+ // propagate out to the generic handler. If we were able to log
+ // context information here, that would be great, but we can't, so
+ // there's no point.
+ }
return false;
}
};
@@ -188,10 +208,10 @@ public:
bool operator()(const LLSD& event) const;
/// exception if you try to call when empty
- struct Empty: public std::runtime_error
+ struct Empty: public LLException
{
Empty(const std::string& what):
- std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
+ LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {}
};
private:
@@ -365,16 +385,18 @@ typedef boost::signals2::trackable LLEventTrackable;
class LL_COMMON_API LLEventPump: public LLEventTrackable
{
public:
+ static const std::string ANONYMOUS; // constant for anonymous listeners.
+
/**
* Exception thrown by LLEventPump(). You are trying to instantiate an
* LLEventPump (subclass) using the same name as some other instance, and
* you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
* variant.
*/
- struct DupPumpName: public std::runtime_error
+ struct DupPumpName: public LLException
{
DupPumpName(const std::string& what):
- std::runtime_error(std::string("DupPumpName: ") + what) {}
+ LLException(std::string("DupPumpName: ") + what) {}
};
/**
@@ -399,9 +421,9 @@ public:
/// group exceptions thrown by listen(). We use exceptions because these
/// particular errors are likely to be coding errors, found and fixed by
/// the developer even before preliminary checkin.
- struct ListenError: public std::runtime_error
+ struct ListenError: public LLException
{
- ListenError(const std::string& what): std::runtime_error(what) {}
+ ListenError(const std::string& what): LLException(what) {}
};
/**
* exception thrown by listen(). You are attempting to register a
@@ -476,6 +498,12 @@ public:
* instantiate your listener, then passing the same name on each listen()
* call, allows us to optimize away the second and subsequent dependency
* sorts.
+ *
+ * If name is set to LLEventPump::ANONYMOUS listen will bypass the entire
+ * dependency and ordering calculation. In this case, it is critical that
+ * the result be assigned to a LLTempBoundListener or the listener is
+ * manually disconnected when no longer needed since there will be no
+ * way to later find and disconnect this listener manually.
*
* If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
* listener, listen() will inspect the components of that expression. If a
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
new file mode 100644
index 0000000000..b32ec2c9c9
--- /dev/null
+++ b/indra/llcommon/llexception.cpp
@@ -0,0 +1,55 @@
+/**
+ * @file llexception.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-12
+ * @brief Implementation for llexception.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llexception.h"
+// STL headers
+// std headers
+#include <typeinfo>
+// external library headers
+#include <boost/exception/diagnostic_information.hpp>
+// other Linden headers
+#include "llerror.h"
+#include "llerrorcontrol.h"
+
+namespace {
+// used by crash_on_unhandled_exception_() and log_unhandled_exception_()
+void log_unhandled_exception_(LLError::ELevel level,
+ const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // log same message but allow caller-specified severity level
+ LL_VLOGS(level, "LLException") << LLError::abbreviateFile(file)
+ << "(" << line << "): Unhandled exception caught in " << pretty_function;
+ if (! context.empty())
+ {
+ LL_CONT << ": " << context;
+ }
+ LL_CONT << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL;
+}
+}
+
+void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // LL_ERRS() terminates and propagates message into crash dump.
+ log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context);
+}
+
+void log_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
+{
+ // Use LL_WARNS() because we seriously do not expect this to happen
+ // routinely, but we DO expect to return from this function.
+ log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function, context);
+}
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
new file mode 100644
index 0000000000..dfcb7c192f
--- /dev/null
+++ b/indra/llcommon/llexception.h
@@ -0,0 +1,85 @@
+/**
+ * @file llexception.h
+ * @author Nat Goodspeed
+ * @date 2016-06-29
+ * @brief Types needed for generic exception handling
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEXCEPTION_H)
+#define LL_LLEXCEPTION_H
+
+#include <stdexcept>
+#include <boost/exception/exception.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/current_function.hpp>
+
+// "Found someone who can comfort me
+// But there are always exceptions..."
+// - Empty Pages, Traffic, from John Barleycorn (1970)
+// https://www.youtube.com/watch?v=dRH0CGVK7ic
+
+/**
+ * LLException is intended as the common base class from which all
+ * viewer-specific exceptions are derived. Rationale for why it's derived from
+ * both std::exception and boost::exception is explained in
+ * tests/llexception_test.cpp.
+ *
+ * boost::current_exception_diagnostic_information() is quite wonderful: if
+ * all we need to do with an exception is log it, in most places we should
+ * catch (...) and log boost::current_exception_diagnostic_information().
+ * See CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() below.
+ *
+ * There may be circumstances in which it would be valuable to distinguish an
+ * exception explicitly thrown by viewer code from an exception thrown by
+ * (say) a third-party library. Catching (const LLException&) supports such
+ * usage. However, most of the value of this base class is in the
+ * diagnostic_information() available via Boost.Exception.
+ */
+struct LLException:
+ public std::runtime_error,
+ public boost::exception
+{
+ LLException(const std::string& what):
+ std::runtime_error(what)
+ {}
+};
+
+/**
+ * The point of LLContinueError is to distinguish exceptions that need not
+ * terminate the whole viewer session. In general, an uncaught exception will
+ * be logged and will crash the viewer. However, though an uncaught exception
+ * derived from LLContinueError will still be logged, the viewer will attempt
+ * to continue processing.
+ */
+struct LLContinueError: public LLException
+{
+ LLContinueError(const std::string& what):
+ LLException(what)
+ {}
+};
+
+/**
+ * Please use LLTHROW() to throw viewer exceptions whenever possible. This
+ * enriches the exception's diagnostic_information() with the source file,
+ * line and containing function of the LLTHROW() macro.
+ */
+// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in
+// LLTHROW() in case we ever want to revisit that implementation decision.
+#define LLTHROW(x) BOOST_THROW_EXCEPTION(x)
+
+/// Call this macro from a catch (...) clause
+#define CRASH_ON_UNHANDLED_EXCEPTION(CONTEXT) \
+ crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void crash_on_unhandled_exception_(const char*, int, const char*, const std::string&);
+
+/// Call this from a catch (const LLContinueError&) clause, or from a catch
+/// (...) clause in which you do NOT want the viewer to crash.
+#define LOG_UNHANDLED_EXCEPTION(CONTEXT) \
+ log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void log_unhandled_exception_(const char*, int, const char*, const std::string&);
+
+#endif /* ! defined(LL_LLEXCEPTION_H) */
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 2370253078..2024d707da 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -90,33 +90,15 @@ public:
#if LL_FASTTIMER_USE_RDTSC
static U32 getCPUClockCount32()
{
- U32 ret_val;
- __asm
- {
- _emit 0x0f
- _emit 0x31
- shr eax,8
- shl edx,24
- or eax, edx
- mov dword ptr [ret_val], eax
- }
- return ret_val;
+ unsigned __int64 val = __rdtsc();
+ val = val >> 8;
+ return static_cast<U32>(val);
}
// return full timer value, *not* shifted by 8 bits
static U64 getCPUClockCount64()
{
- U64 ret_val;
- __asm
- {
- _emit 0x0f
- _emit 0x31
- mov eax,eax
- mov edx,edx
- mov dword ptr [ret_val+4], edx
- mov dword ptr [ret_val], eax
- }
- return ret_val;
+ return static_cast<U64>( __rdtsc() );
}
#else
@@ -173,16 +155,16 @@ public:
// Mac+Linux+Solaris FAST x86 implementation of CPU clock
static U32 getCPUClockCount32()
{
- U64 x;
- __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
- return (U32)(x >> 8);
+ U32 low(0),high(0);
+ __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
+ return (low>>8) | (high<<24);
}
static U64 getCPUClockCount64()
{
- U64 x;
- __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
- return x;
+ U32 low(0),high(0);
+ __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
+ return (U64)low | ( ((U64)high) << 32);
}
#endif
@@ -296,7 +278,16 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
{
#if LL_FAST_TIMER_ON
BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- if (!cur_timer_data) return;
+ if (!cur_timer_data)
+ {
+ // How likely is it that
+ // LLThreadLocalSingletonPointer<T>::getInstance() will return NULL?
+ // Even without researching, what we can say is that if we exit
+ // without setting mStartTime at all, gcc 4.7 produces (fatal)
+ // warnings about a possibly-uninitialized data member.
+ mStartTime = 0;
+ return;
+ }
TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
accumulator.mActiveCount++;
// keep current parent as long as it is active when we are
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 3e25228aeb..315e18e4f2 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -45,7 +45,7 @@ typedef FILE LLFILE;
typedef struct _stat llstat;
#else
typedef struct stat llstat;
-#include <bits/postypes.h>
+#include <sys/types.h>
#endif
#ifndef S_ISREG
diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h
index 401e4d759a..feb5f41848 100644
--- a/indra/llcommon/llhandle.h
+++ b/indra/llcommon/llhandle.h
@@ -28,8 +28,11 @@
#define LLHANDLE_H
#include "llpointer.h"
+#include "llexception.h"
+#include <stdexcept>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
+#include <boost/throw_exception.hpp>
/**
* Helper object for LLHandle. Don't instantiate these directly, used
@@ -213,4 +216,82 @@ private:
mutable LLRootHandle<T> mHandle;
};
+
+
+class LLCheckedHandleBase
+{
+public:
+ class Stale : public LLException
+ {
+ public:
+ Stale() :
+ LLException("Attempt to access stale handle.")
+ {}
+ };
+
+protected:
+ LLCheckedHandleBase() { }
+
+};
+
+/**
+ * This is a simple wrapper for Handles, allowing direct calls to the underlying
+ * pointer. The checked handle will throw a Stale if an attempt
+ * is made to access the object referenced by the handle and that object has
+ * been destroyed.
+ **/
+template <typename T>
+class LLCheckedHandle: public LLCheckedHandleBase
+{
+public:
+
+ LLCheckedHandle(LLHandle<T> handle):
+ mHandle(handle)
+ { }
+
+ /**
+ * Test the underlying handle. If it is no longer valid, throw a Stale exception.
+ */
+ void check() const
+ {
+ T* ptr = mHandle.get();
+ if (!ptr)
+ BOOST_THROW_EXCEPTION(Stale());
+ }
+
+ /**
+ * Cast back to an appropriate handle
+ */
+ operator LLHandle<T>() const
+ {
+ return mHandle;
+ }
+
+ /**
+ * Converts the LLCheckedHandle to a bool. Allows for if (chkdHandle) {}
+ * Does not throw.
+ */
+ /*explicit*/ operator bool() const // explicit conversion operator not available with Linux compiler
+ {
+ return (mHandle.get() != NULL);
+ }
+
+ /**
+ * Attempt to call a method or access a member in the structure referenced
+ * by the handle. If the handle no longer points to a valid structure
+ * throw a Stale.
+ */
+ T* operator ->() const
+ {
+ T* ptr = mHandle.get();
+ if (!ptr)
+ BOOST_THROW_EXCEPTION(Stale());
+ return ptr;
+ }
+
+private:
+
+ LLHandle<T> mHandle;
+};
+
#endif
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 84d2a12f65..c87d2a3e58 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -33,6 +33,7 @@
#include "lltimer.h"
#include "lluuid.h"
#include "llleaplistener.h"
+#include "llexception.h"
#if LL_MSVC
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
@@ -69,7 +70,7 @@ public:
// Rule out empty vector
if (plugin.empty())
{
- throw Error("no plugin command");
+ LLTHROW(Error("no plugin command"));
}
// Don't leave desc empty either, but in this case, if we weren't
@@ -112,7 +113,7 @@ public:
// If that didn't work, no point in keeping this LLLeap object.
if (! mChild)
{
- throw Error(STRINGIZE("failed to run " << mDesc));
+ LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));
}
// Okay, launch apparently worked. Change our mDonePump listener.
diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h
index e33f25e530..8aac8a64c5 100644
--- a/indra/llcommon/llleap.h
+++ b/indra/llcommon/llleap.h
@@ -13,9 +13,9 @@
#define LL_LLLEAP_H
#include "llinstancetracker.h"
+#include "llexception.h"
#include <string>
#include <vector>
-#include <stdexcept>
/**
* LLSD Event API Plugin class. Because instances are managed by
@@ -67,9 +67,9 @@ public:
* string(s) passed to create() might come from an external source. This
* way the caller can catch LLLeap::Error and try to recover.
*/
- struct Error: public std::runtime_error
+ struct Error: public LLException
{
- Error(const std::string& what): std::runtime_error(what) {}
+ Error(const std::string& what): LLException(what) {}
};
virtual ~LLLeap();
diff --git a/indra/llcommon/llmake.h b/indra/llcommon/llmake.h
index 9a662a0640..08744f90fb 100644
--- a/indra/llcommon/llmake.h
+++ b/indra/llcommon/llmake.h
@@ -12,12 +12,10 @@
*
* also relevant:
*
- * Template parameter deduction for constructors
- * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0091r0.html
- *
- * https://github.com/viboes/std-make
- *
- * but obviously we're not there yet.
+ * Template argument deduction for class templates
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html
+ * was apparently adopted in June 2016? Unclear when compilers will
+ * portably support this, but there is hope.
*
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Copyright (c) 2015, Linden Research, Inc.
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 3a8eabac09..1e04044269 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -591,7 +591,7 @@ char* LLPrivateMemoryPool::LLMemoryBlock::allocate()
void LLPrivateMemoryPool::LLMemoryBlock::freeMem(void* addr)
{
//bit index
- U32 idx = ((U32)addr - (U32)mBuffer - mDummySize) / mSlotSize ;
+ uintptr_t idx = ((uintptr_t)addr - (uintptr_t)mBuffer - mDummySize) / mSlotSize ;
U32* bits = &mUsageBits ;
if(idx >= 32)
@@ -773,7 +773,7 @@ char* LLPrivateMemoryPool::LLMemoryChunk::allocate(U32 size)
void LLPrivateMemoryPool::LLMemoryChunk::freeMem(void* addr)
{
- U32 blk_idx = getPageIndex((U32)addr) ;
+ U32 blk_idx = getPageIndex((uintptr_t)addr) ;
LLMemoryBlock* blk = (LLMemoryBlock*)(mMetaBuffer + blk_idx * sizeof(LLMemoryBlock)) ;
blk = blk->mSelf ;
@@ -798,7 +798,7 @@ bool LLPrivateMemoryPool::LLMemoryChunk::empty()
bool LLPrivateMemoryPool::LLMemoryChunk::containsAddress(const char* addr) const
{
- return (U32)mBuffer <= (U32)addr && (U32)mBuffer + mBufferSize > (U32)addr ;
+ return (uintptr_t)mBuffer <= (uintptr_t)addr && (uintptr_t)mBuffer + mBufferSize > (uintptr_t)addr ;
}
//debug use
@@ -831,13 +831,13 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
for(U32 i = 1 ; i < blk_list.size(); i++)
{
total_size += blk_list[i]->getBufferSize() ;
- if((U32)blk_list[i]->getBuffer() < (U32)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
+ if((uintptr_t)blk_list[i]->getBuffer() < (uintptr_t)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
{
LL_ERRS() << "buffer corrupted." << LL_ENDL ;
}
}
- llassert_always(total_size + mMinBlockSize >= mBufferSize - ((U32)mDataBuffer - (U32)mBuffer)) ;
+ llassert_always(total_size + mMinBlockSize >= mBufferSize - ((uintptr_t)mDataBuffer - (uintptr_t)mBuffer)) ;
U32 blk_num = (mBufferSize - (mDataBuffer - mBuffer)) / mMinBlockSize ;
for(U32 i = 0 ; i < blk_num ; )
@@ -860,7 +860,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
#endif
#if 0
LL_INFOS() << "---------------------------" << LL_ENDL ;
- LL_INFOS() << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << LL_ENDL ;
+ LL_INFOS() << "Chunk buffer: " << (uintptr_t)getBuffer() << " size: " << getBufferSize() << LL_ENDL ;
LL_INFOS() << "available blocks ... " << LL_ENDL ;
for(S32 i = 0 ; i < mBlockLevels ; i++)
@@ -868,7 +868,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
LLMemoryBlock* blk = mAvailBlockList[i] ;
while(blk)
{
- LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
+ LL_INFOS() << "blk buffer " << (uintptr_t)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
blk = blk->mNext ;
}
}
@@ -879,7 +879,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
LLMemoryBlock* blk = mFreeSpaceList[i] ;
while(blk)
{
- LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
+ LL_INFOS() << "blk buffer " << (uintptr_t)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
blk = blk->mNext ;
}
}
@@ -1155,9 +1155,9 @@ void LLPrivateMemoryPool::LLMemoryChunk::addToAvailBlockList(LLMemoryBlock* blk)
return ;
}
-U32 LLPrivateMemoryPool::LLMemoryChunk::getPageIndex(U32 addr)
+U32 LLPrivateMemoryPool::LLMemoryChunk::getPageIndex(uintptr_t addr)
{
- return (addr - (U32)mDataBuffer) / mMinBlockSize ;
+ return (addr - (uintptr_t)mDataBuffer) / mMinBlockSize ;
}
//for mAvailBlockList
@@ -1495,7 +1495,7 @@ void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk)
U16 LLPrivateMemoryPool::findHashKey(const char* addr)
{
- return (((U32)addr) / CHUNK_SIZE) % mHashFactor ;
+ return (((uintptr_t)addr) / CHUNK_SIZE) % mHashFactor ;
}
LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::findChunk(const char* addr)
@@ -1720,7 +1720,7 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
S32 k = 0 ;
for(mem_allocation_info_t::iterator iter = sMemAllocationTracker.begin() ; iter != sMemAllocationTracker.end() ; ++iter)
{
- LL_INFOS() << k++ << ", " << (U32)iter->first << " : " << iter->second << LL_ENDL ;
+ LL_INFOS() << k++ << ", " << (uintptr_t)iter->first << " : " << iter->second << LL_ENDL ;
}
sMemAllocationTracker.clear() ;
}
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 0fb257aab1..5a3c9bd762 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -110,11 +110,15 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
#else
+ char* aligned = NULL;
void* mem = malloc( size + (align - 1) + sizeof(void*) );
- char* aligned = ((char*)mem) + sizeof(void*);
- aligned += align - ((uintptr_t)aligned & (align - 1));
+ if (mem)
+ {
+ aligned = ((char*)mem) + sizeof(void*);
+ aligned += align - ((uintptr_t)aligned & (align - 1));
- ((void**)aligned)[-1] = mem;
+ ((void**)aligned)[-1] = mem;
+ }
return aligned;
#endif
}
@@ -134,7 +138,6 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
-#if !LL_USE_TCMALLOC
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
{
#if defined(LL_WINDOWS)
@@ -183,13 +186,6 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r
#endif
}
-#else // USE_TCMALLOC
-// ll_aligned_foo_16 are not needed with tcmalloc
-#define ll_aligned_malloc_16 malloc
-#define ll_aligned_realloc_16(a,b,c) realloc(a,b)
-#define ll_aligned_free_16 free
-#endif // USE_TCMALLOC
-
inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32().
{
#if defined(LL_WINDOWS)
@@ -419,7 +415,7 @@ public:
{
bool operator()(const LLMemoryBlock* const& lhs, const LLMemoryBlock* const& rhs)
{
- return (U32)lhs->getBuffer() < (U32)rhs->getBuffer();
+ return (uintptr_t)lhs->getBuffer() < (uintptr_t)rhs->getBuffer();
}
};
};
@@ -450,7 +446,7 @@ public:
void dump() ;
private:
- U32 getPageIndex(U32 addr) ;
+ U32 getPageIndex(uintptr_t addr) ;
U32 getBlockLevel(U32 size) ;
U16 getPageLevel(U32 size) ;
LLMemoryBlock* addBlock(U32 blk_idx) ;
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 2c4bcc91f6..3698d9db44 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -138,6 +138,12 @@
#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
+
+#if ADDRESS_SIZE == 64
+// That one is all over the place for x64 builds.
+#pragma warning( disable : 4267 ) // 'var' : conversion from 'size_t' to 'type', possible loss of data)
+#endif
+
#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
#pragma warning( disable : 4996 ) // warning: deprecated
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 44f56daf2d..8c321d06b9 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -34,6 +34,7 @@
#include "llapr.h"
#include "apr_signal.h"
#include "llevents.h"
+#include "llexception.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
@@ -472,9 +473,9 @@ private:
*****************************************************************************/
/// Need an exception to avoid constructing an invalid LLProcess object, but
/// internal use only
-struct LLProcessError: public std::runtime_error
+struct LLProcessError: public LLException
{
- LLProcessError(const std::string& msg): std::runtime_error(msg) {}
+ LLProcessError(const std::string& msg): LLException(msg) {}
};
LLProcessPtr LLProcess::create(const LLSDOrParams& params)
@@ -530,8 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
if (! params.validateBlock(true))
{
- throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
- << LLSDNotationStreamer(params)));
+ LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
+ << LLSDNotationStreamer(params))));
}
mPostend = params.postend;
@@ -596,10 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):
}
else
{
- throw LLProcessError(STRINGIZE("For " << params.executable()
- << ": unsupported FileParam for " << which
- << ": type='" << fparam.type()
- << "', name='" << fparam.name() << "'"));
+ LLTHROW(LLProcessError(STRINGIZE("For " << params.executable()
+ << ": unsupported FileParam for " << which
+ << ": type='" << fparam.type()
+ << "', name='" << fparam.name() << "'")));
}
}
// By default, pass APR_NO_PIPE for unspecified slots.
@@ -678,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
gAPRPoolp)))
{
- throw LLProcessError(STRINGIZE(params << " failed"));
+ LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
}
// arrange to call status_callback()
@@ -1063,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)
PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
if (! wp)
{
- throw NoPipe(error);
+ LLTHROW(NoPipe(error));
}
return *wp;
}
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 43ccadc412..bfac4567a5 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -30,13 +30,13 @@
#include "llinitparam.h"
#include "llsdparam.h"
#include "llwin32headerslean.h"
+#include "llexception.h"
#include "apr_thread_proc.h"
#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/optional.hpp>
#include <boost/noncopyable.hpp>
#include <iosfwd> // std::ostream
-#include <stdexcept>
#if LL_WINDOWS
#include "llwin32headerslean.h" // for HANDLE
@@ -479,9 +479,9 @@ public:
/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
/// create a pipe at the corresponding FILESLOT.
- struct NoPipe: public std::runtime_error
+ struct NoPipe: public LLException
{
- NoPipe(const std::string& what): std::runtime_error(what) {}
+ NoPipe(const std::string& what): LLException(what) {}
};
/**
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index e3e1d0c391..65b4507e2d 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -398,7 +398,7 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)
HANDLE hThread = GetCurrentThread();
unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
int iCurThreadPriority = GetThreadPriority(hThread);
- unsigned long dwProcessMask, dwSystemMask, dwNewMask = 1;
+ DWORD_PTR dwProcessMask, dwSystemMask, dwNewMask = 1;
GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index c3f235c6ee..52255bfaeb 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -63,7 +63,7 @@ void set_thread_name( DWORD dwThreadID, const char* threadName)
__try
{
- ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
+ ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
index 185f0d63fb..491f920c0f 100644
--- a/indra/llcommon/llthreadsafequeue.cpp
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -27,6 +27,7 @@
#include <apr_pools.h>
#include <apr_queue.h>
#include "llthreadsafequeue.h"
+#include "llexception.h"
@@ -41,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
{
if(mOwnsPool) {
apr_status_t status = apr_pool_create(&mPool, 0);
- if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool");
+ if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));
} else {
; // No op.
}
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
- if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue");
+ if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
}
@@ -68,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)
apr_status_t status = apr_queue_push(mQueue, element);
if(status == APR_EINTR) {
- throw LLThreadSafeQueueInterrupt();
+ LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
- throw LLThreadSafeQueueError("push failed");
+ LLTHROW(LLThreadSafeQueueError("push failed"));
} else {
; // Success.
}
@@ -88,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)
apr_status_t status = apr_queue_pop(mQueue, &element);
if(status == APR_EINTR) {
- throw LLThreadSafeQueueInterrupt();
+ LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
- throw LLThreadSafeQueueError("pop failed");
+ LLTHROW(LLThreadSafeQueueError("pop failed"));
} else {
return element;
}
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 58cac38769..45289ef0b4 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -27,9 +27,8 @@
#ifndef LL_LLTHREADSAFEQUEUE_H
#define LL_LLTHREADSAFEQUEUE_H
-
+#include "llexception.h"
#include <string>
-#include <stdexcept>
struct apr_pool_t; // From apr_pools.h
@@ -40,11 +39,11 @@ class LLThreadSafeQueueImplementation; // See below.
// A general queue exception.
//
class LL_COMMON_API LLThreadSafeQueueError:
-public std::runtime_error
+ public LLException
{
public:
LLThreadSafeQueueError(std::string const & message):
- std::runtime_error(message)
+ LLException(message)
{
; // No op.
}
diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp
index 82d0dc8b4b..c275b90120 100644
--- a/indra/llcommon/lluriparser.cpp
+++ b/indra/llcommon/lluriparser.cpp
@@ -205,9 +205,9 @@ void LLUriParser::glue(std::string& uri) const
uri = first_part + second_part;
}
-void LLUriParser::glueFirst(std::string& uri) const
+void LLUriParser::glueFirst(std::string& uri, bool use_scheme) const
{
- if (mScheme.size())
+ if (use_scheme && mScheme.size())
{
uri = mScheme;
uri += "://";
diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h
index 2df8085ae6..cfbf54f3c8 100644
--- a/indra/llcommon/lluriparser.h
+++ b/indra/llcommon/lluriparser.h
@@ -60,7 +60,7 @@ public:
void extractParts();
void glue(std::string& uri) const;
- void glueFirst(std::string& uri) const;
+ void glueFirst(std::string& uri, bool use_scheme = true) const;
void glueSecond(std::string& uri) const;
bool test() const;
S32 normalize();
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index e3671047b4..d4af2c6b01 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data )
unsigned int ret = 0;
for( int ix = 0; ix < 5; ++ix ) {
char * s = strchr( encodeTable, fiveChars[ ix ] );
-if( s == 0 ) throw bad_input_data();
+if( s == 0 ) LLTHROW(bad_input_data());
ret = ret * 85 + (s-encodeTable);
}
return ret;
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index f51279e817..20de205454 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -237,8 +237,21 @@ namespace tut
void ErrorTestObject::test<4>()
// file abbreviation
{
- std::string thisFile = __FILE__;
- std::string abbreviateFile = LLError::abbreviateFile(thisFile);
+ std::string prev, abbreviateFile = __FILE__;
+ do
+ {
+ prev = abbreviateFile;
+ abbreviateFile = LLError::abbreviateFile(abbreviateFile);
+ // __FILE__ is assumed to end with
+ // indra/llcommon/tests/llerror_test.cpp. This test used to call
+ // abbreviateFile() exactly once, then check below whether it
+ // still contained the string 'indra'. That fails if the FIRST
+ // part of the pathname also contains indra! Certain developer
+ // machine images put local directory trees under
+ // /ngi-persist/indra, which is where we observe the problem. So
+ // now, keep calling abbreviateFile() until it returns its
+ // argument unchanged, THEN check.
+ } while (abbreviateFile != prev);
ensure_ends_with("file name abbreviation",
abbreviateFile,
@@ -551,9 +564,9 @@ namespace tut
function;
writeReturningLocationAndFunction(location, function);
- ensure_equals("order is location time type function message",
+ ensure_equals("order is time location type function message",
message(0),
- location + roswell() + " INFO: " + function + ": apple");
+ roswell() + " INFO: " + location + function + ": apple");
}
template<> template<>
diff --git a/indra/llcommon/tests/llexception_test.cpp b/indra/llcommon/tests/llexception_test.cpp
new file mode 100644
index 0000000000..6bee1943c2
--- /dev/null
+++ b/indra/llcommon/tests/llexception_test.cpp
@@ -0,0 +1,308 @@
+/**
+ * @file llexception_test.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-12
+ * @brief Tests for throwing exceptions.
+ *
+ * This isn't a regression test: it doesn't need to be run every build, which
+ * is why the corresponding line in llcommon/CMakeLists.txt is commented out.
+ * Rather it's a head-to-head test of what kind of exception information we
+ * can collect from various combinations of exception base classes, type of
+ * throw verb and sequences of catch clauses.
+ *
+ * This "test" makes no ensure() calls: its output goes to stdout for human
+ * examination.
+ *
+ * As of 2016-08-12 with Boost 1.57, we come to the following conclusions.
+ * These should probably be re-examined from time to time as we update Boost.
+ *
+ * - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than
+ * plain throw. The macro annotates the exception object with the filename,
+ * line number and function name from which the exception was thrown.
+ *
+ * - That being the case, deriving only from boost::exception isn't an option.
+ * Every exception object passed to BOOST_THROW_EXCEPTION() must be derived
+ * directly or indirectly from std::exception. The only question is whether
+ * to also derive from boost::exception. We decided to derive LLException
+ * from both, as it makes message output slightly cleaner, but this is a
+ * trivial reason: if a strong reason emerges to prefer single inheritance,
+ * dropping the boost::exception base class shouldn't be a problem.
+ *
+ * - (As you will have guessed, ridiculous things like a char* or int or a
+ * class derived from neither boost::exception nor std::exception can only
+ * be caught by that specific type or (...), and
+ * boost::current_exception_diagnostic_information() simply throws up its
+ * hands and confesses utter ignorance. Stay away from such nonsense.)
+ *
+ * - But if you derive from std::exception, to nat's surprise,
+ * boost::current_exception_diagnostic_information() gives as much
+ * information about exceptions in a catch (...) clause as you can get from
+ * a specific catch (const std::exception&) clause, notably the concrete
+ * exception class and the what() string. So instead of a sequence like
+ *
+ * try { ... }
+ * catch (const boost::exception& e) { ... boost-flavored logging ... }
+ * catch (const std::exception& e) { ... std::exception logging ... }
+ * catch (...) { ... generic logging ... }
+ *
+ * we should be able to get away with only a catch (...) clause that logs
+ * boost::current_exception_diagnostic_information().
+ *
+ * - Going further: boost::current_exception_diagnostic_information() provides
+ * just as much information even within a std::set_terminate() handler. So
+ * it might not even be strictly necessary to include a catch (...) clause
+ * since the viewer does use std::set_terminate().
+ *
+ * - (We might consider adding a catch (int) clause because Kakadu internally
+ * throws ints, and who knows if one of those might leak out. If it does,
+ * boost::current_exception_diagnostic_information() can do nothing with it.
+ * A catch (int) clause could at least log the value and rethrow.)
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llexception.h"
+// STL headers
+// std headers
+#include <typeinfo>
+// external library headers
+#include <boost/throw_exception.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+// helper for display output
+// usage: std::cout << center(some string value, fill char, width) << std::endl;
+// (assumes it's the only thing on that particular line)
+struct center
+{
+ center(const std::string& label, char fill, std::size_t width):
+ mLabel(label),
+ mFill(fill),
+ mWidth(width)
+ {}
+
+ // Use friend declaration not because we need to grant access, but because
+ // it lets us declare a free operator like a member function.
+ friend std::ostream& operator<<(std::ostream& out, const center& ctr)
+ {
+ std::size_t padded = ctr.mLabel.length() + 2;
+ std::size_t left = (ctr.mWidth - padded) / 2;
+ std::size_t right = ctr.mWidth - left - padded;
+ return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' '
+ << std::string(right, ctr.mFill);
+ }
+
+ std::string mLabel;
+ char mFill;
+ std::size_t mWidth;
+};
+
+/*****************************************************************************
+* Four kinds of exceptions: derived from boost::exception, from
+* std::exception, from both, from neither
+*****************************************************************************/
+// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION()
+// (which we want) -- we reach a failure topped by this comment:
+// //All boost exceptions are required to derive from std::exception,
+// //to ensure compatibility with BOOST_NO_EXCEPTIONS.
+struct FromBoost: public boost::exception
+{
+ FromBoost(const std::string& what): mWhat(what) {}
+ ~FromBoost() throw() {}
+ std::string what() const { return mWhat; }
+ std::string mWhat;
+};
+
+struct FromStd: public std::runtime_error
+{
+ FromStd(const std::string& what): std::runtime_error(what) {}
+};
+
+struct FromBoth: public boost::exception, public std::runtime_error
+{
+ FromBoth(const std::string& what): std::runtime_error(what) {}
+};
+
+// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION().
+struct FromNeither
+{
+ FromNeither(const std::string& what): mWhat(what) {}
+ std::string what() const { return mWhat; }
+ std::string mWhat;
+};
+
+/*****************************************************************************
+* Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION()
+*****************************************************************************/
+template <typename EXC>
+void plain_throw(const std::string& what)
+{
+ throw EXC(what);
+}
+
+template <typename EXC>
+void boost_throw(const std::string& what)
+{
+ BOOST_THROW_EXCEPTION(EXC(what));
+}
+
+// Okay, for completeness, functions that throw non-class values. We wouldn't
+// even deign to consider these if we hadn't found examples in our own source
+// code! (Note that Kakadu's internal exception support is still based on
+// throwing ints.)
+void throw_char_ptr(const std::string& what)
+{
+ throw what.c_str(); // umm...
+}
+
+void throw_int(const std::string& what)
+{
+ throw int(what.length());
+}
+
+/*****************************************************************************
+* Three sequences of catch clauses:
+* boost::exception then ...,
+* std::exception then ...,
+* or just ...
+*****************************************************************************/
+void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (const boost::exception& e)
+ {
+ std::cout << "catch (const boost::exception& e)" << std::endl;
+ std::cout << "e is " << typeid(e).name() << std::endl;
+ std::cout << "boost::diagnostic_information(e):\n'"
+ << boost::diagnostic_information(e) << "'" << std::endl;
+ // no way to report e.what()
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "catch (const std::exception& e)" << std::endl;
+ std::cout << "e is " << typeid(e).name() << std::endl;
+ std::cout << "boost::diagnostic_information(e):\n'"
+ << boost::diagnostic_information(e) << "'" << std::endl;
+ std::cout << "e.what: '"
+ << e.what() << "'" << std::endl;
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
+{
+ try
+ {
+ thrower(what);
+ }
+ catch (...)
+ {
+ std::cout << "catch (...)" << std::endl;
+ std::cout << "boost::current_exception_diagnostic_information():\n'"
+ << boost::current_exception_diagnostic_information() << "'"
+ << std::endl;
+ }
+}
+
+/*****************************************************************************
+* Try a particular kind of throw against each of three catch sequences
+*****************************************************************************/
+void catch_several(void (*thrower)(const std::string&), const std::string& what)
+{
+ std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl;
+ catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")");
+
+ std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl;
+ catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")");
+
+ std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl;
+ catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")");
+}
+
+/*****************************************************************************
+* For a particular kind of exception, try both kinds of throw against all
+* three catch sequences
+*****************************************************************************/
+template <typename EXC>
+void catch_both_several(const std::string& what)
+{
+ std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl;
+ catch_several(plain_throw<EXC>, "plain_throw<" + what + ">");
+
+ std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl;
+ catch_several(boost_throw<EXC>, "boost_throw<" + what + ">");
+}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llexception_data
+ {
+ };
+ typedef test_group<llexception_data> llexception_group;
+ typedef llexception_group::object object;
+ llexception_group llexceptiongrp("llexception");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("throwing exceptions");
+
+ // For each kind of exception, try both kinds of throw against all
+ // three catch sequences
+ std::size_t margin = 72;
+ std::cout << center("FromStd", '=', margin) << std::endl;
+ catch_both_several<FromStd>("FromStd");
+
+ std::cout << center("FromBoth", '=', margin) << std::endl;
+ catch_both_several<FromBoth>("FromBoth");
+
+ std::cout << center("FromBoost", '=', margin) << std::endl;
+ // can't throw with BOOST_THROW_EXCEPTION(), just use catch_several()
+ catch_several(plain_throw<FromBoost>, "plain_throw<FromBoost>");
+
+ std::cout << center("FromNeither", '=', margin) << std::endl;
+ // can't throw this with BOOST_THROW_EXCEPTION() either
+ catch_several(plain_throw<FromNeither>, "plain_throw<FromNeither>");
+
+ std::cout << center("const char*", '=', margin) << std::endl;
+ // We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft
+ // as a const char* or an int, so don't bother with
+ // catch_both_several() -- just catch_several().
+ catch_several(throw_char_ptr, "throw_char_ptr");
+
+ std::cout << center("int", '=', margin) << std::endl;
+ catch_several(throw_int, "throw_int");
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index d342dece84..c387da6c48 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -110,10 +110,7 @@ namespace tut
// finding indra/lib/python. Use our __FILE__, with
// raw-string syntax to deal with Windows pathnames.
"mydir = os.path.dirname(r'" << __FILE__ << "')\n"
- // We expect mydir to be .../indra/llcommon/tests.
- "sys.path.insert(0,\n"
- " os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n"
- "from indra.base import llsd\n"
+ "from llbase import llsd\n"
"\n"
"class ProtocolError(Exception):\n"
" def __init__(self, msg, data):\n"
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 6fbb9abfc0..81b930e1e2 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1518,10 +1518,7 @@ namespace tut
// scanner.
import_llsd("import os.path\n"
"import sys\n"
- "sys.path.insert(0,\n"
- " os.path.join(os.path.dirname(r'" __FILE__ "'),\n"
- " os.pardir, os.pardir, 'lib', 'python'))\n"
- "from indra.base import llsd\n")
+ "from llbase import llsd\n")
{}
~TestPythonCompatible() {}
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 785197ba11..9a4bbbd630 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -35,13 +35,13 @@
#include <tut/tut.hpp>
#include "llerrorcontrol.h"
+#include "llexception.h"
#include "stringize.h"
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <list>
#include <string>
-#include <stdexcept>
// statically reference the function in test.cpp... it's short, we could
// replicate, but better to reuse
@@ -67,9 +67,9 @@ struct WrapLLErrs
LLError::restoreSettings(mPriorErrorSettings);
}
- struct FatalException: public std::runtime_error
+ struct FatalException: public LLException
{
- FatalException(const std::string& what): std::runtime_error(what) {}
+ FatalException(const std::string& what): LLException(what) {}
};
void operator()(const std::string& message)
@@ -78,7 +78,7 @@ struct WrapLLErrs
error = message;
// Also throw an appropriate exception since calling code is likely to
// assume that control won't continue beyond LL_ERRS.
- throw FatalException(message);
+ LLTHROW(FatalException(message));
}
std::string error;
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index 0bb0348d26..6f362df921 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -213,7 +213,7 @@ endif (DARWIN)
# The following come from LLAddBuildTest.cmake's INTEGRATION_TEST_xxxx target.
set_target_properties(http_texture_load
PROPERTIES
- LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:CONSOLE ${TCMALLOC_LINK_FLAGS}"
+ LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:CONSOLE"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
LINK_FLAGS_RELEASE ""
)
diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py
index 04cde651c4..3ec9cd7d4c 100755
--- a/indra/llcorehttp/tests/test_llcorehttp_peer.py
+++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py
@@ -42,10 +42,13 @@ except ImportError:
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
-mydir = os.path.dirname(__file__) # expected to be .../indra/llcorehttp/tests/
-sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
-from indra.util.fastest_elementtree import parse as xml_parse
-from indra.base import llsd
+from llbase.fastest_elementtree import parse as xml_parse
+from llbase import llsd
+
+# we're in llcorehttp/tests ; testrunner.py is found in llmessage/tests
+sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
+ "llmessage", "tests"))
+
from testrunner import freeport, run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
diff --git a/indra/llcorehttp/tests/testrunner.py b/indra/llcorehttp/tests/testrunner.py
deleted file mode 100755
index 9a2de71142..0000000000
--- a/indra/llcorehttp/tests/testrunner.py
+++ /dev/null
@@ -1,265 +0,0 @@
-#!/usr/bin/env python
-"""\
-@file testrunner.py
-@author Nat Goodspeed
-@date 2009-03-20
-@brief Utilities for writing wrapper scripts for ADD_COMM_BUILD_TEST unit tests
-
-$LicenseInfo:firstyear=2009&license=viewerlgpl$
-Second Life Viewer Source Code
-Copyright (C) 2010, Linden Research, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation;
-version 2.1 of the License only.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-$/LicenseInfo$
-"""
-
-from __future__ import with_statement
-
-import os
-import sys
-import re
-import errno
-import socket
-
-VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "0") # default to quiet
-# Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if
-# that construct actually turns on verbosity...
-VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE)
-
-if VERBOSE:
- def debug(fmt, *args):
- print fmt % args
- sys.stdout.flush()
-else:
- debug = lambda *args: None
-
-def freeport(portlist, expr):
- """
- Find a free server port to use. Specifically, evaluate 'expr' (a
- callable(port)) until it stops raising EADDRINUSE exception.
-
- Pass:
-
- portlist: an iterable (e.g. xrange()) of ports to try. If you exhaust the
- range, freeport() lets the socket.error exception propagate. If you want
- unbounded, you could pass itertools.count(baseport), though of course in
- practice the ceiling is 2^16-1 anyway. But it seems prudent to constrain
- the range much more sharply: if we're iterating an absurd number of times,
- probably something else is wrong.
-
- expr: a callable accepting a port number, specifically one of the items
- from portlist. If calling that callable raises socket.error with
- EADDRINUSE, freeport() retrieves the next item from portlist and retries.
-
- Returns: (expr(port), port)
-
- port: the value from portlist for which expr(port) succeeded
-
- Raises:
-
- Any exception raised by expr(port) other than EADDRINUSE.
-
- socket.error if, for every item from portlist, expr(port) raises
- socket.error. The exception you see is the one from the last item in
- portlist.
-
- StopIteration if portlist is completely empty.
-
- Example:
-
- class Server(HTTPServer):
- # If you use BaseHTTPServer.HTTPServer, turning off this flag is
- # essential for proper operation of freeport()!
- allow_reuse_address = False
- # ...
- server, port = freeport(xrange(8000, 8010),
- lambda port: Server(("localhost", port),
- MyRequestHandler))
- # pass 'port' to client code
- # call server.serve_forever()
- """
- try:
- # If portlist is completely empty, let StopIteration propagate: that's an
- # error because we can't return meaningful values. We have no 'port',
- # therefore no 'expr(port)'.
- portiter = iter(portlist)
- port = portiter.next()
-
- while True:
- try:
- # If this value of port works, return as promised.
- value = expr(port)
-
- except socket.error, err:
- # Anything other than 'Address already in use', propagate
- if err.args[0] != errno.EADDRINUSE:
- raise
-
- # Here we want the next port from portiter. But on StopIteration,
- # we want to raise the original exception rather than
- # StopIteration. So save the original exc_info().
- type, value, tb = sys.exc_info()
- try:
- try:
- port = portiter.next()
- except StopIteration:
- raise type, value, tb
- finally:
- # Clean up local traceback, see docs for sys.exc_info()
- del tb
-
- else:
- debug("freeport() returning %s on port %s", value, port)
- return value, port
-
- # Recap of the control flow above:
- # If expr(port) doesn't raise, return as promised.
- # If expr(port) raises anything but EADDRINUSE, propagate that
- # exception.
- # If portiter.next() raises StopIteration -- that is, if the port
- # value we just passed to expr(port) was the last available -- reraise
- # the EADDRINUSE exception.
- # If we've actually arrived at this point, portiter.next() delivered a
- # new port value. Loop back to pass that to expr(port).
-
- except Exception, err:
- debug("*** freeport() raising %s: %s", err.__class__.__name__, err)
- raise
-
-def run(*args, **kwds):
- """All positional arguments collectively form a command line, executed as
- a synchronous child process.
- In addition, pass server=new_thread_instance as an explicit keyword (to
- differentiate it from an additional command-line argument).
- new_thread_instance should be an instantiated but not yet started Thread
- subclass instance, e.g.:
- run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd"))
- """
- # If there's no server= keyword arg, don't start a server thread: simply
- # run a child process.
- try:
- thread = kwds.pop("server")
- except KeyError:
- pass
- else:
- # Start server thread. Note that this and all other comm server
- # threads should be daemon threads: we'll let them run "forever,"
- # confident that the whole process will terminate when the main thread
- # terminates, which will be when the child process terminates.
- thread.setDaemon(True)
- thread.start()
- # choice of os.spawnv():
- # - [v vs. l] pass a list of args vs. individual arguments,
- # - [no p] don't use the PATH because we specifically want to invoke the
- # executable passed as our first arg,
- # - [no e] child should inherit this process's environment.
- debug("Running %s...", " ".join(args))
- if kwds.get("use_path", False):
- rc = os.spawnvp(os.P_WAIT, args[0], args)
- else:
- rc = os.spawnv(os.P_WAIT, args[0], args)
- debug("%s returned %s", args[0], rc)
- return rc
-
-# ****************************************************************************
-# test code -- manual at this point, see SWAT-564
-# ****************************************************************************
-def test_freeport():
- # ------------------------------- Helpers --------------------------------
- from contextlib import contextmanager
- # helper Context Manager for expecting an exception
- # with exc(SomeError):
- # raise SomeError()
- # raises AssertionError otherwise.
- @contextmanager
- def exc(exception_class, *args):
- try:
- yield
- except exception_class, err:
- for i, expected_arg in enumerate(args):
- assert expected_arg == err.args[i], \
- "Raised %s, but args[%s] is %r instead of %r" % \
- (err.__class__.__name__, i, err.args[i], expected_arg)
- print "Caught expected exception %s(%s)" % \
- (err.__class__.__name__, ', '.join(repr(arg) for arg in err.args))
- else:
- assert False, "Failed to raise " + exception_class.__class__.__name__
-
- # helper to raise specified exception
- def raiser(exception):
- raise exception
-
- # the usual
- def assert_equals(a, b):
- assert a == b, "%r != %r" % (a, b)
-
- # ------------------------ Sanity check the above ------------------------
- class SomeError(Exception): pass
- # Without extra args, accept any err.args value
- with exc(SomeError):
- raiser(SomeError("abc"))
- # With extra args, accept only the specified value
- with exc(SomeError, "abc"):
- raiser(SomeError("abc"))
- with exc(AssertionError):
- with exc(SomeError, "abc"):
- raiser(SomeError("def"))
- with exc(AssertionError):
- with exc(socket.error, errno.EADDRINUSE):
- raiser(socket.error(errno.ECONNREFUSED, 'Connection refused'))
-
- # ----------- freeport() without engaging socket functionality -----------
- # If portlist is empty, freeport() raises StopIteration.
- with exc(StopIteration):
- freeport([], None)
-
- assert_equals(freeport([17], str), ("17", 17))
-
- # This is the magic exception that should prompt us to retry
- inuse = socket.error(errno.EADDRINUSE, 'Address already in use')
- # Get the iterator to our ports list so we can check later if we've used all
- ports = iter(xrange(5))
- with exc(socket.error, errno.EADDRINUSE):
- freeport(ports, lambda port: raiser(inuse))
- # did we entirely exhaust 'ports'?
- with exc(StopIteration):
- ports.next()
-
- ports = iter(xrange(2))
- # Any exception but EADDRINUSE should quit immediately
- with exc(SomeError):
- freeport(ports, lambda port: raiser(SomeError()))
- assert_equals(ports.next(), 1)
-
- # ----------- freeport() with platform-dependent socket stuff ------------
- # This is what we should've had unit tests to begin with (see CHOP-661).
- def newbind(port):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('127.0.0.1', port))
- return sock
-
- bound0, port0 = freeport(xrange(7777, 7780), newbind)
- assert_equals(port0, 7777)
- bound1, port1 = freeport(xrange(7777, 7780), newbind)
- assert_equals(port1, 7778)
- bound2, port2 = freeport(xrange(7777, 7780), newbind)
- assert_equals(port2, 7779)
- with exc(socket.error, errno.EADDRINUSE):
- bound3, port3 = freeport(xrange(7777, 7780), newbind)
-
-if __name__ == "__main__":
- test_freeport()
diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h
index 8b4afae24a..56e26c23ba 100644
--- a/indra/llcrashlogger/llcrashlogger.h
+++ b/indra/llcrashlogger/llcrashlogger.h
@@ -57,7 +57,7 @@ public:
LLSD constructPostData();
virtual void updateApplication(const std::string& message = LLStringUtil::null);
virtual bool init();
- virtual bool mainLoop() = 0;
+ virtual bool frame() = 0;
virtual bool cleanup() = 0;
void commonCleanup();
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 91fa8c6ad1..a6cbcc131e 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -942,6 +942,12 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
{
llassert( getComponents() <= 4 );
// This is fairly bogus, but it'll do for now.
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return;
+ }
+
U8 *pos = getData();
U32 x, y;
for (x = 0; x < getWidth(); x++)
@@ -1069,6 +1075,11 @@ void LLImageRaw::composite( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::composite", src, dst))
+ {
+ return;
+ }
+
llassert(3 == src->getComponents());
llassert(3 == dst->getComponents());
@@ -1136,7 +1147,6 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
-
U8* src_data = src->getData();
U8* dst_data = dst->getData();
S32 pixels = getWidth() * getHeight();
@@ -1171,6 +1181,11 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst))
+ {
+ return;
+ }
+
llassert( 1 == src->getComponents() );
llassert( 4 == dst->getComponents() );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
@@ -1193,13 +1208,20 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
// Fill the buffer with a constant color
void LLImageRaw::fill( const LLColor4U& color )
{
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return;
+ }
+
S32 pixels = getWidth() * getHeight();
if( 4 == getComponents() )
{
U32* data = (U32*) getData();
+ U32 rgbaColor = color.asRGBA();
for( S32 i = 0; i < pixels; i++ )
{
- data[i] = color.mAll;
+ data[ i ] = rgbaColor;
}
}
else
@@ -1231,14 +1253,13 @@ LLPointer<LLImageRaw> LLImageRaw::duplicate()
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
{
- if (!src)
+ LLImageRaw* dst = this; // Just for clarity.
+
+ if (!validateSrcAndDst("LLImageRaw::copy", src, dst))
{
- LL_WARNS() << "LLImageRaw::copy called with a null src pointer" << LL_ENDL;
return;
}
- LLImageRaw* dst = this; // Just for clarity.
-
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
// No scaling needed
@@ -1365,6 +1386,11 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::copyScaled", src, dst))
+ {
+ return;
+ }
+
llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert_always( src->getComponents() == dst->getComponents() );
@@ -1401,7 +1427,18 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
{
- llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
+ S32 components = getComponents();
+ if (! ((1 == components) || (3 == components) || (4 == components) ))
+ {
+ LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
+ return false;
+ }
+
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return false;
+ }
S32 old_width = getWidth();
S32 old_height = getHeight();
@@ -1415,67 +1452,53 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
if (scale_image_data)
{
- /*
- S32 temp_data_size = old_width * new_height * getComponents();
- llassert_always(temp_data_size > 0);
- std::vector<U8> temp_buffer(temp_data_size);
+ S32 new_data_size = new_width * new_height * components;
- // Vertical
- for( S32 col = 0; col < old_width; col++ )
- {
- copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width );
- }
-
- deleteData();
+ if (new_data_size > 0)
+ {
+ U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
+ if(NULL == new_data)
+ {
+ return false;
+ }
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
-
- // Horizontal
- for( S32 row = 0; row < new_height; row++ )
- {
- copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
+ bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components);
+ setDataAndSize(new_data, new_width, new_height, components);
}
- */
-
- S32 new_data_size = new_width * new_height * getComponents();
- llassert_always(new_data_size > 0);
-
- U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
- if(NULL == new_data)
- {
- return false;
- }
-
- bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents());
- setDataAndSize(new_data, new_width, new_height, getComponents());
}
else
{
// copy out existing image data
- S32 temp_data_size = old_width * old_height * getComponents();
+ S32 temp_data_size = old_width * old_height * components;
std::vector<U8> temp_buffer(temp_data_size);
memcpy(&temp_buffer[0], getData(), temp_data_size);
// allocate new image data, will delete old data
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
-
- for( S32 row = 0; row < new_height; row++ )
- {
- if (row < old_height)
- {
- memcpy(new_buffer + (new_width * row * getComponents()), &temp_buffer[0] + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width));
- if (old_width < new_width)
- {
- // pad out rest of row with black
- memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
- }
- }
- else
- {
- // pad remaining rows with black
- memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
- }
- }
+ U8* new_buffer = allocateDataSize(new_width, new_height, components);
+
+ if (!new_buffer)
+ {
+ LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL;
+ return false;
+ }
+
+ for( S32 row = 0; row < new_height; row++ )
+ {
+ if (row < old_height)
+ {
+ memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width));
+ if (old_width < new_width)
+ {
+ // pad out rest of row with black
+ memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width));
+ }
+ }
+ else
+ {
+ // pad remaining rows with black
+ memset(new_buffer + (new_width * row * components), 0, new_width * components);
+ }
+ }
}
return true ;
@@ -1692,6 +1715,25 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
}
}
+bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
+{
+ if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid())
+ {
+ LL_WARNS() << func << ": Source: ";
+ if (!src) LL_CONT << "Null pointer";
+ else if (src->isBufferInvalid()) LL_CONT << "Invalid buffer";
+ else LL_CONT << "OK";
+
+ LL_CONT << "; Destination: ";
+ if (!dst) LL_CONT << "Null pointer";
+ else if (dst->isBufferInvalid()) LL_CONT << "Invalid buffer";
+ else LL_CONT << "OK";
+ LL_CONT << "." << LL_ENDL;
+
+ return false;
+ }
+ return true;
+}
//----------------------------------------------------------------------------
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index adc650d360..9cc7431a9c 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -277,6 +277,9 @@ protected:
public:
static S32 sGlobalRawMemory;
static S32 sRawImageCount;
+
+private:
+ bool validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst);
};
// Compressed representation of image.
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index 5bf3f29b3c..a5e546e977 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -201,7 +201,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
cinfo.out_color_space = JCS_RGB;
jpeg_start_decompress (&cinfo);
- mHeight = cinfo.output_width;
+ mWidth = cinfo.output_width;
mHeight = cinfo.output_height;
jpeg_destroy_decompress(&cinfo);
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index aad139f570..da289ea889 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -31,6 +31,16 @@
#include "llimage.h"
#include "llpngwrapper.h"
+#include "llexception.h"
+
+namespace {
+// Failure to load an image shouldn't crash the whole viewer.
+struct PngError: public LLContinueError
+{
+ PngError(png_const_charp msg): LLContinueError(msg) {}
+};
+} // anonymous namespace
+
// ---------------------------------------------------------------------------
// LLPngWrapper
// ---------------------------------------------------------------------------
@@ -75,11 +85,10 @@ BOOL LLPngWrapper::isValidPng(U8* src)
}
// Called by the libpng library when a fatal encoding or decoding error
-// occurs. We simply throw the error message and let our try/catch
-// block clean up.
+// occurs. We throw PngError and let our try/catch block clean up.
void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)
{
- throw msg;
+ LLTHROW(PngError(msg));
}
// Called by the libpng library when reading (decoding) the PNG file. We
@@ -129,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
this, &errorHandler, NULL);
if (mReadPngPtr == NULL)
{
- throw "Problem creating png read structure";
+ LLTHROW(PngError("Problem creating png read structure"));
}
// Allocate/initialize the memory for image information.
@@ -187,9 +196,9 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
mFinalSize = dataPtr.mOffset;
}
- catch (png_const_charp msg)
+ catch (const PngError& msg)
{
- mErrorMessage = msg;
+ mErrorMessage = msg.what();
releaseResources();
return (FALSE);
}
@@ -288,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
if (mColorType == -1)
{
- throw "Unsupported image: unexpected number of channels";
+ LLTHROW(PngError("Unsupported image: unexpected number of channels"));
}
mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, &errorHandler, NULL);
if (!mWritePngPtr)
{
- throw "Problem creating png write structure";
+ LLTHROW(PngError("Problem creating png write structure"));
}
mWriteInfoPtr = png_create_info_struct(mWritePngPtr);
@@ -339,9 +348,9 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
png_write_end(mWritePngPtr, mWriteInfoPtr);
mFinalSize = dataPtr.mOffset;
}
- catch (png_const_charp msg)
+ catch (const PngError& msg)
{
- mErrorMessage = msg;
+ mErrorMessage = msg.what();
releaseResources();
return (FALSE);
}
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 3bb1778d9d..925da5674b 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -41,8 +41,12 @@ LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
std::string LLImageJ2COJ::getEngineInfo() const
{
+#ifdef OPENJPEG_VERSION
return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
+ opj_version();
+#else
+ return std::string("OpenJPEG runtime: ") + opj_version();
+#endif
}
// Return string from message, eliminating final \n if present
diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt
index b8f8b420c3..cb0e204e91 100644
--- a/indra/llkdu/CMakeLists.txt
+++ b/indra/llkdu/CMakeLists.txt
@@ -40,6 +40,14 @@ set_source_files_properties(${llkdu_HEADER_FILES}
list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
+# Our KDU package is built with KDU_X86_INTRINSICS in its .vcxproj file.
+# Unless that macro is also set for every consumer build, KDU freaks out,
+# spamming the viewer log with alignment FUD.
+set_source_files_properties(${llkdu_SOURCE_FILES}
+ PROPERTIES
+ COMPILE_DEFINITIONS
+ "KDU_X86_INTRINSICS")
+
if (USE_KDU)
add_library (llkdu ${llkdu_SOURCE_FILES})
diff --git a/indra/llkdu/include_kdu_xxxx.h b/indra/llkdu/include_kdu_xxxx.h
new file mode 100644
index 0000000000..a1dbced60b
--- /dev/null
+++ b/indra/llkdu/include_kdu_xxxx.h
@@ -0,0 +1,40 @@
+/**
+ * @file include_kdu_xxxx.h
+ * @author Nat Goodspeed
+ * @date 2016-04-25
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// This file specifically omits #include guards of its own: it's sort of an
+// #include macro used to wrap KDU #includes with proper incantations. Usage:
+
+// #define kdu_xxxx "kdu_compressed.h" // or whichever KDU header
+// #include "include_kdu_xxxx.h"
+// // kdu_xxxx #undef'ed by include_kdu_xxxx.h
+
+#if LL_DARWIN
+// don't *really* want to rebuild KDU so turn off specific warnings for this header
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wself-assign-field"
+#pragma clang diagnostic ignored "-Wunused-private-field"
+#include kdu_xxxx
+#pragma clang diagnostic pop
+#elif LL_WINDOWS
+// With warnings-as-errors in effect, strange relationship between
+// jp2_output_box and its subclass jp2_target in kdu_compressed.h
+// causes build failures. Specifically:
+// warning C4263: 'void kdu_supp::jp2_target::open(kdu_supp::jp2_family_tgt *)' : member function does not override any base class virtual member function
+// warning C4264: 'void kdu_supp::jp2_output_box::open(kdu_core::kdu_uint32)' : no override available for virtual member function from base 'kdu_supp::jp2_output_box'; function is hidden
+#pragma warning(push)
+#pragma warning(disable : 4263 4264)
+#include kdu_xxxx
+#pragma warning(pop)
+#else // some other platform
+#include kdu_xxxx
+#endif
+
+#undef kdu_xxxx
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 9347e51b85..cb29da8f5f 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -1,4 +1,4 @@
- /**
+/**
* @file llimagej2ckdu.cpp
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
*
@@ -25,6 +25,7 @@
*/
#include "linden_common.h"
+
#include "llimagej2ckdu.h"
#include "lltimer.h"
@@ -32,12 +33,75 @@
#include "llmath.h"
#include "llkdumem.h"
-#include "kdu_block_coding.h"
+#define kdu_xxxx "kdu_block_coding.h"
+#include "include_kdu_xxxx.h"
+
+// Avoid ubiquitous necessity of kdu_core:: qualification
+using namespace kdu_core;
+
+#include "llexception.h"
+#include <boost/exception/diagnostic_information.hpp>
+#include <sstream>
+#include <iomanip>
+
+// stream kdu_dims to std::ostream
+// Turns out this must NOT be in the anonymous namespace!
+// It must also precede #include "stringize.h".
+inline
+std::ostream& operator<<(std::ostream& out, const kdu_dims& dims)
+{
+ return out << "(" << dims.pos.x << "," << dims.pos.y << "),"
+ "[" << dims.size.x << "x" << dims.size.y << "]";
+}
+
+#include "stringize.h"
+
+namespace {
+// Failure to load an image shouldn't crash the whole viewer.
+struct KDUError: public LLContinueError
+{
+ KDUError(const std::string& msg): LLContinueError(msg) {}
+};
+
+// KDU defines int error codes as hex values, so we should log them in hex
+// so we can grep KDU headers for the hex. However those hex values
+// generally "happen" to encode big-endian multibyte character sequences,
+// e.g. KDU_ERROR_EXCEPTION is 0x6b647545: 'kduE'
+// But beware because KDU_NULL_EXCEPTION is simply 0 -- which doesn't
+// preclude somebody from throwing it.
+std::string report_kdu_exception(kdu_exception mb)
+{
+ std::ostringstream out;
+ // always report mb in hex
+ out << "kdu_exception " << std::hex << mb;
+
+ // Also display as many chars as are encoded in the kdu_exception
+ // value. Make a char array; reserve 1 extra byte for nul terminator.
+ char bytes[sizeof(kdu_exception) + 1];
+ // Back up through 'bytes'
+ char *bptr = bytes + sizeof(bytes);
+ *(--bptr) = '\0';
+ while (mb)
+ {
+ // store low-order byte of mb in next-left char
+ *(--bptr) = char(mb & 0xFF);
+ // then shift mb right by one byte
+ mb >>= 8;
+ }
+ // did that produce any characters?
+ if (*bptr)
+ {
+ out << " (" << bptr << ')';
+ }
+
+ return out.str();
+}
+} // anonymous namespace
class kdc_flow_control {
public:
- kdc_flow_control(kdu_image_in_base *img_in, kdu_codestream codestream);
+ kdc_flow_control(kdu_supp::kdu_image_in_base *img_in, kdu_codestream codestream);
~kdc_flow_control();
bool advance_components();
void process_components();
@@ -46,7 +110,7 @@ private:
struct kdc_component_flow_control {
public:
- kdu_image_in_base *reader;
+ kdu_supp::kdu_image_in_base *reader;
int vert_subsampling;
int ratio_counter; /* Initialized to 0, decremented by `count_delta';
when < 0, a new line must be processed, after
@@ -86,7 +150,8 @@ std::string LLImageJ2CKDU::getEngineInfo() const
class LLKDUDecodeState
{
public:
- LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap);
+ LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
+ kdu_codestream* codestreamp);
~LLKDUDecodeState();
bool processTileDecode(F32 decode_time, bool limit_time = true);
@@ -165,9 +230,15 @@ struct LLKDUMessageError : public LLKDUMessage
// terminating handler→flush call."
// So throwing an exception here isn't arbitrary: we MUST throw an
// exception if we want to recover from a KDU error.
+ // Because this confused me: the above quote specifically refers to
+ // the kdu_error class, which is constructed internally within KDU at
+ // the point where a fatal error is discovered and reported. It is NOT
+ // talking about the kdu_message subclass passed to
+ // kdu_customize_errors(). Destroying this static object at program
+ // shutdown will NOT engage the behavior described above.
if (end_of_message)
{
- throw "KDU throwing an exception";
+ LLTHROW(KDUError("LLKDUMessageError::flush()"));
}
}
};
@@ -196,6 +267,10 @@ LLImageJ2CKDU::~LLImageJ2CKDU()
// Stuff for new simple decode
void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision);
+// This is called by the real (private) initDecode() (keep_codestream true)
+// and getMetadata() methods (keep_codestream false). As far as nat can tell,
+// mode is always MODE_FAST. It was called by findDiscardLevelsBoundaries()
+// as well, when that still existed, with keep_codestream true and MODE_FAST.
void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)
{
S32 data_size = base.getDataSize();
@@ -206,6 +281,12 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
//
mCodeStreamp.reset();
+ // It's not clear to nat under what circumstances we would reuse a
+ // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
+ // two U32s and a pointer, so it's not as if it would be a huge overhead
+ // to allocate a new one every time.
+ // Also -- why is base.getData() tested specifically here? If that returns
+ // NULL, shouldn't we bail out of the whole method?
if (!mInputp && base.getData())
{
// The compressed data has been loaded
@@ -262,13 +343,19 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
S32 components = mCodeStreamp->get_num_components();
- if (components >= 3)
- { // Check that components have consistent dimensions (for PPM file)
- kdu_dims dims1; mCodeStreamp->get_dims(1,dims1);
- kdu_dims dims2; mCodeStreamp->get_dims(2,dims2);
- if ((dims1 != dims) || (dims2 != dims))
+ // Check that components have consistent dimensions (for PPM file)
+ for (int idx = 1; idx < components; ++idx)
+ {
+ kdu_dims other_dims;
+ mCodeStreamp->get_dims(idx, other_dims);
+ if (other_dims != dims)
{
- LL_ERRS() << "Components don't have matching dimensions!" << LL_ENDL;
+ // This method is only called from methods that catch KDUError.
+ // We want to fail the image load, not crash the viewer.
+ LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
+ << stringize(other_dims)
+ << " do not match component 0 dimensions "
+ << stringize(dims) << "!")));
}
}
@@ -295,6 +382,9 @@ void LLImageJ2CKDU::cleanupCodeStream()
mTileIndicesp.reset();
}
+// This is the protected virtual method called by LLImageJ2C::initDecode().
+// However, as far as nat can tell, LLImageJ2C::initDecode() is called only by
+// llimage_libtest.cpp's load_image() function. No detectable production use.
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
{
return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region);
@@ -327,6 +417,9 @@ bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc
return true;
}
+// This is the real (private) initDecode() called both by the protected
+// initDecode() method and by decodeImpl(). As far as nat can tell, only the
+// decodeImpl() usage matters for production.
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
{
base.resetLastError();
@@ -384,14 +477,24 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
mTPosp->x = 0;
}
}
- catch (const char* msg)
+ catch (const KDUError& msg)
+ {
+ base.setLastError(msg.what());
+ return false;
+ }
+ catch (kdu_exception kdu_value)
{
- base.setLastError(ll_safe_string(msg));
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
return false;
}
catch (...)
{
- base.setLastError("Unknown J2C error");
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -464,7 +567,8 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
kdu_coords offset = tile_dims.pos - dims.pos;
int row_gap = channels*dims.size.x; // inter-row separation
kdu_byte *buf = buffer + offset.y*row_gap + offset.x*channels;
- mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap));
+ mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap,
+ mCodeStreamp.get()));
}
// Do the actual processing
F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32();
@@ -480,16 +584,28 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
return false;
}
}
- catch (const char* msg)
+ catch (const KDUError& msg)
+ {
+ base.setLastError(msg.what());
+ base.decodeFailed();
+ cleanupCodeStream();
+ return true; // done
+ }
+ catch (kdu_exception kdu_value)
{
- base.setLastError(ll_safe_string(msg));
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
base.decodeFailed();
cleanupCodeStream();
return true; // done
}
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
base.decodeFailed();
cleanupCodeStream();
return true; // done
@@ -673,14 +789,24 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
base.updateData(); // set width, height
delete[] output_buffer;
}
- catch(const char* msg)
+ catch(const KDUError& msg)
+ {
+ base.setLastError(msg.what());
+ return false;
+ }
+ catch (kdu_exception kdu_value)
{
- base.setLastError(ll_safe_string(msg));
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
return false;
}
catch( ... )
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
@@ -697,14 +823,24 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
setupCodeStream(base, false, MODE_FAST);
return true;
}
- catch (const char* msg)
+ catch (const KDUError& msg)
+ {
+ base.setLastError(msg.what());
+ return false;
+ }
+ catch (kdu_exception kdu_value)
{
- base.setLastError(ll_safe_string(msg));
+ // KDU internally throws kdu_exception. It's possible that such an
+ // exception might leak out into our code. Catch kdu_exception
+ // specially because boost::current_exception_diagnostic_information()
+ // could do nothing with it.
+ base.setLastError(report_kdu_exception(kdu_value));
return false;
}
catch (...)
{
- base.setLastError( "Unknown J2C error" );
+ base.setLastError("Unknown J2C error: " +
+ boost::current_exception_diagnostic_information());
return false;
}
}
@@ -1120,7 +1256,8 @@ all necessary level shifting, type conversion, rounding and truncation. */
}
}
-LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
+LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
+ kdu_codestream* codestreamp)
{
S32 c;
@@ -1166,7 +1303,7 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
mEngines[c] = kdu_synthesis(res,&mAllocator,use_shorts);
}
}
- mAllocator.finalize(); // Actually creates buffering resources
+ mAllocator.finalize(*codestreamp); // Actually creates buffering resources
for (c = 0; c < mNumComponents; c++)
{
mLines[c].create(); // Grabs resources from the allocator.
@@ -1224,7 +1361,7 @@ separation between consecutive rows in the real buffer. */
// kdc_flow_control
-kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream codestream)
+kdc_flow_control::kdc_flow_control (kdu_supp::kdu_image_in_base *img_in, kdu_codestream codestream)
{
int n;
diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h
index 7d234435a4..b57e4cc40e 100644
--- a/indra/llkdu/llimagej2ckdu.h
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -37,15 +37,8 @@
#include "kdu_messaging.h"
#include "kdu_params.h"
-// don't *really* want to rebuild KDU so turn off specific warnings for this header
-#if LL_DARWIN
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-private-field"
-#include "kdu_compressed.h"
-#pragma clang diagnostic pop
-#else
-#include "kdu_compressed.h"
-#endif
+#define kdu_xxxx "kdu_compressed.h"
+#include "include_kdu_xxxx.h"
#include "kdu_sample_processing.h"
#include <boost/scoped_ptr.hpp>
@@ -111,17 +104,19 @@ private:
}
}
- kdu_codestream* operator->() { return &mCodeStream; }
+ // for those few times when you need a raw kdu_codestream*
+ kdu_core::kdu_codestream* get() { return &mCodeStream; }
+ kdu_core::kdu_codestream* operator->() { return &mCodeStream; }
private:
- kdu_codestream mCodeStream;
+ kdu_core::kdu_codestream mCodeStream;
};
// Encode variable
boost::scoped_ptr<LLKDUMemSource> mInputp;
CodeStreamHolder mCodeStreamp;
- boost::scoped_ptr<kdu_coords> mTPosp; // tile position
- boost::scoped_ptr<kdu_dims> mTileIndicesp;
+ boost::scoped_ptr<kdu_core::kdu_coords> mTPosp; // tile position
+ boost::scoped_ptr<kdu_core::kdu_dims> mTileIndicesp;
int mBlocksSize;
int mPrecinctsSize;
int mLevels;
diff --git a/indra/llkdu/llkdumem.cpp b/indra/llkdu/llkdumem.cpp
index 0347475559..96e9da25d8 100644
--- a/indra/llkdu/llkdumem.cpp
+++ b/indra/llkdu/llkdumem.cpp
@@ -28,6 +28,9 @@
#include "llkdumem.h"
#include "llerror.h"
+using namespace kdu_core;
+using kd_supp_image_local::image_line_buf;
+
#if defined(LL_WINDOWS)
# pragma warning(disable: 4702) // unreachable code
#endif
diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h
index fab913d93b..09d81f38de 100644
--- a/indra/llkdu/llkdumem.h
+++ b/indra/llkdu/llkdumem.h
@@ -29,26 +29,22 @@
// Support classes for reading and writing from memory buffers in KDU
#define KDU_NO_THREADS
-// don't *really* want to rebuild KDU so turn off specific warnings for this header
-#if LL_DARWIN
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wself-assign-field"
-#pragma clang diagnostic ignored "-Wunused-private-field"
-#include "kdu_image.h"
-#pragma clang diagnostic pop
-#else
-#include "kdu_image.h"
-#endif
+
+#define kdu_xxxx "kdu_image.h"
+#include "include_kdu_xxxx.h"
#include "kdu_elementary.h"
#include "kdu_messaging.h"
#include "kdu_params.h"
-#include "kdu_compressed.h"
+
+#define kdu_xxxx "kdu_compressed.h"
+#include "include_kdu_xxxx.h"
+
#include "kdu_sample_processing.h"
#include "image_local.h"
#include "stdtypes.h"
-class LLKDUMemSource: public kdu_compressed_source
+class LLKDUMemSource: public kdu_core::kdu_compressed_source
{
public:
LLKDUMemSource(U8 *input_buffer, U32 size)
@@ -62,7 +58,7 @@ public:
{
}
- int read(kdu_byte *buf, int num_bytes)
+ int read(kdu_core::kdu_byte *buf, int num_bytes)
{
U32 num_out;
num_out = num_bytes;
@@ -87,7 +83,7 @@ private:
U32 mCurPos;
};
-class LLKDUMemTarget: public kdu_compressed_target
+class LLKDUMemTarget: public kdu_core::kdu_compressed_target
{
public:
LLKDUMemTarget(U8 *output_buffer, U32 &output_size, const U32 buffer_size)
@@ -102,7 +98,7 @@ public:
{
}
- bool write(const kdu_byte *buf, int num_bytes)
+ bool write(const kdu_core::kdu_byte *buf, int num_bytes)
{
U32 num_out;
num_out = num_bytes;
@@ -126,7 +122,7 @@ private:
U32 *mOutputSize;
};
-class LLKDUMemIn : public kdu_image_in_base
+class LLKDUMemIn : public kdu_supp::kdu_image_in_base
{
public:
LLKDUMemIn(const U8 *data,
@@ -134,10 +130,10 @@ public:
const U16 rows,
const U16 cols,
U8 in_num_components,
- siz_params *siz);
+ kdu_core::siz_params *siz);
~LLKDUMemIn();
- bool get(int comp_idx, kdu_line_buf &line, int x_tnum);
+ bool get(int comp_idx, kdu_core::kdu_line_buf &line, int x_tnum);
private:
const U8 *mData;
@@ -146,8 +142,8 @@ private:
int rows, cols;
int alignment_bytes; // Number of 0's at end of each line.
int precision[3];
- image_line_buf *incomplete_lines; // Each "sample" represents a full pixel
- image_line_buf *free_lines;
+ kd_supp_image_local::image_line_buf *incomplete_lines; // Each "sample" represents a full pixel
+ kd_supp_image_local::image_line_buf *free_lines;
int num_unread_rows;
U32 mCurPos;
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
index e8b550baa6..e386a9f71b 100644
--- a/indra/llkdu/tests/llimagej2ckdu_test.cpp
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -30,6 +30,7 @@
#include "llimagej2ckdu.h"
#if LL_DARWIN
+// For this source, it's true that private fields in llkdumem.h are unused.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
#include "llkdumem.h"
@@ -37,7 +38,6 @@
#else
#include "llkdumem.h"
#endif
-
#include "kdu_block_coding.h"
// Tut header
#include "lltut.h"
@@ -113,17 +113,19 @@ void LLImageJ2C::setLastError(const std::string&, const std::string&) { }
bool LLImageJ2C::updateData() { return false; }
void LLImageJ2C::updateRawDiscardLevel() { }
-LLKDUMemIn::LLKDUMemIn(const U8*, const U32, const U16, const U16, const U8, siz_params*) { }
+LLKDUMemIn::LLKDUMemIn(const U8*, const U32, const U16, const U16, const U8, kdu_core::siz_params*) { }
LLKDUMemIn::~LLKDUMemIn() { }
-bool LLKDUMemIn::get(int, kdu_line_buf&, int) { return false; }
+bool LLKDUMemIn::get(int, kdu_core::kdu_line_buf&, int) { return false; }
// Stub Kakadu Library calls
+// they're all namespaced now
+namespace kdu_core {
kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; }
kdu_block_encoder::kdu_block_encoder() { }
kdu_block_decoder::kdu_block_decoder() { }
void kdu_block::set_max_passes(int , bool ) { }
void kdu_block::set_max_bytes(int , bool ) { }
-void kdu_tile::close(kdu_thread_env* ) { }
+void kdu_tile::close(kdu_thread_env *, bool) {}
int kdu_tile::get_num_components() { return 0; }
bool kdu_tile::get_ycc() { return false; }
void kdu_tile::set_components_of_interest(int , const int* ) { }
@@ -156,14 +158,14 @@ void kdu_codestream::set_fussy() { }
void kdu_codestream::get_dims(int, kdu_dims&, bool ) { }
int kdu_codestream::get_min_dwt_levels() { return 5; }
int kdu_codestream::get_max_tile_layers() { return 1; }
-void kdu_codestream::change_appearance(bool, bool, bool) { }
+void kdu_codestream::change_appearance(bool, bool, bool, kdu_thread_env *) {}
void kdu_codestream::get_tile_dims(kdu_coords, int, kdu_dims&, bool ) { }
void kdu_codestream::destroy() { }
void kdu_codestream::collect_timing_stats(int ) { }
void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }
void kdu_codestream::get_valid_tiles(kdu_dims& ) { }
void kdu_codestream::create(kdu_compressed_source*, kdu_thread_env*) { }
-void kdu_codestream::apply_input_restrictions( int, int, int, int, kdu_dims*, kdu_component_access_mode ) { }
+void kdu_codestream::apply_input_restrictions(int, int, int, int, kdu_dims const *, kdu_component_access_mode, kdu_thread_env *, kdu_quality_limiter const *) {}
void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
void kdu_codestream::flush(kdu_long *, int, kdu_uint16 *, bool, bool, double, kdu_thread_env*, int) { }
void kdu_codestream::set_resilient(bool ) { }
@@ -178,13 +180,15 @@ siz_params* kdu_codestream::access_siz() { return NULL; }
kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; }
kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; }
void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { }
-void kdu_subband::get_valid_blocks(kdu_dims &indices) { }
-kdu_block* kdu_subband::open_block(kdu_coords, int*, kdu_thread_env*) { return NULL; }
+void kdu_subband::get_valid_blocks(kdu_dims &indices) const { }
+kdu_block * kdu_subband::open_block(kdu_coords, int *, kdu_thread_env *, int, bool) { return NULL; }
bool kdu_codestream_comment::put_text(const char*) { return false; }
void kdu_customize_warnings(kdu_message*) { }
void kdu_customize_errors(kdu_message*) { }
-kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, kdu_thread_env*, kdu_thread_queue*, int, kdu_roi_image*, int) { kdu_long a = 0; return a; }
+kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, kdu_thread_env *,kdu_thread_queue *, int, kdu_roi_image *, int, kdu_sample_allocator *, kdu_push_pull_params const *) { return kdu_long(0); }
+void kdu_multi_analysis::destroy(kdu_thread_env *) {}
siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { }
+siz_params::~siz_params() {}
void siz_params::finalize(bool ) { }
void siz_params::copy_with_xforms(kdu_params*, int, int, bool, bool, bool) { }
int siz_params::write_marker_segment(kdu_output*, kdu_params*, int) { return 0; }
@@ -193,10 +197,15 @@ bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { retur
kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*, int) { }
void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long, kdu_thread_env* ) { }
+kdu_sample_allocator::~kdu_sample_allocator() {}
+void kdu_sample_allocator::do_finalize(kdu_codestream) {}
void (*kdu_convert_ycc_to_rgb_rev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
void (*kdu_convert_ycc_to_rgb_irrev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
void (*kdu_convert_ycc_to_rgb_rev32)(kdu_int32*,kdu_int32*,kdu_int32*,int);
void (*kdu_convert_ycc_to_rgb_irrev32)(float*,float*,float*,int);
+bool kdu_core_sample_alignment_checker(int, int, int, int, bool, bool) { return false; }
+void kdu_pull_ifc::destroy() {}
+} // namespace kdu_core
// -------------------------------------------------------------------------------------------
// TUT
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 93b9f22b25..92a48df53c 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -153,7 +153,7 @@ inline F64 llabs(const F64 a)
inline S32 lltrunc( F32 f )
{
-#if LL_WINDOWS && !defined( __INTEL_COMPILER )
+#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32)
// Avoids changing the floating point control word.
// Add or subtract 0.5 - epsilon and then round
const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF };
@@ -179,7 +179,7 @@ inline S32 lltrunc( F64 f )
inline S32 llfloor( F32 f )
{
-#if LL_WINDOWS && !defined( __INTEL_COMPILER )
+#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32)
// Avoids changing the floating point control word.
// Accurate (unlike Stereopsis version) for all values between S32_MIN and S32_MAX and slightly faster than Stereopsis version.
// Add -(0.5 - epsilon) and then round
diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h
index cebd2ace7d..54a275633f 100644
--- a/indra/llmath/llsimdmath.h
+++ b/indra/llmath/llsimdmath.h
@@ -31,7 +31,7 @@
#error "Please include llmath.h before this file."
#endif
-#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 ) )
+#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) )
#error SSE2 not enabled. LLVector4a and related class will not compile.
#endif
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index d932eb53a0..567ad9a414 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2143,19 +2143,22 @@ BOOL LLVolume::generate()
F32 profile_detail = mDetail;
F32 path_detail = mDetail;
-
- U8 path_type = mParams.getPathParams().getCurveType();
- U8 profile_type = mParams.getProfileParams().getCurveType();
-
- if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
- { //cylinders don't care about Z-Axis
- mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
- }
- else if (path_type == LL_PCODE_PATH_CIRCLE)
- {
- mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
+
+ if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
+ {
+ U8 path_type = mParams.getPathParams().getCurveType();
+ U8 profile_type = mParams.getProfileParams().getCurveType();
+ if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
+ {
+ //cylinders don't care about Z-Axis
+ mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
+ }
+ else if (path_type == LL_PCODE_PATH_CIRCLE)
+ {
+ mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
+ }
}
-
+
BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h
index fddad34978..704ce852d9 100644
--- a/indra/llmath/v4coloru.h
+++ b/indra/llmath/v4coloru.h
@@ -47,14 +47,7 @@ class LLColor4U
{
public:
- union
- {
- U8 mV[LENGTHOFCOLOR4U];
- U32 mAll;
- LLColor4* mSources;
- LLColor4U* mSourcesU;
- };
-
+ U8 mV[LENGTHOFCOLOR4U];
LLColor4U(); // Initializes LLColor4U to (0, 0, 0, 1)
LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1)
@@ -132,6 +125,9 @@ public:
return LLColor4(*this);
}
+ U32 asRGBA() const;
+ void fromRGBA( U32 aVal );
+
static LLColor4U white;
static LLColor4U black;
static LLColor4U red;
@@ -565,6 +561,26 @@ void LLColor4U::setVecScaleClamp(const LLColor3& color)
mV[3] = 255;
}
+inline U32 LLColor4U::asRGBA() const
+{
+ // Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here
+
+ return (mV[3] << 24) | (mV[2] << 16) | (mV[1] << 8) | mV[0];
+}
+
+inline void LLColor4U::fromRGBA( U32 aVal )
+{
+ // Little endian: values are swapped in memory. The original code access the array like a U32, so we need to swap here
+
+ mV[ 0 ] = aVal & 0xFF;
+ aVal >>= 8;
+ mV[ 1 ] = aVal & 0xFF;
+ aVal >>= 8;
+ mV[ 2 ] = aVal & 0xFF;
+ aVal >>= 8;
+ mV[ 3 ] = aVal & 0xFF;
+}
+
#endif
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 1ca5f58ae2..004db546b7 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -43,6 +43,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include "llexception.h"
+#include "stringize.h"
#include <map>
#include <set>
@@ -231,13 +233,12 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
}
- catch (std::exception e)
- {
- LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << url << "', " << agentIds.size()
+ << " Agent Ids)"));
+ throw;
}
}
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index d4c0788b7d..74cdff2b00 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -27,6 +27,8 @@
#include "linden_common.h"
#include "llcoproceduremanager.h"
+#include "llexception.h"
+#include "stringize.h"
#include <boost/assign.hpp>
//=========================================================================
@@ -388,14 +390,14 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap
{
coproc->mProc(httpAdapter, coproc->mId);
}
- catch (std::exception &e)
- {
- LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() <<
- " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("Coprocedure('" << coproc->mName
+ << "', id=" << coproc->mId.asString()
+ << ") in pool '" << mPoolName << "'"));
+ // must NOT omit this or we deplete the pool
+ mActiveCoprocs.erase(itActive);
+ throw;
}
LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL;
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index 7742cbc182..9bf38fb336 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -642,7 +642,7 @@ HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request)
mHttpRequest(request)
{
mBoundListener = LLEventPumps::instance().obtain("mainloop").
- listen(LLEventPump::inventName(), boost::bind(&HttpRequestPumper::pollRequest, this, _1));
+ listen(LLEventPump::ANONYMOUS, boost::bind(&HttpRequestPumper::pollRequest, this, _1));
}
HttpRequestPumper::~HttpRequestPumper()
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index f235965879..04b34a296c 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -31,6 +31,7 @@
#include "llstl.h"
#include "llhttpconstants.h"
+#include "llexception.h"
const std::string CONTEXT_HEADERS("headers");
const std::string CONTEXT_PATH("path");
@@ -92,27 +93,28 @@ LLHTTPNode::~LLHTTPNode()
namespace {
- class NotImplemented
+ struct NotImplemented: public LLException
{
+ NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}
};
}
// virtual
LLSD LLHTTPNode::simpleGet() const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePut(const LLSD& input) const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePost(const LLSD& input) const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
@@ -172,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
// virtual
LLSD LLHTTPNode::simpleDel(const LLSD&) const
{
- throw NotImplemented();
+ LLTHROW(NotImplemented());
}
// virtual
diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp
index 4aba5cae72..e0590dfdff 100644
--- a/indra/llmessage/llxfer.cpp
+++ b/indra/llmessage/llxfer.cpp
@@ -294,7 +294,7 @@ S32 LLXfer::processEOF()
}
else
{
- LL_INFOS() << "xfer from " << mRemoteHost << " failed, code "
+ LL_INFOS() << "xfer from " << mRemoteHost << " failed or aborted, code "
<< mCallbackResult << ": " << getFileName() << LL_ENDL;
}
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 0ab67b8dda..272dbbc785 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -401,7 +401,7 @@ U64 LLXferManager::registerXfer(const void *datap, const S32 length)
///////////////////////////////////////////////////////////
-void LLXferManager::requestFile(const std::string& local_filename,
+U64 LLXferManager::requestFile(const std::string& local_filename,
const std::string& remote_filename,
ELLPath remote_path,
const LLHost& remote_host,
@@ -424,10 +424,12 @@ void LLXferManager::requestFile(const std::string& local_filename,
{
// cout << "requested a xfer already in progress" << endl;
- return;
+ return xferp->mID;
}
}
+ U64 xfer_id = 0;
+
S32 chunk_size = use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1;
xferp = (LLXfer *) new LLXfer_File(chunk_size);
if (xferp)
@@ -438,13 +440,15 @@ void LLXferManager::requestFile(const std::string& local_filename,
// around.
// Note: according to AaronB, this is here to deal with locks on files that were
// in transit during a crash,
- if(delete_remote_on_completion &&
- (remote_filename.substr(remote_filename.length()-4) == ".tmp"))
+ if( delete_remote_on_completion
+ && (remote_filename.substr(remote_filename.length()-4) == ".tmp")
+ && gDirUtilp->fileExists(local_filename))
{
LLFile::remove(local_filename);
}
+ xfer_id = getNextID();
((LLXfer_File *)xferp)->initializeRequest(
- getNextID(),
+ xfer_id,
local_filename,
remote_filename,
remote_path,
@@ -457,6 +461,7 @@ void LLXferManager::requestFile(const std::string& local_filename,
{
LL_ERRS() << "Xfer allocation error" << LL_ENDL;
}
+ return xfer_id;
}
void LLXferManager::requestFile(const std::string& remote_filename,
@@ -616,7 +621,7 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user
if (!xferp)
{
char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
- LL_WARNS() << "received xfer data from " << mesgsys->getSender()
+ LL_INFOS() << "received xfer data from " << mesgsys->getSender()
<< " for non-existent xfer id: "
<< U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << LL_ENDL;
return;
@@ -1103,6 +1108,29 @@ void LLXferManager::retransmitUnackedPackets ()
}
}
+///////////////////////////////////////////////////////////
+
+void LLXferManager::abortRequestById(U64 xfer_id, S32 result_code)
+{
+ LLXfer * xferp = findXfer(xfer_id, mReceiveList);
+ if (xferp)
+ {
+ if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
+ {
+ // causes processAbort();
+ xferp->abort(result_code);
+ }
+ else
+ {
+ xferp->mCallbackResult = result_code;
+ xferp->processEOF(); //should notify requester
+ removeXfer(xferp, &mReceiveList);
+ }
+ // Since already removed or marked as aborted no need
+ // to wait for processAbort() to start new download
+ startPendingDownloads();
+ }
+}
///////////////////////////////////////////////////////////
diff --git a/indra/llmessage/llxfermanager.h b/indra/llmessage/llxfermanager.h
index b3d110e7a1..d258f0a5ce 100644
--- a/indra/llmessage/llxfermanager.h
+++ b/indra/llmessage/llxfermanager.h
@@ -140,7 +140,7 @@ class LLXferManager
// file requesting routines
// .. to file
- virtual void requestFile(const std::string& local_filename,
+ virtual U64 requestFile(const std::string& local_filename,
const std::string& remote_filename,
ELLPath remote_path,
const LLHost& remote_host,
@@ -202,6 +202,7 @@ class LLXferManager
virtual void retransmitUnackedPackets ();
// error handling
+ void abortRequestById(U64 xfer_id, S32 result_code);
virtual void processAbort (LLMessageSystem *mesgsys, void **user_data);
};
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index cecb2021e7..290b67feb3 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -4007,7 +4007,7 @@ void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::st
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("untrustedSimulatorMessage", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h
index 0d149b5258..7c8f27bbd2 100644
--- a/indra/llmessage/tests/commtest.h
+++ b/indra/llmessage/tests/commtest.h
@@ -33,15 +33,15 @@
#include "llevents.h"
#include "llsd.h"
#include "llhost.h"
+#include "llexception.h"
#include "stringize.h"
#include <map>
#include <string>
-#include <stdexcept>
#include <boost/lexical_cast.hpp>
-struct CommtestError: public std::runtime_error
+struct CommtestError: public LLException
{
- CommtestError(const std::string& what): std::runtime_error(what) {}
+ CommtestError(const std::string& what): LLException(what) {}
};
static bool query_verbose()
@@ -68,7 +68,7 @@ static int query_port(const std::string& var)
const char* cport = getenv(var.c_str());
if (! cport)
{
- throw CommtestError(STRINGIZE("missing environment variable" << var));
+ LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var)));
}
// This will throw, too, if the value of PORT isn't numeric.
int port(boost::lexical_cast<int>(cport));
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 2aff90ca1e..5eb739393f 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -34,6 +34,7 @@
#include "llares.h"
#include "llpumpio.h"
#include "llhttpclient.h"
+#include "llexception.h"
/*****************************************************************************
* NetworkIO
@@ -51,7 +52,7 @@ public:
ll_init_apr();
if (! gAPRPoolp)
{
- throw std::runtime_error("Can't initialize APR");
+ LLTHROW(LLException("Can't initialize APR"));
}
// Create IO Pump to use for HTTP Requests.
@@ -59,7 +60,7 @@ public:
LLHTTPClient::setPump(*mServicePump);
if (ll_init_ares() == NULL || !gAres->isInitialized())
{
- throw std::runtime_error("Can't start DNS resolver");
+ LLTHROW(LLException("Can't start DNS resolver"));
}
// You can interrupt pump() without waiting the full timeout duration
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index e45249b1cb..bac18fa374 100755
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -34,10 +34,8 @@ import sys
from threading import Thread
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
-mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/
-sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
-from indra.util.fastest_elementtree import parse as xml_parse
-from indra.base import llsd
+from llbase.fastest_elementtree import parse as xml_parse
+from llbase import llsd
from testrunner import freeport, run, debug, VERBOSE
import time
diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py
index 5b9beb359b..9a2de71142 100755
--- a/indra/llmessage/tests/testrunner.py
+++ b/indra/llmessage/tests/testrunner.py
@@ -168,7 +168,10 @@ def run(*args, **kwds):
# executable passed as our first arg,
# - [no e] child should inherit this process's environment.
debug("Running %s...", " ".join(args))
- rc = os.spawnv(os.P_WAIT, args[0], args)
+ if kwds.get("use_path", False):
+ rc = os.spawnvp(os.P_WAIT, args[0], args)
+ else:
+ rc = os.spawnv(os.P_WAIT, args[0], args)
debug("%s returned %s", args[0], rc)
return rc
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index 84667f1b82..2cdea67723 100644
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -56,13 +56,13 @@ set(llplugin_HEADER_FILES
set_source_files_properties(${llplugin_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
-if(NOT WORD_SIZE EQUAL 32)
+if(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ ##add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
-endif(NOT WORD_SIZE EQUAL 32)
+endif(NOT ADDRESS_SIZE EQUAL 32)
list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES})
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 3d173d0459..f1b6fe0a12 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -73,6 +73,7 @@ bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::s
// Queue up the media init message -- it will be sent after all the currently queued messages.
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
message.setValue("target", mTarget);
+ message.setValueReal("factor", mZoomFactor);
sendMessage(message);
mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
@@ -116,7 +117,7 @@ void LLPluginClassMedia::reset()
mMediaHeight = 0;
mDirtyRect = LLRect::null;
mAutoScaleMedia = false;
- mRequestedVolume = 1.0f;
+ mRequestedVolume = 0.0f;
mPriority = PRIORITY_NORMAL;
mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
mAllowDownsample = false;
@@ -1259,7 +1260,7 @@ void LLPluginClassMedia::focus(bool focused)
sendMessage(message);
}
-void LLPluginClassMedia::set_page_zoom_factor( double factor )
+void LLPluginClassMedia::set_page_zoom_factor( F64 factor )
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor");
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index fc27b7bea3..3b0739d044 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -68,6 +68,7 @@ public:
int getTextureHeight() const;
int getFullWidth() const { return mFullMediaWidth; };
int getFullHeight() const { return mFullMediaHeight; };
+ F64 getZoomFactor() const { return mZoomFactor; };
// This may return NULL. Callers need to check for and handle this case.
unsigned char* getBitsData();
@@ -83,7 +84,8 @@ public:
void setSize(int width, int height);
void setAutoScale(bool auto_scale);
-
+ void setZoomFactor(F64 zoom_factor) { mZoomFactor = zoom_factor; }
+
void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
@@ -204,7 +206,7 @@ public:
bool pluginSupportsMediaBrowser(void);
void focus(bool focused);
- void set_page_zoom_factor( double factor );
+ void set_page_zoom_factor( F64 factor );
void clear_cache();
void clear_cookies();
void set_cookies(const std::string &cookies);
@@ -367,6 +369,8 @@ protected:
int mTextureHeight;
int mMediaWidth;
int mMediaHeight;
+
+ F64 mZoomFactor;
float mRequestedVolume;
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 00bde8dbc3..8071d716da 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -1071,7 +1071,7 @@ bool LLDAELoader::OpenFile(const std::string& filename)
std::string LLDAELoader::preprocessDAE(std::string filename)
{
// Open a DAE file for some preprocessing (like removing space characters in IDs), see MAINT-5678
- std::ifstream inFile;
+ llifstream inFile;
inFile.open(filename.c_str(), std::ios_base::in);
std::stringstream strStream;
strStream << inFile.rdbuf();
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 0e2946632a..cf0a117567 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -364,12 +364,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (right_x)
{
- F32 cr_x = (cur_x - origin.mV[VX]) / sScaleX;
- if (*right_x < cr_x)
- {
- // rightmost edge of previously drawn text, don't draw over previous text
- *right_x = cr_x;
- }
+ *right_x = (cur_x - origin.mV[VX]) / sScaleX;
}
//FIXME: add underline as glyph?
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index b30bc1aed6..58c1186a3e 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -349,8 +349,8 @@ void LLGLSLShader::unloadInternal()
for (GLsizei i = 0; i < count; i++)
{
glDetachObjectARB(mProgramObject, obj[i]);
- glDeleteObjectARB(obj[i]);
- }
+ glDeleteObjectARB(obj[i]);
+ }
glDeleteObjectARB(mProgramObject);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ebed454271..81a5537f78 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -487,14 +487,15 @@ bool LLImageGL::checkSize(S32 width, S32 height)
return check_power_of_two(width) && check_power_of_two(height);
}
-void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level)
+bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level)
{
if (width != mWidth || height != mHeight || ncomponents != mComponents)
{
// Check if dimensions are a power of two!
if (!checkSize(width,height))
{
- LL_ERRS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL;
+ LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL;
+ return false;
}
if (mTexName)
@@ -529,6 +530,8 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
mMaxDiscardLevel = MAX_DISCARD_LEVEL;
}
}
+
+ return true;
}
//----------------------------------------------------------------------------
@@ -909,7 +912,11 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
S32 h = raw_image->getHeight() << discard_level;
// setSize may call destroyGLTexture if the size does not match
- setSize(w, h, raw_image->getComponents(), discard_level);
+ if (!setSize(w, h, raw_image->getComponents(), discard_level))
+ {
+ LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
+ return FALSE;
+ }
if( !mHasExplicitFormat )
{
@@ -1273,7 +1280,11 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
S32 h = raw_h << discard_level;
// setSize may call destroyGLTexture if the size does not match
- setSize(w, h, imageraw->getComponents(), discard_level);
+ if (!setSize(w, h, imageraw->getComponents(), discard_level))
+ {
+ LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
+ return FALSE;
+ }
if( !mHasExplicitFormat )
{
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 21982eab1d..ad2aea9067 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -94,7 +94,7 @@ protected:
public:
virtual void dump(); // debugging info to LL_INFOS()
- void setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
+ bool setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
void setAllowCompression(bool allow) { mAllowCompression = allow; }
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 69420dd0bb..0e242a20f6 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -2039,7 +2039,8 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count)
}
}
- mVerticesp[mCount] = mVerticesp[mCount-1];
+ if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen
+ mVerticesp[mCount] = mVerticesp[mCount-1];
}
void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count)
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index b297223c2e..55f0791174 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -520,7 +520,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
if (!filename.empty())
{
LL_CONT << "From " << filename << ":\n";
- }
+ }
LL_CONT << log << LL_ENDL;
}
}
diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp
index 1d18cb2bb0..06fac190ed 100644
--- a/indra/llui/llclipboard.cpp
+++ b/indra/llui/llclipboard.cpp
@@ -123,7 +123,15 @@ bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool u
// Concatenate the input string to the LL and the system clipboard
bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary)
{
- mString = src.substr(pos, len);
+ try
+ {
+ mString = src.substr(pos, len);
+ }
+ catch (const std::exception& e)
+ {
+ LL_WARNS() << "Can't add the substring to clipboard: " << e.what() << LL_ENDL;
+ return false;
+ }
return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString));
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 1f9869fadc..4f664a1ccc 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2318,7 +2318,8 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLFloaterView::restoreAll()
{
// make sure all subwindows aren't minimized
- for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
+ child_list_t child_list = *(getChildList());
+ for (child_list_const_iter_t child_it = child_list.begin(); child_it != child_list.end(); ++child_it)
{
LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
if (floaterp)
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 1a51b96fdf..1b213c3418 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -186,7 +186,6 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
LLUI::removePopup(view);
}
-
void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)
{
// notes if keyboard focus is changed again (by onFocusLost/onFocusReceived)
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 8166ef6a07..f9664e0658 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -684,6 +684,13 @@ void LLFolderView::draw()
}
}
+ if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().overlaps(mRenamer->getRect()))
+ {
+ // renamer is not connected to the item we are renaming in any form so manage it manually
+ // TODO: consider stopping on any scroll action instead of when out of visible area
+ finishRenamingItem();
+ }
+
// skip over LLFolderViewFolder::draw since we don't want the folder icon, label,
// and arrow for the root folder
LLView::draw();
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 5eb5ca4f82..3d618548c4 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -127,6 +127,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mIsSelected( FALSE ),
mIsCurSelection( FALSE ),
mSelectPending(FALSE),
+ mIsItemCut(false),
+ mCutGeneration(0),
mLabelStyle( LLFontGL::NORMAL ),
mHasVisibleChildren(FALSE),
mIsFolderComplete(true),
@@ -694,6 +696,19 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L
return mIsCurSelection;
}
+/*virtual*/ bool LLFolderViewItem::isFadeItem()
+{
+ LLClipboard& clipboard = LLClipboard::instance();
+ if (mCutGeneration != clipboard.getGeneration())
+ {
+ mCutGeneration = clipboard.getGeneration();
+ mIsItemCut = clipboard.isCutMode()
+ && ((getParentFolder() && getParentFolder()->isFadeItem())
+ || getViewModelItem()->isCutToClipboard());
+ }
+ return mIsItemCut;
+}
+
void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor,
const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor)
{
@@ -875,6 +890,12 @@ void LLFolderViewItem::draw()
}
LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor;
+
+ if (isFadeItem())
+ {
+ // Fade out item color to indicate it's being cut
+ color.mV[VALPHA] *= 0.5f;
+ }
drawLabel(font, text_left, y, color, right_x);
//--------------------------------------------------------------------------------//
@@ -882,7 +903,7 @@ void LLFolderViewItem::draw()
//
if (!mLabelSuffix.empty())
{
- font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor,
+ font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, S32_MAX, &right_x, FALSE );
}
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 0322c8836d..61c39e0175 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -121,8 +121,11 @@ protected:
mIsMouseOverTitle,
mAllowWear,
mAllowDrop,
- mSelectPending;
-
+ mSelectPending,
+ mIsItemCut;
+
+ S32 mCutGeneration;
+
LLUIColor mFontColor;
LLUIColor mFontHighlightColor;
@@ -145,6 +148,7 @@ protected:
virtual void addFolder(LLFolderViewFolder*) { }
virtual bool isHighlightAllowed();
virtual bool isHighlightActive();
+ virtual bool isFadeItem();
virtual bool isFlashing() { return false; }
virtual void setFlashState(bool) { }
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index a395af537a..641241a88c 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -173,6 +173,7 @@ public:
virtual BOOL isItemCopyable() const = 0;
virtual BOOL copyToClipboard() const = 0;
virtual BOOL cutToClipboard() = 0;
+ virtual bool isCutToClipboard() { return false; };
virtual BOOL isClipboardPasteable() const = 0;
virtual void pasteFromClipboard() = 0;
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 492c9315d1..c89e1dac1d 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2636,10 +2636,17 @@ void LLLineEditor::showContextMenu(S32 x, S32 y)
void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
{
- if (new_context_menu)
- mContextMenuHandle = new_context_menu->getHandle();
- else
- mContextMenuHandle.markDead();
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
+
+ if (new_context_menu)
+ {
+ mContextMenuHandle = new_context_menu->getHandle();
+ }
}
void LLLineEditor::setFont(const LLFontGL* font)
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index c6d472f59b..ccbd305a16 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -272,7 +272,7 @@ public:
void setReplaceNewlinesWithSpaces(BOOL replace);
- void setContextMenu(LLContextMenu* new_context_menu);
+ void resetContextMenu() { setContextMenu(NULL); };
private:
// private helper methods
@@ -308,6 +308,8 @@ private:
virtual S32 getPreeditFontSize() const;
virtual LLWString getPreeditString() const { return getWText(); }
+ void setContextMenu(LLContextMenu* new_context_menu);
+
protected:
LLUIString mText; // The string being edited.
std::string mPrevText; // Saved string for 'ESC' revert
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index c7d7535f87..20be739286 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -181,7 +181,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mMaxTextByteLength( p.max_text_length ),
mFont(p.font),
mFontShadow(p.font_shadow),
- mPopupMenu(NULL),
+ mPopupMenuHandle(),
mReadOnly(p.read_only),
mSpellCheck(p.spellcheck),
mSpellCheckStart(-1),
@@ -1263,9 +1263,10 @@ void LLTextBase::setReadOnlyColor(const LLColor4 &c)
//virtual
void LLTextBase::onVisibilityChange( BOOL new_visibility )
{
- if(!new_visibility && mPopupMenu)
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mPopupMenuHandle.get());
+ if(!new_visibility && menu)
{
- mPopupMenu->hide();
+ menu->hide();
}
LLUICtrl::onVisibilityChange(new_visibility);
}
@@ -1956,41 +1957,48 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
// create and return the context menu from the XUI file
- delete mPopupMenu;
+
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mPopupMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
llassert(LLMenuGL::sMenuContainer != NULL);
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
- if (mIsFriendSignal)
- {
- bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url)));
- LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend");
- LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend");
+ menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
- if (addFriendButton && removeFriendButton)
- {
- addFriendButton->setEnabled(!isFriend);
- removeFriendButton->setEnabled(isFriend);
- }
- }
+ if (mIsFriendSignal)
+ {
+ bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url)));
+ LLView* addFriendButton = menu->getChild<LLView>("add_friend");
+ LLView* removeFriendButton = menu->getChild<LLView>("remove_friend");
- if (mIsObjectBlockedSignal)
- {
- bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url));
- LLView* blockButton = mPopupMenu->getChild<LLView>("block_object");
- LLView* unblockButton = mPopupMenu->getChild<LLView>("unblock_object");
+ if (addFriendButton && removeFriendButton)
+ {
+ addFriendButton->setEnabled(!isFriend);
+ removeFriendButton->setEnabled(isFriend);
+ }
+ }
- if (blockButton && unblockButton)
- {
- blockButton->setVisible(!is_blocked);
- unblockButton->setVisible(is_blocked);
- }
- }
-
- if (mPopupMenu)
- {
- mPopupMenu->show(x, y);
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
- }
+ if (mIsObjectBlockedSignal)
+ {
+ bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url));
+ LLView* blockButton = menu->getChild<LLView>("block_object");
+ LLView* unblockButton = menu->getChild<LLView>("unblock_object");
+
+ if (blockButton && unblockButton)
+ {
+ blockButton->setVisible(!is_blocked);
+ unblockButton->setVisible(is_blocked);
+ }
+ }
+ menu->show(x, y);
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
}
void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 85641fd899..3d3a6ca869 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -673,7 +673,7 @@ protected:
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
// support widgets
- LLContextMenu* mPopupMenu;
+ LLHandle<LLContextMenu> mPopupMenuHandle;
LLView* mDocumentView;
LLScrollContainer* mScroller;
diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp
index 324ceb7fba..bfe0a5bb5d 100644
--- a/indra/llui/lltextvalidate.cpp
+++ b/indra/llui/lltextvalidate.cpp
@@ -328,6 +328,15 @@ namespace LLTextValidate
return rv;
}
+ bool validateASCIINoLeadingSpace(const LLWString &str)
+ {
+ if (LLStringOps::isSpace(str[0]))
+ {
+ return FALSE;
+ }
+ return validateASCII(str);
+ }
+
// Used for multiline text stored on the server.
// Example is landmark description in Places SP.
bool validateASCIIWithNewLine(const LLWString &str)
diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h
index 5c830d7db3..e2b6c313d6 100644
--- a/indra/llui/lltextvalidate.h
+++ b/indra/llui/lltextvalidate.h
@@ -52,6 +52,7 @@ namespace LLTextValidate
bool validateASCIIPrintableNoPipe(const LLWString &str);
bool validateASCIIPrintableNoSpace(const LLWString &str);
bool validateASCII(const LLWString &str);
+ bool validateASCIINoLeadingSpace(const LLWString &str);
bool validateASCIIWithNewLine(const LLWString &str);
}
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index aabc7ed2e4..f790d8e005 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -522,7 +522,7 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)
else
{
std::string part(ti->begin(), ti->end());
- context = context->findChildView(part, recurse);
+ context = context->findChildView(LLURI::unescape(part), recurse);
recurse = false;
}
}
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e4848362a7..27a2456deb 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -183,8 +183,9 @@ bool LLUrlEntryBase::isLinkDisabled() const
bool LLUrlEntryBase::isWikiLinkCorrect(std::string url)
{
- std::string label = getLabelFromWikiLink(url);
- return (LLUrlRegistry::instance().hasUrl(label)) ? false : true;
+ LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url));
+ label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end());
+ return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true;
}
std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const
@@ -205,9 +206,15 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const
std::string label;
up.extractParts();
- up.glueFirst(label);
- std::string query = url.substr(label.size());
- return query;
+ up.glueFirst(label, false);
+
+ size_t pos = url.find(label);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+ pos += label.size();
+ return url.substr(pos);
}
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 62c3f401bf..9604e5ce10 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -391,7 +391,27 @@ static void buildPathname(std::ostream& out, const LLView* view)
buildPathname(out, view->getParent());
// Build pathname into ostream on the way back from recursion.
- out << '/' << view->getName();
+ out << '/';
+
+ // substitute all '/' in name with appropriate code
+ std::string name = view->getName();
+ std::size_t found = name.find('/');
+ std::size_t start = 0;
+ while (found != std::string::npos)
+ {
+ std::size_t sub_len = found - start;
+ if (sub_len > 0)
+ {
+ out << name.substr(start, sub_len);
+ }
+ out << "%2F";
+ start = found + 1;
+ found = name.find('/', start);
+ }
+ if (start < name.size())
+ {
+ out << name.substr(start, name.size() - start);
+ }
}
std::string LLView::getPathname() const
@@ -812,7 +832,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
{
if (!getVisible())
- return false;
+ return NULL;
BOOST_FOREACH(LLView* viewp, mChildList)
{
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 5f4fb8f4a0..86a15f2ef2 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -531,6 +531,13 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
case LL_PATH_PER_ACCOUNT_CHAT_LOGS:
prefix = getPerAccountChatLogsDir();
+ if (prefix.empty())
+ {
+ // potentially directory was not set yet
+ // intentionally return a blank string to the caller
+ LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL;
+ return std::string();
+ }
break;
case LL_PATH_LOGS:
diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h
index faa5d3abb7..6daf1ac55b 100644
--- a/indra/llwindow/llappdelegate-objc.h
+++ b/indra/llwindow/llappdelegate-objc.h
@@ -41,7 +41,7 @@
@property (retain) NSString *currentInputLanguage;
-- (void) mainLoop;
+- (void) oneFrame;
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
- (void) languageUpdated;
- (bool) romanScript;
diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp
index d00d9ab47e..0d1a47408b 100644
--- a/indra/llwindow/lldragdropwin32.cpp
+++ b/indra/llwindow/lldragdropwin32.cpp
@@ -113,7 +113,7 @@ class LLDragDropWin32Target:
PVOID data = GlobalLock( stgmed.hGlobal );
mDropUrl = std::string( (char*)data );
// XXX MAJOR MAJOR HACK!
- LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
@@ -168,7 +168,7 @@ class LLDragDropWin32Target:
if ( mAllowDrop )
{
// XXX MAJOR MAJOR HACK!
- LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
@@ -215,7 +215,7 @@ class LLDragDropWin32Target:
HRESULT __stdcall DragLeave( void )
{
// XXX MAJOR MAJOR HACK!
- LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
@@ -232,7 +232,7 @@ class LLDragDropWin32Target:
if ( mAllowDrop )
{
// window impl stored in Window data (neat!)
- LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if ( NULL != window_imp )
{
POINT pt_client;
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 0a30f4c807..a05ba8cbba 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -166,6 +166,8 @@ public:
// Provide native key event data
virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
+ // Get system UI size based on DPI (for 96 DPI UI size should be 1.0)
+ virtual F32 getSystemUISize() { return 1.0; }
protected:
LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
virtual ~LLWindow();
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index d2afb3f91b..474953d3a4 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -175,6 +175,11 @@ BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window)
return FALSE;
}
+void LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
+{
+
+}
+
void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
{
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 6a7137e593..de789a71d9 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -65,6 +65,7 @@ public:
virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
virtual BOOL handleTimerEvent(LLWindow *window);
virtual BOOL handleDeviceChange(LLWindow *window);
+ virtual void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
enum DragNDropAction {
DNDA_START_TRACKING = 0,// Start tracking an incoming drag
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index c22f3382fb..b06cd2c184 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -69,7 +69,7 @@ typedef const NativeKeyEventData * NSKeyEventRef;
// These are defined in llappviewermacosx.cpp.
bool initViewer();
void handleQuit();
-bool runMainLoop();
+bool pumpMainLoop();
void initMainLoop();
void cleanupViewer();
void handleUrl(const char* url);
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 875ffe4cd4..55e68283b7 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -60,24 +60,50 @@
#include <dinput.h>
#include <Dbt.h.>
-// culled from winuser.h
-#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */
-const S32 WM_MOUSEWHEEL = 0x020A;
-#endif
-#ifndef WHEEL_DELTA /* Added to be compatible with later SDK's */
-const S32 WHEEL_DELTA = 120; /* Value for rolling one detent */
-#endif
const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
const F32 ICON_FLASH_TIME = 0.5f;
+#ifndef WM_DPICHANGED
+#define WM_DPICHANGED 0x02E0
+#endif
+
extern BOOL gDebugWindowProc;
LPWSTR gIconResource = IDI_APPLICATION;
LLW32MsgCallback gAsyncMsgCallback = NULL;
+#ifndef DPI_ENUMS_DECLARED
+
+typedef enum PROCESS_DPI_AWARENESS {
+ PROCESS_DPI_UNAWARE = 0,
+ PROCESS_SYSTEM_DPI_AWARE = 1,
+ PROCESS_PER_MONITOR_DPI_AWARE = 2
+} PROCESS_DPI_AWARENESS;
+
+typedef enum MONITOR_DPI_TYPE {
+ MDT_EFFECTIVE_DPI = 0,
+ MDT_ANGULAR_DPI = 1,
+ MDT_RAW_DPI = 2,
+ MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+
+#endif
+
+typedef HRESULT(STDAPICALLTYPE *SetProcessDpiAwarenessType)(_In_ PROCESS_DPI_AWARENESS value);
+
+typedef HRESULT(STDAPICALLTYPE *GetProcessDpiAwarenessType)(
+ _In_ HANDLE hprocess,
+ _Out_ PROCESS_DPI_AWARENESS *value);
+
+typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
+ _In_ HMONITOR hmonitor,
+ _In_ MONITOR_DPI_TYPE dpiType,
+ _Out_ UINT *dpiX,
+ _Out_ UINT *dpiY);
+
//
// LLWindowWin32
//
@@ -759,7 +785,7 @@ void LLWindowWin32::close()
LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
// Don't process events in our mainWindowProc any longer.
- SetWindowLong(mWindowHandle, GWL_USERDATA, NULL);
+ SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, NULL);
// Make sure we don't leave a blank toolbar button.
ShowWindow(mWindowHandle, SW_HIDE);
@@ -1538,7 +1564,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL;
}
- SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
+ SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this);
// register this window as handling drag/drop events from the OS
DragAcceptFiles( mWindowHandle, TRUE );
@@ -1850,7 +1876,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// This is to avoid triggering double click teleport after returning focus (see MAINT-3786).
static bool sHandleDoubleClick = true;
- LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( h_wnd, GWLP_USERDATA );
if (NULL != window_imp)
@@ -2593,6 +2619,24 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return 0;
}
+
+ case WM_DPICHANGED:
+ {
+ LPRECT lprc_new_scale;
+ F32 new_scale = LOWORD(w_param) / USER_DEFAULT_SCREEN_DPI;
+ lprc_new_scale = (LPRECT)l_param;
+ S32 new_width = lprc_new_scale->right - lprc_new_scale->left;
+ S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top;
+ window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height);
+ SetWindowPos(h_wnd,
+ HWND_TOP,
+ lprc_new_scale->left,
+ lprc_new_scale->top,
+ new_width,
+ new_height,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ return 0;
+ }
case WM_SETFOCUS:
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS");
@@ -3879,6 +3923,92 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
}
//static
+void LLWindowWin32::setDPIAwareness()
+{
+ HMODULE hShcore = LoadLibrary(L"shcore.dll");
+ if (hShcore != NULL)
+ {
+ SetProcessDpiAwarenessType pSPDA;
+ pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
+ if (pSPDA)
+ {
+
+ HRESULT hr = pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
+ if (hr != S_OK)
+ {
+ LL_WARNS() << "SetProcessDpiAwareness() function returned an error. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ }
+ }
+ FreeLibrary(hShcore);
+ }
+ else
+ {
+ LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ }
+}
+
+F32 LLWindowWin32::getSystemUISize()
+{
+ float scale_value = 0;
+ HWND hWnd = (HWND)getPlatformWindow();
+ HDC hdc = GetDC(hWnd);
+ HMONITOR hMonitor;
+ HANDLE hProcess = GetCurrentProcess();
+ PROCESS_DPI_AWARENESS dpi_awareness;
+
+ HMODULE hShcore = LoadLibrary(L"shcore.dll");
+
+ if (hShcore != NULL)
+ {
+ GetProcessDpiAwarenessType pGPDA;
+ pGPDA = (GetProcessDpiAwarenessType)GetProcAddress(hShcore, "GetProcessDpiAwareness");
+ GetDpiForMonitorType pGDFM;
+ pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor");
+ if (pGPDA != NULL && pGDFM != NULL)
+ {
+ pGPDA(hProcess, &dpi_awareness);
+ if (dpi_awareness == PROCESS_PER_MONITOR_DPI_AWARE)
+ {
+ POINT pt;
+ UINT dpix = 0, dpiy = 0;
+ HRESULT hr = E_FAIL;
+ RECT rect;
+
+ GetWindowRect(hWnd, &rect);
+ // Get the DPI for the monitor, on which the center of window is displayed and set the scaling factor
+ pt.x = (rect.left + rect.right) / 2;
+ pt.y = (rect.top + rect.bottom) / 2;
+ hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+ hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
+ if (hr == S_OK)
+ {
+ scale_value = dpix / USER_DEFAULT_SCREEN_DPI;
+ }
+ else
+ {
+ LL_WARNS() << "Could not determine DPI for monitor. Setting scale to default 100 %" << LL_ENDL;
+ scale_value = 1.0f;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Process is not per-monitor DPI-aware. Setting scale to default 100 %" << LL_ENDL;
+ scale_value = 1.0f;
+ }
+ }
+ FreeLibrary(hShcore);
+ }
+ else
+ {
+ LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / USER_DEFAULT_SCREEN_DPI;
+ }
+
+ ReleaseDC(hWnd, hdc);
+ return scale_value;
+}
+
+//static
std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
{
// Fonts previously in getFontListSans() have moved to fonts.xml.
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 1a775eadaf..39ef9b31a4 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -110,10 +110,12 @@ public:
/*virtual*/ void interruptLanguageTextInput();
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ /*virtual*/ F32 getSystemUISize();
+
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
static std::vector<std::string> getDynamicFallbackFontList();
-
+ static void setDPIAwareness();
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp
index 3149fad6e8..ec3616e26a 100644
--- a/indra/mac_crash_logger/llcrashloggermac.cpp
+++ b/indra/mac_crash_logger/llcrashloggermac.cpp
@@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()
{
}
-bool LLCrashLoggerMac::mainLoop()
+bool LLCrashLoggerMac::frame()
{
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
diff --git a/indra/mac_crash_logger/llcrashloggermac.h b/indra/mac_crash_logger/llcrashloggermac.h
index 6d8f63ecac..05ef8c9f53 100644
--- a/indra/mac_crash_logger/llcrashloggermac.h
+++ b/indra/mac_crash_logger/llcrashloggermac.h
@@ -37,7 +37,7 @@ public:
LLCrashLoggerMac(void);
~LLCrashLoggerMac(void);
virtual bool init();
- virtual bool mainLoop();
+ virtual bool frame();
virtual bool cleanup();
virtual void gatherPlatformSpecificFiles();
};
diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp
index 95d4e65207..54e41a1954 100644
--- a/indra/mac_crash_logger/mac_crash_logger.cpp
+++ b/indra/mac_crash_logger/mac_crash_logger.cpp
@@ -49,7 +49,7 @@ int main(int argc, char **argv)
{
// return NSApplicationMain(argc, (const char **)argv);
}
- app.mainLoop();
+ app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index 24eb3947b4..22af50ab26 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -4,15 +4,15 @@ add_subdirectory(base)
if (LINUX)
add_subdirectory(gstreamer010)
+ add_subdirectory(libvlc)
endif (LINUX)
-if (WINDOWS OR DARWIN)
- add_subdirectory(quicktime)
+if (DARWIN)
add_subdirectory(cef)
-endif (WINDOWS OR DARWIN)
+endif (DARWIN)
if (WINDOWS)
+ add_subdirectory(cef)
add_subdirectory(winmmshim)
+ add_subdirectory(libvlc)
endif (WINDOWS)
-
-### add_subdirectory(example)
diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/media_plugins/base/CMakeLists.txt
index 7367b9e5e6..70c81d4023 100644
--- a/indra/media_plugins/base/CMakeLists.txt
+++ b/indra/media_plugins/base/CMakeLists.txt
@@ -28,13 +28,13 @@ include_directories(SYSTEM
### media_plugin_base
-if(NOT WORD_SIZE EQUAL 32)
+if(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ ##add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
-endif(NOT WORD_SIZE EQUAL 32)
+endif(NOT ADDRESS_SIZE EQUAL 32)
set(media_plugin_base_SOURCE_FILES
media_plugin_base.cpp
diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt
index db471c7906..5db0a8fbfd 100644
--- a/indra/media_plugins/cef/CMakeLists.txt
+++ b/indra/media_plugins/cef/CMakeLists.txt
@@ -34,13 +34,13 @@ include_directories(SYSTEM
### media_plugin_cef
-if(NOT WORD_SIZE EQUAL 32)
+if(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ ##add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
-endif(NOT WORD_SIZE EQUAL 32)
+endif(NOT ADDRESS_SIZE EQUAL 32)
set(media_plugin_cef_SOURCE_FILES
media_plugin_cef.cpp
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index 8d9d1dd975..d04bc16d4f 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -100,6 +100,12 @@ private:
LLCEFLib* mLLCEFLib;
VolumeCatcher mVolumeCatcher;
+
+ U8 *mPopupBuffer;
+ U32 mPopupW;
+ U32 mPopupH;
+ U32 mPopupX;
+ U32 mPopupY;
};
////////////////////////////////////////////////////////////////////////////////
@@ -127,12 +133,19 @@ MediaPluginBase(host_send_func, host_user_data)
mCookiePath = "";
mPickedFile = "";
mLLCEFLib = new LLCEFLib();
+
+ mPopupBuffer = NULL;
+ mPopupW = 0;
+ mPopupH = 0;
+ mPopupX = 0;
+ mPopupY = 0;
}
////////////////////////////////////////////////////////////////////////////////
//
MediaPluginCEF::~MediaPluginCEF()
{
+ delete[] mPopupBuffer;
}
////////////////////////////////////////////////////////////////////////////////
@@ -155,20 +168,28 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg)
//
void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup)
{
- if (mPixels && pixels)
+ if( is_popup )
+ {
+ delete mPopupBuffer;
+ mPopupBuffer = NULL;
+ mPopupH = 0;
+ mPopupW = 0;
+ mPopupX = 0;
+ mPopupY = 0;
+ }
+
+ if( mPixels && pixels )
{
if (is_popup)
{
- for (int line = 0; line < height; ++line)
+ if( width > 0 && height> 0 )
{
- int inverted_y = mHeight - y - height;
- int src = line * width * mDepth;
- int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth;
-
- if (dst + width * mDepth < mWidth * mHeight * mDepth)
- {
- memcpy(mPixels + dst, pixels + src, width * mDepth);
- }
+ mPopupBuffer = new U8[ width * height * mDepth ];
+ memcpy( mPopupBuffer, pixels, width * height * mDepth );
+ mPopupH = height;
+ mPopupW = width;
+ mPopupX = x;
+ mPopupY = mHeight - y - height;
}
}
else
@@ -177,6 +198,23 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y,
{
memcpy(mPixels, pixels, mWidth * mHeight * mDepth);
}
+ if( mPopupBuffer && mPopupH && mPopupW )
+ {
+ U32 bufferSize = mWidth * mHeight * mDepth;
+ U32 popupStride = mPopupW * mDepth;
+ U32 bufferStride = mWidth * mDepth;
+ int dstY = mPopupY;
+
+ int src = 0;
+ int dst = dstY * mWidth * mDepth + mPopupX * mDepth;
+
+ for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line )
+ {
+ memcpy( mPixels + dst, mPopupBuffer + src, popupStride );
+ src += popupStride;
+ dst += bufferStride;
+ }
+ }
}
setDirty(0, 0, mWidth, mHeight);
@@ -463,6 +501,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
LLCEFLib::LLCEFLibSettings settings;
settings.initial_width = 1024;
settings.initial_height = 1024;
+ // The LLCEFLibSettings struct in the Windows 32-bit
+ // llceflib's build 500907 does not have a page_zoom_factor
+ // member. Set below.
+ //settings.page_zoom_factor = message_in.getValueReal("factor");
settings.plugins_enabled = mPluginsEnabled;
settings.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granualrity/query UI
settings.javascript_enabled = mJavascriptEnabled;
@@ -479,6 +521,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
// if this fails, the media system in viewer will put up a message
}
+ // now we can set page zoom factor
+ mLLCEFLib->setPageZoom(message_in.getValueReal("factor"));
+
// Plugin gets to decide the texture parameters to use.
mDepth = 4;
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
@@ -559,6 +604,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
S32 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
+ y = mHeight - y;
+
// only even send left mouse button events to LLCEFLib
// (partially prompted by crash in OS X CEF when sending right button events)
// we catch the right click in viewer and display our own context menu anyway
diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt
index 171645ef04..d2a17b1d76 100644
--- a/indra/media_plugins/example/CMakeLists.txt
+++ b/indra/media_plugins/example/CMakeLists.txt
@@ -32,13 +32,13 @@ include_directories(SYSTEM
### media_plugin_example
-if(NOT WORD_SIZE EQUAL 32)
+if(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ ##add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
-endif(NOT WORD_SIZE EQUAL 32)
+endif(NOT ADDRESS_SIZE EQUAL 32)
set(media_plugin_example_SOURCE_FILES
media_plugin_example.cpp
diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt
index 447f6e0689..6d18814b1e 100644
--- a/indra/media_plugins/gstreamer010/CMakeLists.txt
+++ b/indra/media_plugins/gstreamer010/CMakeLists.txt
@@ -33,13 +33,13 @@ include_directories(SYSTEM
### media_plugin_gstreamer010
-if(NOT WORD_SIZE EQUAL 32)
+if(NOT ADDRESS_SIZE EQUAL 32)
if(WINDOWS)
- add_definitions(/FIXED:NO)
+ ##add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
-endif(NOT WORD_SIZE EQUAL 32)
+endif(NOT ADDRESS_SIZE EQUAL 32)
set(media_plugin_gstreamer010_SOURCE_FILES
media_plugin_gstreamer010.cpp
diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt
new file mode 100644
index 0000000000..32574c7afa
--- /dev/null
+++ b/indra/media_plugins/libvlc/CMakeLists.txt
@@ -0,0 +1,86 @@
+# -*- cmake -*-
+
+project(media_plugin_libvlc)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(OpenGL)
+
+include(LibVLCPlugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ ${VLC_INCLUDE_DIR}
+)
+include_directories(SYSTEM
+ ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
+ )
+
+
+### media_plugin_libvlc
+
+if(NOT ADDRESS_SIZE EQUAL 32)
+ if(WINDOWS)
+ ##add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT ADDRESS_SIZE EQUAL 32)
+
+set(media_plugin_libvlc_SOURCE_FILES
+ media_plugin_libvlc.cpp
+ )
+
+add_library(media_plugin_libvlc
+ SHARED
+ ${media_plugin_libvlc_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_libvlc
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${VLC_PLUGIN_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_libvlc
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ media_plugin_libvlc
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT"
+ )
+endif (WINDOWS)
+
+if (DARWIN)
+ # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+ set_target_properties(
+ media_plugin_libvlc
+ PROPERTIES
+ PREFIX ""
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path"
+ LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+ )
+
+endif (DARWIN)
diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
new file mode 100644
index 0000000000..0bd323eb58
--- /dev/null
+++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
@@ -0,0 +1,618 @@
+/**
+* @file media_plugin_libvlc.cpp
+* @brief LibVLC plugin for LLMedia API plugin system
+*
+* @cond
+* $LicenseInfo:firstyear=2008&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+* @endcond
+*/
+
+#include "linden_common.h"
+
+#include "llgl.h"
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#include "vlc/vlc.h"
+#include "vlc/libvlc_version.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginLibVLC :
+ public MediaPluginBase
+{
+public:
+ MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginLibVLC();
+
+ /*virtual*/ void receiveMessage(const char* message_string);
+
+private:
+ bool init();
+
+ void initVLC();
+ void playMedia();
+ void resetVLC();
+ void setVolume(const F64 volume);
+ void updateTitle(const char* title);
+
+ static void* lock(void* data, void** p_pixels);
+ static void unlock(void* data, void* id, void* const* raw_pixels);
+ static void display(void* data, void* id);
+
+ /*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */;
+
+ static void eventCallbacks(const libvlc_event_t* event, void* ptr);
+
+ libvlc_instance_t* mLibVLC;
+ libvlc_media_t* mLibVLCMedia;
+ libvlc_media_player_t* mLibVLCMediaPlayer;
+
+ struct mLibVLCContext
+ {
+ unsigned char* texture_pixels;
+ libvlc_media_player_t* mp;
+ MediaPluginLibVLC* parent;
+ };
+ struct mLibVLCContext mLibVLCCallbackContext;
+
+ std::string mURL;
+ F64 mCurVolume;
+
+ bool mIsLooping;
+
+ float mCurTime;
+ float mDuration;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
+MediaPluginBase(host_send_func, host_user_data)
+{
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mDepth = 4;
+ mPixels = 0;
+
+ mLibVLC = 0;
+ mLibVLCMedia = 0;
+ mLibVLCMediaPlayer = 0;
+
+ mCurVolume = 0.0;
+
+ mIsLooping = false;
+
+ mCurTime = 0.0;
+ mDuration = 0.0;
+
+ mURL = std::string();
+
+ setStatus(STATUS_NONE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginLibVLC::~MediaPluginLibVLC()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+void* MediaPluginLibVLC::lock(void* data, void** p_pixels)
+{
+ struct mLibVLCContext* context = (mLibVLCContext*)data;
+
+ *p_pixels = context->texture_pixels;
+
+ return NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels)
+{
+ // nothing to do here for the moment
+ // we *could* modify pixels here to, for example, Y flip, but this is done with
+ // a VLC video filter transform.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::display(void* data, void* id)
+{
+ struct mLibVLCContext* context = (mLibVLCContext*)data;
+
+ context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::initVLC()
+{
+ char const* vlc_argv[] =
+ {
+ "--no-xlib",
+ "--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client
+ };
+
+ int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
+ mLibVLC = libvlc_new(vlc_argc, vlc_argv);
+
+ if (!mLibVLC)
+ {
+ // for the moment, if this fails, the plugin will fail and
+ // the media sub-system will tell the viewer something went wrong.
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::resetVLC()
+{
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+ libvlc_release(mLibVLC);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// *virtual*
+void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
+
+ message.setValueS32("left", left);
+ message.setValueS32("top", top);
+ message.setValueS32("right", right);
+ message.setValueS32("bottom", bottom);
+
+ message.setValueReal("current_time", mCurTime);
+ message.setValueReal("duration", mDuration);
+ message.setValueReal("current_rate", 1.0f);
+
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
+{
+ MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr;
+ if (parent == 0)
+ {
+ return;
+ }
+
+ switch (event->type)
+ {
+ case libvlc_MediaPlayerOpening:
+ parent->setStatus(STATUS_LOADING);
+ break;
+
+ case libvlc_MediaPlayerPlaying:
+ parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f;
+ parent->setStatus(STATUS_PLAYING);
+ break;
+
+ case libvlc_MediaPlayerPaused:
+ parent->setStatus(STATUS_PAUSED);
+ break;
+
+ case libvlc_MediaPlayerStopped:
+ parent->setStatus(STATUS_DONE);
+ break;
+
+ case libvlc_MediaPlayerEndReached:
+ parent->setStatus(STATUS_DONE);
+ break;
+
+ case libvlc_MediaPlayerEncounteredError:
+ parent->setStatus(STATUS_ERROR);
+ break;
+
+ case libvlc_MediaPlayerTimeChanged:
+ parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f;
+ break;
+
+ case libvlc_MediaPlayerPositionChanged:
+ break;
+
+ case libvlc_MediaPlayerLengthChanged:
+ parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f;
+ break;
+
+ case libvlc_MediaPlayerTitleChanged:
+ {
+ char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title);
+ if (title)
+ {
+ parent->updateTitle(title);
+ }
+ }
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::playMedia()
+{
+ if (mURL.length() == 0)
+ {
+ return;
+ }
+
+ if (mLibVLCMediaPlayer)
+ {
+ // stop listening to events while we reset things
+ libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
+ if (em)
+ {
+ libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL);
+ libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL);
+ };
+
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+
+ mLibVLCMediaPlayer = 0;
+ }
+
+ if (mLibVLCMedia)
+ {
+ libvlc_media_release(mLibVLCMedia);
+
+ mLibVLCMedia = 0;
+ }
+
+ mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
+ if (!mLibVLCMedia)
+ {
+ mLibVLCMediaPlayer = 0;
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia);
+ if (!mLibVLCMediaPlayer)
+ {
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ // listen to events
+ libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
+ if (em)
+ {
+ libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this);
+ libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
+ }
+
+ mLibVLCCallbackContext.parent = this;
+ mLibVLCCallbackContext.texture_pixels = mPixels;
+ mLibVLCCallbackContext.mp = mLibVLCMediaPlayer;
+
+ // Send a "navigate begin" event.
+ // This is really a browser message but the QuickTime plugin did it and
+ // the media system relies on this message to update internal state so we must send it too
+ // Note: see "navigate_complete" message below too
+ // https://jira.secondlife.com/browse/MAINT-6528
+ LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ message_begin.setValue("uri", mURL);
+ message_begin.setValueBoolean("history_back_available", false);
+ message_begin.setValueBoolean("history_forward_available", false);
+ sendMessage(message_begin);
+
+ // volume level gets set before VLC is initialized (thanks media system) so we have to record
+ // it in mCurVolume and set it again here so that volume levels are correctly initialized
+ setVolume(mCurVolume);
+
+ setStatus(STATUS_LOADED);
+
+ libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
+ libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
+
+ // note this relies on the "set_loop" message arriving before the "start" (play) one
+ // but that appears to always be the case
+ if (mIsLooping)
+ {
+ libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1");
+ }
+
+ libvlc_media_player_play(mLibVLCMediaPlayer);
+
+ // send a "location_changed" message - this informs the media system
+ // that a new URL is the 'current' one and is used extensively.
+ // Again, this is really a browser message but we will use it here.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
+ message.setValue("uri", mURL);
+ sendMessage(message);
+
+ // Send a "navigate complete" event.
+ // This is really a browser message but the QuickTime plugin did it and
+ // the media system relies on this message to update internal state so we must send it too
+ // Note: see "navigate_begin" message above too
+ // https://jira.secondlife.com/browse/MAINT-6528
+ LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ message_complete.setValue("uri", mURL);
+ message_complete.setValueS32("result_code", 200);
+ message_complete.setValue("result_string", "OK");
+ sendMessage(message_complete);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::updateTitle(const char* title)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", title);
+ sendMessage(message);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::setVolume(const F64 volume)
+{
+ mCurVolume = volume;
+
+ if (mLibVLCMediaPlayer)
+ {
+ int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, (int)(volume * 100));
+ if (result != 0)
+ {
+ // volume wasn't set but not much to be done here
+ }
+ }
+ else
+ {
+ // volume change was requested but VLC wasn't ready.
+ // that's okay thought because we saved the value in mCurVolume and
+ // the next volume change after the VLC system is initilzied will set it
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginLibVLC::receiveMessage(const char* message_string)
+{
+ LLPluginMessage message_in;
+
+ if (message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if (message_name == "init")
+ {
+ initVLC();
+
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::ostringstream s;
+ s << "LibVLC plugin ";
+ s << LIBVLC_VERSION_MAJOR;
+ s << ".";
+ s << LIBVLC_VERSION_MINOR;
+ s << ".";
+ s << LIBVLC_VERSION_REVISION;
+
+ message.setValue("plugin_version", s.str());
+ sendMessage(message);
+ }
+ else if (message_name == "idle")
+ {
+ }
+ else if (message_name == "cleanup")
+ {
+ resetVLC();
+ }
+ else if (message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+ }
+ else if (message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if (iter != mSharedSegments.end())
+ {
+ if (mPixels == iter->second.mAddress)
+ {
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ libvlc_media_player_release(mLibVLCMediaPlayer);
+ mLibVLCMediaPlayer = 0;
+
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+ //std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ //std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if (message_name == "init")
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGB);
+ message.setValueU32("format", GL_BGRA_EXT);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else if (message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ if (!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if (iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ playMedia();
+ };
+ };
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+ }
+ else if (message_name == "load_uri")
+ {
+ mURL = message_in.getValue("uri");
+ playMedia();
+ }
+ }
+ else
+ if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if (message_name == "stop")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_stop(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "start")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_play(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "pause")
+ {
+ if (mLibVLCMediaPlayer)
+ {
+ libvlc_media_player_pause(mLibVLCMediaPlayer);
+ }
+ }
+ else if (message_name == "seek")
+ {
+ if (mDuration > 0)
+ {
+ F64 normalized_offset = message_in.getValueReal("time") / mDuration;
+ libvlc_media_player_set_position(mLibVLCMediaPlayer, normalized_offset);
+ }
+ }
+ else if (message_name == "set_loop")
+ {
+ mIsLooping = true;
+ }
+ else if (message_name == "set_volume")
+ {
+ // volume comes in 0 -> 1.0
+ F64 volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginLibVLC::init()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", "LibVLC Plugin");
+ sendMessage(message);
+
+ return true;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func,
+ void* host_user_data,
+ LLPluginInstance::sendMessageFunction *plugin_send_func,
+ void **plugin_user_data)
+{
+ MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginLibVLC::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
deleted file mode 100644
index c5615145be..0000000000
--- a/indra/media_plugins/quicktime/CMakeLists.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- cmake -*-
-
-project(media_plugin_quicktime)
-
-include(00-Common)
-include(LLCommon)
-include(LLImage)
-include(LLPlugin)
-include(LLMath)
-include(LLRender)
-include(LLWindow)
-include(Linking)
-include(PluginAPI)
-include(MediaPluginBase)
-include(OpenGL)
-include(QuickTimePlugin)
-include(Boost)
-
-include_directories(
- ${LLPLUGIN_INCLUDE_DIRS}
- ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
- ${LLCOMMON_INCLUDE_DIRS}
- ${LLMATH_INCLUDE_DIRS}
- ${LLIMAGE_INCLUDE_DIRS}
- ${LLRENDER_INCLUDE_DIRS}
- ${LLWINDOW_INCLUDE_DIRS}
-)
-include_directories(SYSTEM
- ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
- )
-
-if (DARWIN)
- include(CMakeFindFrameworks)
- find_library(CARBON_LIBRARY Carbon)
-endif (DARWIN)
-
-
-### media_plugin_quicktime
-
-set(media_plugin_quicktime_SOURCE_FILES
- media_plugin_quicktime.cpp
- )
-
-add_library(media_plugin_quicktime
- SHARED
- ${media_plugin_quicktime_SOURCE_FILES}
-)
-
-target_link_libraries(media_plugin_quicktime
- ${LLPLUGIN_LIBRARIES}
- ${MEDIA_PLUGIN_BASE_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- ${QUICKTIME_LIBRARY}
- ${PLUGIN_API_WINDOWS_LIBRARIES}
-)
-
-if (WINDOWS)
- set_target_properties(
- media_plugin_quicktime
- PROPERTIES
- LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
- LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD"
- )
-endif (WINDOWS)
-
-if (QUICKTIME)
-
- add_definitions(-DLL_QUICKTIME_ENABLED=1)
-
- if (DARWIN)
- # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
- set_target_properties(
- media_plugin_quicktime
- PROPERTIES
- PREFIX ""
- BUILD_WITH_INSTALL_RPATH 1
- INSTALL_NAME_DIR "@executable_path"
- LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
- )
-
-# We use a bunch of deprecated system APIs.
- set_source_files_properties(
- media_plugin_quicktime.cpp PROPERTIES
- COMPILE_FLAGS -Wno-deprecated-declarations
- )
- find_library(CARBON_LIBRARY Carbon)
- target_link_libraries(media_plugin_quicktime ${CARBON_LIBRARY})
- endif (DARWIN)
-endif (QUICKTIME)
-
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
deleted file mode 100644
index 7ef5a0fe44..0000000000
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ /dev/null
@@ -1,1084 +0,0 @@
-/**
- * @file media_plugin_quicktime.cpp
- * @brief QuickTime plugin for LLMedia API plugin system
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-
-#include "llgl.h"
-
-#include "llplugininstance.h"
-#include "llpluginmessage.h"
-#include "llpluginmessageclasses.h"
-#include "media_plugin_base.h"
-
-#if LL_QUICKTIME_ENABLED
-
-#if defined(LL_DARWIN)
-#include <QuickTime/QuickTime.h>
-#elif defined(LL_WINDOWS)
-#include "llwin32headers.h"
-#include "MacTypes.h"
-#include "QTML.h"
-#include "Movies.h"
-#include "QDoffscreen.h"
-#include "FixMath.h"
-#include "QTLoadLibraryUtils.h"
-#endif
-
-
-
-// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
-////////////////////////////////////////////////////////////////////////////////
-//
-class MediaPluginQuickTime : public MediaPluginBase
-{
-public:
- MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
- ~MediaPluginQuickTime();
-
- /* virtual */ void receiveMessage(const char *message_string);
-
-private:
-
- int mNaturalWidth;
- int mNaturalHeight;
- Movie mMovieHandle;
- GWorldPtr mGWorldHandle;
- ComponentInstance mMovieController;
- int mCurVolume;
- bool mMediaSizeChanging;
- bool mIsLooping;
- std::string mMovieTitle;
- bool mReceivedTitle;
- const int mMinWidth;
- const int mMaxWidth;
- const int mMinHeight;
- const int mMaxHeight;
- F64 mPlayRate;
- std::string mNavigateURL;
-
- enum ECommand {
- COMMAND_NONE,
- COMMAND_STOP,
- COMMAND_PLAY,
- COMMAND_FAST_FORWARD,
- COMMAND_FAST_REWIND,
- COMMAND_PAUSE,
- COMMAND_SEEK,
- };
- ECommand mCommand;
-
- // Override this to add current time and duration to the message
- /*virtual*/ void setDirty(int left, int top, int right, int bottom)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
-
- message.setValueS32("left", left);
- message.setValueS32("top", top);
- message.setValueS32("right", right);
- message.setValueS32("bottom", bottom);
-
- if(mMovieHandle)
- {
- message.setValueReal("current_time", getCurrentTime());
- message.setValueReal("duration", getDuration());
- message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle)));
- }
-
- sendMessage(message);
- }
-
-
- static Rect rectFromSize(int width, int height)
- {
- Rect result;
-
-
- result.left = 0;
- result.top = 0;
- result.right = width;
- result.bottom = height;
-
- return result;
- }
-
- Fixed getPlayRate(void)
- {
- Fixed result;
- if(mPlayRate == 0.0f)
- {
- // Default to the movie's preferred rate
- result = GetMoviePreferredRate(mMovieHandle);
- if(result == 0)
- {
- // Don't return a 0 play rate, ever.
- std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl;
- result = X2Fix(1.0f);
- }
- }
- else
- {
- result = X2Fix(mPlayRate);
- }
-
- return result;
- }
-
- void load( const std::string url )
- {
-
- if ( url.empty() )
- return;
-
- // Stop and unload any existing movie before starting another one.
- unload();
-
- setStatus(STATUS_LOADING);
-
- //In case std::string::c_str() makes a copy of the url data,
- //make sure there is memory to hold it before allocating memory for handle.
- //if fails, NewHandleClear(...) should return NULL.
- const char* url_string = url.c_str() ;
- Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) );
-
- if ( NULL == handle || noErr != MemError() || NULL == *handle )
- {
- setStatus(STATUS_ERROR);
- return;
- }
-
- BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) );
-
- OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType );
- DisposeHandle( handle );
- if ( noErr != err )
- {
- setStatus(STATUS_ERROR);
- return;
- };
-
- mNavigateURL = url;
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
- message.setValue("uri", mNavigateURL);
- sendMessage(message);
-
- // do pre-roll actions (typically fired for streaming movies but not always)
- PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
-
- Rect movie_rect = rectFromSize(mWidth, mHeight);
-
- // make a new movie controller
- mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie );
-
- // movie controller
- MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this );
-
- SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize );
-
- // function that gets called when a frame is drawn
- SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this );
-
- setStatus(STATUS_LOADED);
-
- sizeChanged();
- };
-
- bool unload()
- {
- // new movie and have to get title again
- mReceivedTitle = false;
-
- if ( mMovieHandle )
- {
- StopMovie( mMovieHandle );
- if ( mMovieController )
- {
- MCMovieChanged( mMovieController, mMovieHandle );
- };
- };
-
- if ( mMovieController )
- {
- MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this );
- DisposeMovieController( mMovieController );
- mMovieController = NULL;
- };
-
- if ( mMovieHandle )
- {
- SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this );
- DisposeMovie( mMovieHandle );
- mMovieHandle = NULL;
- };
-
- mGWorldHandle = NULL;
-
- setStatus(STATUS_NONE);
-
- return true;
- }
-
- bool navigateTo( const std::string url )
- {
- unload();
- load( url );
-
- return true;
- };
-
- bool sizeChanged()
- {
- if ( ! mMovieHandle )
- return false;
-
- // Check to see whether the movie's natural size has updated
- {
- int width, height;
- getMovieNaturalSize(&width, &height);
- if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight)))
- {
- mNaturalWidth = width;
- mNaturalHeight = height;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
- message.setValue("name", mTextureSegmentName);
- message.setValueS32("width", width);
- message.setValueS32("height", height);
- sendMessage(message);
- //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
- }
- }
-
-
- // sanitize destination size
- Rect dest_rect = rectFromSize(mWidth, mHeight);
-
- // media depth won't change
- int depth_bits = mDepth * 8;
- long rowbytes = mDepth * mTextureWidth;
-
- if(mPixels != NULL)
- {
- // We have pixels. Set up a GWorld pointing at the texture.
- OSErr result = QTNewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
- if ( noErr != result )
- {
- // TODO: unrecoverable?? throw exception? return something?
- return false;
- }
- }
- else
- {
- // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
- Rect tempRect = rectFromSize(1, 1);
- OSErr result = QTNewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
- if ( noErr != result )
- {
- // TODO: unrecoverable?? throw exception? return something?
- return false;
- }
- }
-
- SetMovieGWorld( mMovieHandle, mGWorldHandle, NULL );
-
- // Set up the movie display matrix
- {
- // scale movie to fit rect and invert vertically to match opengl image format
- MatrixRecord transform;
- SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix
- double scaleX = (double) mWidth / mNaturalWidth;
- double scaleY = -1.0 * (double) mHeight / mNaturalHeight;
- double centerX = mWidth / 2.0;
- double centerY = mHeight / 2.0;
- ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
- SetMovieMatrix( mMovieHandle, &transform );
- }
-
- // update movie controller
- if ( mMovieController )
- {
- MCSetControllerPort( mMovieController, mGWorldHandle );
- MCPositionController( mMovieController, &dest_rect, &dest_rect,
- mcTopLeftMovie | mcPositionDontInvalidate );
- MCMovieChanged( mMovieController, mMovieHandle );
- }
-
-
- // Emit event with size change so the calling app knows about it too
- // TODO:
- //LLMediaEvent event( this );
- //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event );
-
- return true;
- }
- static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
- {
- Boolean result = false;
-
- MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
- switch( action )
- {
- // handle window resizing
- case mcActionControllerSizeChanged:
- // Ensure that the movie draws correctly at the new size
- self->sizeChanged();
- break;
-
- // Block any movie controller actions that open URLs.
- case mcActionLinkToURL:
- case mcActionGetNextURL:
- case mcActionLinkToURLExtended:
- // Prevent the movie controller from handling the message
- result = true;
- break;
-
- default:
- break;
- };
-
- return result;
- };
-
- static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref )
- {
- MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
- // IMPORTANT: typically, a consumer who is observing this event will set a flag
- // when this event is fired then render later. Be aware that the media stream
- // can change during this period - dimensions, depth, format etc.
- //LLMediaEvent event( self );
-// self->updateQuickTime();
- // TODO ^^^
-
-
- if ( self->mWidth > 0 && self->mHeight > 0 )
- self->setDirty( 0, 0, self->mWidth, self->mHeight );
-
- return noErr;
- };
-
- static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
- {
- MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
- // TODO:
- //LLMediaEvent event( self );
- //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
-
- // Send a "navigate complete" event.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
- message.setValue("uri", self->mNavigateURL);
- message.setValueS32("result_code", 200);
- message.setValue("result_string", "OK");
- self->sendMessage(message);
- };
-
-
- void rewind()
- {
- GoToBeginningOfMovie( mMovieHandle );
- MCMovieChanged( mMovieController, mMovieHandle );
- };
-
- bool processState()
- {
- if ( mCommand == COMMAND_PLAY )
- {
- if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
- {
- long state = GetMovieLoadState( mMovieHandle );
-
- if ( state >= kMovieLoadStatePlaythroughOK )
- {
- // if the movie is at the end (generally because it reached it naturally)
- // and we play is requested, jump back to the start of the movie.
- // note: this is different from having loop flag set.
- if ( IsMovieDone( mMovieHandle ) )
- {
- Fixed rate = X2Fix( 0.0 );
- MCDoAction( mMovieController, mcActionPlay, (void*)rate );
- rewind();
- };
-
- MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
- MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
- setStatus(STATUS_PLAYING);
- mCommand = COMMAND_NONE;
- };
- };
- }
- else
- if ( mCommand == COMMAND_STOP )
- {
- if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
- {
- if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
- {
- Fixed rate = X2Fix( 0.0 );
- MCDoAction( mMovieController, mcActionPlay, (void*)rate );
- rewind();
-
- setStatus(STATUS_LOADED);
- mCommand = COMMAND_NONE;
- };
- };
- }
- else
- if ( mCommand == COMMAND_PAUSE )
- {
- if ( mStatus == STATUS_PLAYING )
- {
- if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
- {
- Fixed rate = X2Fix( 0.0 );
- MCDoAction( mMovieController, mcActionPlay, (void*)rate );
- setStatus(STATUS_PAUSED);
- mCommand = COMMAND_NONE;
- };
- };
- };
-
- return true;
- };
-
- void play(F64 rate)
- {
- mPlayRate = rate;
- mCommand = COMMAND_PLAY;
- };
-
- void stop()
- {
- mCommand = COMMAND_STOP;
- };
-
- void pause()
- {
- mCommand = COMMAND_PAUSE;
- };
-
- void getMovieNaturalSize(int *movie_width, int *movie_height)
- {
- Rect rect;
-
- GetMovieNaturalBoundsRect( mMovieHandle, &rect );
-
- int width = ( rect.right - rect.left );
- int height = ( rect.bottom - rect.top );
-
- // make sure width and height fall in valid range
- if ( width < mMinWidth )
- width = mMinWidth;
-
- if ( width > mMaxWidth )
- width = mMaxWidth;
-
- if ( height < mMinHeight )
- height = mMinHeight;
-
- if ( height > mMaxHeight )
- height = mMaxHeight;
-
- // return the new rect
- *movie_width = width;
- *movie_height = height;
- }
-
- void updateQuickTime(int milliseconds)
- {
- if ( ! mMovieHandle )
- return;
-
- if ( ! mMovieController )
- return;
-
- // this wasn't required in 1.xx viewer but we have to manually
- // work the Windows message pump now
- #if defined( LL_WINDOWS )
- MSG msg;
- while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
- {
- GetMessage( &msg, NULL, 0, 0 );
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- };
- #endif
-
- MCIdle( mMovieController );
-
- if ( ! mGWorldHandle )
- return;
-
- if ( mMediaSizeChanging )
- return;
-
- // update state machine
- processState();
-
- // see if title arrived and if so, update member variable with contents
- checkTitle();
-
- // QT call to see if we are at the end - can't do with controller
- if ( IsMovieDone( mMovieHandle ) )
- {
- // special code for looping - need to rewind at the end of the movie
- if ( mIsLooping )
- {
- // go back to start
- rewind();
-
- if ( mMovieController )
- {
- // kick off new play
- MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
-
- // set the volume
- MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
- };
- }
- else
- {
- if(mStatus == STATUS_PLAYING)
- {
- setStatus(STATUS_DONE);
- }
- }
- }
-
- };
-
- void seek( F64 time )
- {
- if ( mMovieController )
- {
- TimeRecord when;
- when.scale = GetMovieTimeScale( mMovieHandle );
- when.base = 0;
-
- // 'time' is in (floating point) seconds. The timebase time will be in 'units', where
- // there are 'scale' units per second.
- SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) );
-
- when.value.hi = ( SInt32 )( raw_time >> 32 );
- when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) );
-
- MCDoAction( mMovieController, mcActionGoToTime, &when );
- };
- };
-
- F64 getLoadedDuration()
- {
- TimeValue duration;
- if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr)
- {
- // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie.
- duration = GetMovieDuration( mMovieHandle );
- }
- TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
- return (F64)duration / (F64)scale;
- };
-
- F64 getDuration()
- {
- TimeValue duration = GetMovieDuration( mMovieHandle );
- TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
- return (F64)duration / (F64)scale;
- };
-
- F64 getCurrentTime()
- {
- TimeValue curr_time = GetMovieTime( mMovieHandle, 0 );
- TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
- return (F64)curr_time / (F64)scale;
- };
-
- void setVolume( F64 volume )
- {
- mCurVolume = (short)(volume * ( double ) 0x100 );
-
- if ( mMovieController )
- {
- MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
- };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void update(int milliseconds = 0)
- {
- updateQuickTime(milliseconds);
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseDown( int x, int y )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseUp( int x, int y )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseMove( int x, int y )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void keyPress( unsigned char key )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- // Grab movie title into mMovieTitle - should be called repeatedly
- // until it returns true since movie title takes a while to become
- // available.
- const bool getMovieTitle()
- {
- // grab meta data from movie
- QTMetaDataRef media_data_ref;
- OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref );
- if ( noErr != result )
- return false;
-
- // look up "Display Name" in meta data
- OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
- QTMetaDataItem item = kQTMetaDataItemUninitialized;
- result = (OSErr)QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,
- 0, kQTMetaDataKeyFormatCommon,
- (const UInt8 *)&meta_data_key,
- sizeof( meta_data_key ), &item );
- if ( noErr != result )
- return false;
-
- // find the size of the title
- ByteCount size;
- result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
- if ( noErr != result || size <= 0 /*|| size > 1024 FIXME: arbitrary limit */ )
- return false;
-
- // allocate some space and grab it
- UInt8* item_data = new UInt8[ size + 1 ];
- memset( item_data, 0, ( size + 1 ) * sizeof( UInt8 ) );
- result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
- if ( noErr != result )
- {
- delete [] item_data;
- return false;
- };
-
- // save it
- if ( strlen( (char*)item_data ) )
- mMovieTitle = std::string( (char* )item_data );
- else
- mMovieTitle = "";
-
- // clean up
- delete [] item_data;
-
- return true;
- };
-
- // called regularly to see if title changed
- void checkTitle()
- {
- // we did already receive title so keep checking
- if ( ! mReceivedTitle )
- {
- // grab title from movie meta data
- if ( getMovieTitle() )
- {
- // pass back to host application
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
- message.setValue("name", mMovieTitle );
- sendMessage( message );
-
- // stop looking once we find a title for this movie.
- // TODO: this may to be reset if movie title changes
- // during playback but this is okay for now
- mReceivedTitle = true;
- };
- };
- };
-};
-
-MediaPluginQuickTime::MediaPluginQuickTime(
- LLPluginInstance::sendMessageFunction host_send_func,
- void *host_user_data ) :
- MediaPluginBase(host_send_func, host_user_data),
- mMinWidth( 0 ),
- mMaxWidth( 2048 ),
- mMinHeight( 0 ),
- mMaxHeight( 2048 )
-{
-// std::cerr << "MediaPluginQuickTime constructor" << std::endl;
-
- mNaturalWidth = -1;
- mNaturalHeight = -1;
- mMovieHandle = 0;
- mGWorldHandle = 0;
- mMovieController = 0;
- mCurVolume = 0x99;
- mMediaSizeChanging = false;
- mIsLooping = false;
- mMovieTitle = std::string();
- mReceivedTitle = false;
- mCommand = COMMAND_NONE;
- mPlayRate = 0.0f;
- mStatus = STATUS_NONE;
-}
-
-MediaPluginQuickTime::~MediaPluginQuickTime()
-{
-// std::cerr << "MediaPluginQuickTime destructor" << std::endl;
-
- ExitMovies();
-
-#ifdef LL_WINDOWS
- TerminateQTML();
-// std::cerr << "QuickTime closing down" << std::endl;
-#endif
-}
-
-
-void MediaPluginQuickTime::receiveMessage(const char *message_string)
-{
-// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
- LLPluginMessage message_in;
-
- if(message_in.parse(message_string) >= 0)
- {
- std::string message_class = message_in.getClass();
- std::string message_name = message_in.getName();
- if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
- {
- if(message_name == "init")
- {
- LLPluginMessage message("base", "init_response");
- LLSD versions = LLSD::emptyMap();
- versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
- versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
- // Normally a plugin would only specify one of these two subclasses, but this is a demo...
- versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
- message.setValueLLSD("versions", versions);
-
- #ifdef LL_WINDOWS
-
- // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime
- // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html
- // The solution presented there appears to work.
- QTLoadLibrary("qtcf.dll");
-
- // main initialization for QuickTime - only required on Windows
- OSErr result = InitializeQTML( 0L );
- if ( result != noErr )
- {
- //TODO: If no QT on Windows, this fails - respond accordingly.
- }
- else
- {
- //std::cerr << "QuickTime initialized" << std::endl;
- };
- #endif
-
- // required for both Windows and Mac
- EnterMovies();
-
- std::string plugin_version = "QuickTime media plugin, QuickTime version ";
-
- long version = 0;
- Gestalt( gestaltQuickTimeVersion, &version );
- std::ostringstream codec( "" );
- codec << std::hex << version << std::dec;
- plugin_version += codec.str();
- message.setValue("plugin_version", plugin_version);
- sendMessage(message);
- }
- else if(message_name == "idle")
- {
- // no response is necessary here.
- F64 time = message_in.getValueReal("time");
-
- // Convert time to milliseconds for update()
- update((int)(time * 1000.0f));
- }
- else if(message_name == "cleanup")
- {
- // TODO: clean up here
- LLPluginMessage message("base", "goodbye");
- sendMessage(message);
- }
- else if(message_name == "shm_added")
- {
- SharedSegmentInfo info;
- info.mAddress = message_in.getValuePointer("address");
- info.mSize = (size_t)message_in.getValueS32("size");
- std::string name = message_in.getValue("name");
-// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name
-// << ", size: " << info.mSize
-// << ", address: " << info.mAddress
-// << std::endl;
-
- mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
-
- }
- else if(message_name == "shm_remove")
- {
- std::string name = message_in.getValue("name");
-
-// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl;
-
- SharedSegmentMap::iterator iter = mSharedSegments.find(name);
- if(iter != mSharedSegments.end())
- {
- if(mPixels == iter->second.mAddress)
- {
- // This is the currently active pixel buffer. Make sure we stop drawing to it.
- mPixels = NULL;
- mTextureSegmentName.clear();
-
- // Make sure the movie GWorld is no longer pointed at the shared segment.
- sizeChanged();
- }
- mSharedSegments.erase(iter);
- }
- else
- {
-// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl;
- }
-
- // Send the response so it can be cleaned up.
- LLPluginMessage message("base", "shm_remove_response");
- message.setValue("name", name);
- sendMessage(message);
- }
- else
- {
-// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- if(message_name == "init")
- {
- // This is the media init message -- all necessary data for initialization should have been received.
-
- // Plugin gets to decide the texture parameters to use.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
- #if defined(LL_WINDOWS)
- // Values for Windows
- mDepth = 3;
- message.setValueU32("format", GL_RGB);
- message.setValueU32("type", GL_UNSIGNED_BYTE);
-
- // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
- // Padding to a multiple of 3*32 guarantees it'll divide out properly.
- message.setValueU32("padding", 32 * 3);
- #else
- // Values for Mac
- mDepth = 4;
- message.setValueU32("format", GL_BGRA_EXT);
- #ifdef __BIG_ENDIAN__
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
- #else
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
- #endif
-
- // Pad texture width to a multiple of 32 bytes, to line up with cache lines.
- message.setValueU32("padding", 32);
- #endif
- message.setValueS32("depth", mDepth);
- message.setValueU32("internalformat", GL_RGB);
- message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
- message.setValueBoolean("allow_downsample", true);
- sendMessage(message);
- }
- else if(message_name == "size_change")
- {
- std::string name = message_in.getValue("name");
- S32 width = message_in.getValueS32("width");
- S32 height = message_in.getValueS32("height");
- S32 texture_width = message_in.getValueS32("texture_width");
- S32 texture_height = message_in.getValueS32("texture_height");
-
- //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
- message.setValue("name", name);
- message.setValueS32("width", width);
- message.setValueS32("height", height);
- message.setValueS32("texture_width", texture_width);
- message.setValueS32("texture_height", texture_height);
- sendMessage(message);
-
- if(!name.empty())
- {
- // Find the shared memory region with this name
- SharedSegmentMap::iterator iter = mSharedSegments.find(name);
- if(iter != mSharedSegments.end())
- {
-// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl;
-// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl;
-
- mPixels = (unsigned char*)iter->second.mAddress;
- mTextureSegmentName = name;
- mWidth = width;
- mHeight = height;
-
- mTextureWidth = texture_width;
- mTextureHeight = texture_height;
-
- mMediaSizeChanging = false;
-
- sizeChanged();
-
- update();
- };
- };
- }
- else if(message_name == "load_uri")
- {
- std::string uri = message_in.getValue("uri");
- load( uri );
- sendStatus();
- }
- else if(message_name == "mouse_event")
- {
- std::string event = message_in.getValue("event");
- S32 x = message_in.getValueS32("x");
- S32 y = message_in.getValueS32("y");
-
- if(event == "down")
- {
- mouseDown(x, y);
- }
- else if(event == "up")
- {
- mouseUp(x, y);
- }
- else if(event == "move")
- {
- mouseMove(x, y);
- };
- };
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- if(message_name == "stop")
- {
- stop();
- }
- else if(message_name == "start")
- {
- F64 rate = 0.0;
- if(message_in.hasValue("rate"))
- {
- rate = message_in.getValueReal("rate");
- }
- play(rate);
- }
- else if(message_name == "pause")
- {
- pause();
- }
- else if(message_name == "seek")
- {
- F64 time = message_in.getValueReal("time");
- seek(time);
- }
- else if(message_name == "set_loop")
- {
- bool loop = message_in.getValueBoolean("loop");
- mIsLooping = loop;
- }
- else if(message_name == "set_volume")
- {
- F64 volume = message_in.getValueReal("volume");
- setVolume(volume);
- }
- }
- else
- {
-// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl;
- };
- };
-}
-
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
- MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data);
- *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage;
- *plugin_user_data = (void*)self;
-
- return 0;
-}
-
-#else // LL_QUICKTIME_ENABLED
-
-// Stubbed-out class with constructor/destructor (necessary or windows linker
-// will just think its dead code and optimize it all out)
-class MediaPluginQuickTime : public MediaPluginBase
-{
-public:
- MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
- ~MediaPluginQuickTime();
- /* virtual */ void receiveMessage(const char *message_string);
-};
-
-MediaPluginQuickTime::MediaPluginQuickTime(
- LLPluginInstance::sendMessageFunction host_send_func,
- void *host_user_data ) :
- MediaPluginBase(host_send_func, host_user_data)
-{
- // no-op
-}
-
-MediaPluginQuickTime::~MediaPluginQuickTime()
-{
- // no-op
-}
-
-void MediaPluginQuickTime::receiveMessage(const char *message_string)
-{
- // no-op
-}
-
-// We're building without quicktime enabled. Just refuse to initialize.
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
- return -1;
-}
-
-#endif // LL_QUICKTIME_ENABLED
diff --git a/indra/media_plugins/winmmshim/forwarding_api.cpp b/indra/media_plugins/winmmshim/forwarding_api.cpp
index 33f0675028..c558062bd9 100644
--- a/indra/media_plugins/winmmshim/forwarding_api.cpp
+++ b/indra/media_plugins/winmmshim/forwarding_api.cpp
@@ -429,7 +429,7 @@ extern "C" {
return DefDriverProc_orig( dwDriverIdentifier, hdrvr, uMsg, lParam1, lParam2);
}
- BOOL WINAPI DriverCallback( DWORD dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
+ BOOL WINAPI DriverCallback( DWORD_PTR dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
ll_winmm_shim_initialize();
//OutputDebugString(L"DriverCallback\n");
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index dce0ea73cd..ac5e12c392 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -13,7 +13,6 @@ include(DragDrop)
include(EXPAT)
include(FMODEX)
include(GLOD)
-include(GooglePerfTools)
include(Hunspell)
include(JsonCpp)
include(LLAppearance)
@@ -263,6 +262,7 @@ set(viewer_SOURCE_FILES
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
llfloaternotificationstabbed.cpp
+ llfloateroutfitsnapshot.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloaterpathfindingcharacters.cpp
@@ -403,6 +403,7 @@ set(viewer_SOURCE_FILES
llnotificationscripthandler.cpp
llnotificationstorage.cpp
llnotificationtiphandler.cpp
+ lloutfitgallery.cpp
lloutfitslist.cpp
lloutfitobserver.cpp
lloutputmonitorctrl.cpp
@@ -879,6 +880,7 @@ set(viewer_HEADER_FILES
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloaternotificationstabbed.h
+ llfloateroutfitsnapshot.h
llfloaterobjectweights.h
llfloateropenobject.h
llfloaterpathfindingcharacters.h
@@ -1009,6 +1011,7 @@ set(viewer_HEADER_FILES
llnotificationlistview.h
llnotificationmanager.h
llnotificationstorage.h
+ lloutfitgallery.h
lloutfitslist.h
lloutfitobserver.h
lloutputmonitorctrl.h
@@ -1140,6 +1143,7 @@ set(viewer_HEADER_FILES
llsky.h
llslurl.h
llsnapshotlivepreview.h
+ llsnapshotmodel.h
llspatialpartition.h
llspeakers.h
llspeakingindicatormanager.h
@@ -1675,7 +1679,7 @@ if (WINDOWS)
set_target_properties(${VIEWER_BINARY_NAME}
PROPERTIES
# *TODO -reenable this once we get server usage sorted out
- LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS} /LARGEADDRESSAWARE"
+ LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO /LARGEADDRESSAWARE"
LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF /LARGEADDRESSAWARE"
)
@@ -1695,20 +1699,8 @@ if (WINDOWS)
# In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py
# and have the build deps get tracked *please* tell me about it.
- if(USE_TCMALLOC)
- # Configure a var for tcmalloc location, if used.
- # Note the need to specify multiple names explicitly.
- set(GOOGLE_PERF_TOOLS_SOURCE
- ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll
- ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll
- ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll
- )
- endif(USE_TCMALLOC)
-
-
set(COPY_INPUT_DEPENDENCIES
# The following commented dependencies are determined at variably at build time. Can't do this here.
- #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll
${CMAKE_SOURCE_DIR}/../etc/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll
@@ -1750,6 +1742,7 @@ if (WINDOWS)
SLPlugin
media_plugin_quicktime
media_plugin_cef
+ media_plugin_libvlc
winmm_shim
windows-crash-logger
)
@@ -1949,7 +1942,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLLOGIN_LIBRARIES}
${LLPHYSICS_LIBRARIES}
${LLPHYSICSEXTENSIONS_LIBRARIES}
- ${TCMALLOC_LIBRARIES}
${LLAPPEARANCE_LIBRARIES}
)
@@ -1965,6 +1957,7 @@ if (LINUX)
linux-crash-logger
SLPlugin
media_plugin_gstreamer010
+ media_plugin_libvlc
llcommon
)
@@ -2072,7 +2065,7 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger)
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
if (ENABLE_SIGNING)
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index a2cec7aff4..de197cc337 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-4.0.8
+4.1.3
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 6ccf89eabe..e12b8cfecd 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -137,6 +137,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>AdvanceOutfitSnapshot</key>
+ <map>
+ <key>Comment</key>
+ <string>Display advanced parameter settings in outfit snaphot interface</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>AgentPause</key>
<map>
<key>Comment</key>
@@ -4504,28 +4515,6 @@
<key>Value</key>
<string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
</map>
- <key>WebProfileURL</key>
- <map>
- <key>Comment</key>
- <string>URL for Web Profiles</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>https://my.secondlife.com/[AGENT_NAME]</string>
- </map>
- <key>WebProfileNonProductionURL</key>
- <map>
- <key>Comment</key>
- <string>URL for Web Profiles on Non-Production grids</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>https://my-demo.secondlife.com/[AGENT_NAME]</string>
- </map>
<key>HighResSnapshot</key>
<map>
<key>Comment</key>
@@ -4870,7 +4859,7 @@
<key>InventoryTrashMaxCapacity</key>
<map>
<key>Comment</key>
- <string>Maximum capacity of the Trash folder. User will ve offered to clean it up when exceeded.</string>
+ <string>Maximum capacity of the Trash folder. User will be offered to clean it up when exceeded.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6343,17 +6332,6 @@
<key>Value</key>
<integer>512</integer>
</map>
- <key>MemProfiling</key>
- <map>
- <key>Comment</key>
- <string>You want to use tcmalloc's memory profiling options.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>MenuAccessKeyTime</key>
<map>
<key>Comment</key>
@@ -7940,6 +7918,17 @@
<key>Value</key>
<integer>100000</integer>
</map>
+ <key>PrimTextMaxDrawDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum draw distance beyond which PRIM_TEXT won't be rendered</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>64.0</real>
+ </map>
<key>ProbeHardwareOnStartup</key>
<map>
<key>Comment</key>
@@ -10024,28 +10013,28 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>RenderUseFarClip</key>
- <map>
- <key>Comment</key>
- <string>If false, frustum culling will ignore far clip plane.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>RenderUseImpostors</key>
- <map>
- <key>Comment</key>
+ <key>RenderUseFarClip</key>
+ <map>
+ <key>Comment</key>
+ <string>If false, frustum culling will ignore far clip plane.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>RenderUseImpostors</key>
+ <map>
+ <key>Comment</key>
<string>OBSOLETE and UNUSED. See RenderAvatarMaxNonImpostors and RenderAvatarMaxComplexity.</string>
- <key>Persist</key>
+ <key>Persist</key>
<integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>RenderAutoMuteByteLimit</key>
<map>
<key>Comment</key>
@@ -10092,6 +10081,17 @@
<key>Value</key>
<integer>10</integer>
</map>
+ <key>ComplexityChangesPopUpDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Delay before viewer will show avatar complexity notice again</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>300</integer>
+ </map>
<key>RenderAvatarMaxComplexity</key>
<map>
<key>Comment</key>
@@ -10104,6 +10104,50 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderHUDObjectsWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>Viewer will warn user about HUD containing to many objects if objects count is above this value</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1000</integer>
+ </map>
+ <key>RenderHUDTexturesWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>Viewer will warn user about HUD containing to many textures if texture count is above this value</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>200</integer>
+ </map>
+ <key>RenderHUDOversizedTexturesWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>How many textures with size 1024 * 1024 or bigger HUD can contain before notifying user</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>6</integer>
+ </map>
+ <key>RenderHUDTexturesMemoryWarning</key>
+ <map>
+ <key>Comment</key>
+ <string>Viewer will warn user about HUD textures using memory above this value (in bytes)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>32000000</integer>
+ </map>
<key>RenderAutoMuteSurfaceAreaLimit</key>
<map>
<key>Comment</key>
@@ -12792,6 +12836,17 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>LastSystemUIScaleFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Size of system UI during last run. On Windows 100% (96 DPI) system setting is 1.0 UI size</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
<key>UIScrollbarSize</key>
<map>
<key>Comment</key>
@@ -13287,6 +13342,17 @@
<key>Value</key>
<string>1</string>
</map>
+ <key>UpdaterShowReleaseNotes</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables displaying of the Release notes in a web floater after update.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>UploadBakedTexOld</key>
<map>
<key>Comment</key>
@@ -14625,6 +14691,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>OutfitGallerySortByName</key>
+ <map>
+ <key>Comment</key>
+ <string>Always sort outfits by name in Outfit Gallery</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>OutfitOperationsTimeout</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index 92a5413adb..1dddf52961 100644
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -31,6 +31,8 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include "llexception.h"
+#include "stringize.h"
#include <algorithm>
#include <iterator>
@@ -154,13 +156,11 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
} while (false);
}
- catch (std::exception e)
- {
- LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
- }
catch (...)
{
- LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << url << "')"));
+ throw;
}
mPendingObjectQuota.clear();
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index d933537d2e..d8b0787852 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3895,11 +3895,17 @@ void LLAgent::handleTeleportFinished()
mIsMaturityRatingChangingDuringTeleport = false;
}
- // Init SLM Marketplace connection so we know which UI should be used for the user as a merchant
- // Note: Eventually, all merchant will be migrated to the new SLM system and there will be no reason to show the old UI at all.
- // Note: Some regions will not support the SLM cap for a while so we need to do that check for each teleport.
- // *TODO : Suppress that line from here once the whole grid migrated to SLM and move it to idle_startup() (llstartup.cpp)
- check_merchant_status();
+ if (mRegionp)
+ {
+ if (mRegionp->capabilitiesReceived())
+ {
+ onCapabilitiesReceivedAfterTeleport();
+ }
+ else
+ {
+ mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport));
+ }
+ }
}
void LLAgent::handleTeleportFailed()
@@ -3931,6 +3937,14 @@ void LLAgent::handleTeleportFailed()
}
}
+/*static*/
+void LLAgent::onCapabilitiesReceivedAfterTeleport()
+{
+
+ check_merchant_status();
+}
+
+
void LLAgent::teleportRequest(
const U64& region_handle,
const LLVector3& pos_local,
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 3a533c2cba..d82ff7a67f 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -676,6 +676,8 @@ private:
void handleTeleportFinished();
void handleTeleportFailed();
+ static void onCapabilitiesReceivedAfterTeleport();
+
//--------------------------------------------------------------------
// Teleport State
//--------------------------------------------------------------------
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index b76a66ab39..170e4063a1 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -62,23 +62,37 @@ using namespace LLAvatarAppearanceDefines;
///////////////////////////////////////////////////////////////////////////////
-// Callback to wear and start editing an item that has just been created.
-void wear_and_edit_cb(const LLUUID& inv_item)
+void set_default_permissions(LLViewerInventoryItem* item)
{
- if (inv_item.isNull()) return;
-
- LLViewerInventoryItem* item = gInventory.getItem(inv_item);
- if (!item) return;
-
- LLPermissions perm = item->getPermissions();
+ llassert(item);
+ LLPermissions perm = item->getPermissions();
+ if (perm.getMaskNextOwner() != LLFloaterPerms::getNextOwnerPerms("Wearables")
+ || perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Wearables")
+ || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Wearables"))
+ {
perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables"));
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables"));
+
item->setPermissions(perm);
item->updateServer(FALSE);
- gInventory.updateItem(item);
- gInventory.notifyObservers();
+ }
+}
+
+// Callback to wear and start editing an item that has just been created.
+void wear_and_edit_cb(const LLUUID& inv_item)
+{
+ if (inv_item.isNull()) return;
+
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item);
+ if (!item) return;
+
+ set_default_permissions(item);
+
+ // item was just created, update even if permissions did not changed
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
// Request editing the item after it gets worn.
gAgentWearables.requestEditingWearable(inv_item);
@@ -94,13 +108,8 @@ void wear_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
- LLPermissions perm = item->getPermissions();
- perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables"));
- perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables"));
- perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables"));
- item->setPermissions(perm);
+ set_default_permissions(item);
- item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@@ -253,6 +262,7 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i
{
LLAppearanceMgr::instance().addCOFItemLink(inv_item,
new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription);
+ editWearable(inv_item);
}
}
@@ -423,7 +433,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type,
// old_wearable may still be referred to by other inventory items. Revert
// unsaved changes so other inventory items aren't affected by the changes
// that were just saved.
- old_wearable->revertValues();
+ old_wearable->revertValuesWithoutUpdate();
}
void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index)
@@ -1364,6 +1374,30 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array
// LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL;
}
+std::vector<LLViewerObject*> LLAgentWearables::getTempAttachments()
+{
+ llvo_vec_t temp_attachs;
+ if (isAgentAvatarValid())
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end();)
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *objectp = (*attachment_iter);
+ if (objectp && objectp->isTempAttachment())
+ {
+ temp_attachs.push_back(objectp);
+ }
+ }
+ }
+ }
+ return temp_attachs;
+}
+
void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove)
{
if (!isAgentAvatarValid()) return;
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 1004482020..b27698fd8f 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -185,6 +185,8 @@ public:
static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
+ static llvo_vec_t getTempAttachments();
+
//--------------------------------------------------------------------
// Signals
//--------------------------------------------------------------------
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index 49291ea564..c1f898284a 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -30,6 +30,8 @@
#include "llappviewer.h"
#include "llviewercontrol.h"
+#include "llexception.h"
+#include "stringize.h"
#include <openssl/x509_vfy.h>
#include <openssl/ssl.h>
@@ -534,7 +536,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
// somewhat clumsy, as we may run into errors that do not map directly to curl
// error codes. Should be refactored with login refactoring, perhaps.
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
- result.setMessage(cert_exception.getMessage());
+ result.setMessage(cert_exception.what());
LLPointer<LLCertificate> cert = cert_exception.getCert();
cert->ref(); // adding an extra ref here
result.setErrorData(cert.get());
@@ -544,13 +546,14 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
catch (LLCertException &cert_exception)
{
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
- result.setMessage(cert_exception.getMessage());
+ result.setMessage(cert_exception.what());
LLPointer<LLCertificate> cert = cert_exception.getCert();
cert->ref(); // adding an extra ref here
result.setErrorData(cert.get());
}
catch (...)
{
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("('" << url << "')"));
// any other odd error, we just handle as a connect error.
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);
}
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 549df80fa1..be8877328d 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -48,16 +48,19 @@
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
frameTimer = nil;
-
+
[self languageUpdated];
-
+
if (initViewer())
{
- frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES];
+ // Set up recurring calls to oneFrame (repeating timer with timeout 0)
+ // until applicationShouldTerminate.
+ frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self
+ selector:@selector(oneFrame) userInfo:nil repeats:YES];
} else {
handleQuit();
}
-
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];
// [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
@@ -96,22 +99,29 @@
- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender
{
- if (!runMainLoop())
+ // run one frame to assess state
+ if (!pumpMainLoop())
{
+ // pumpMainLoop() returns true when done, false if it wants to be
+ // called again. Since it returned false, do not yet cancel
+ // frameTimer.
handleQuit();
return NSTerminateCancel;
} else {
+ // pumpMainLoop() returned true: it's done. Okay, done with frameTimer.
[frameTimer release];
cleanupViewer();
return NSTerminateNow;
}
}
-- (void) mainLoop
+- (void) oneFrame
{
- bool appExiting = runMainLoop();
+ bool appExiting = pumpMainLoop();
if (appExiting)
{
+ // Once pumpMainLoop() reports that we're done, cancel frameTimer:
+ // stop the repetitive calls.
[frameTimer release];
[[NSApplication sharedApplication] terminate:self];
}
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index a1d9786321..92e3cd0279 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
#include "llaccordionctrltab.h"
#include "llagent.h"
#include "llagentcamera.h"
@@ -1517,6 +1518,26 @@ void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit)
wearInventoryCategory(cat, false, false);
}
+// Remove existing photo link from outfit folder.
+void LLAppearanceMgr::removeOutfitPhoto(const LLUUID& outfit_id)
+{
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ gInventory.collectDescendents(
+ outfit_id,
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ gInventory.removeItem(outfit_item->getUUID());
+ }
+ }
+}
+
// Open outfit renaming dialog.
void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id)
{
@@ -1854,15 +1875,15 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
return false;
}
- // Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
+ // Check whether the outfit contains any wearables
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
- LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
+ LLFindWearables is_wearable;
gInventory.collectDescendentsIf(outfit_cat_id,
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
- is_worn);
+ is_wearable);
return items.size() > 0;
}
@@ -2945,6 +2966,16 @@ void LLAppearanceMgr::updateIsDirty()
gInventory.collectDescendentsIf(base_outfit, outfit_cats, outfit_items,
LLInventoryModel::EXCLUDE_TRASH, collector);
+ for (U32 i = 0; i < outfit_items.size(); ++i)
+ {
+ LLViewerInventoryItem* linked_item = outfit_items.at(i)->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ outfit_items.erase(outfit_items.begin() + i);
+ break;
+ }
+ }
+
if(outfit_items.size() != cof_items.size())
{
LL_DEBUGS("Avatar") << "item count different - base " << outfit_items.size() << " cof " << cof_items.size() << LL_ENDL;
@@ -3092,6 +3123,14 @@ void appearance_mgr_update_dirty_state()
{
if (LLAppearanceMgr::instanceExists())
{
+ LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
+ LLUUID image_id = app_mgr.getOutfitImage();
+ if(image_id.notNull())
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(app_mgr.getBaseOutfitUUID(), image_id, cb);
+ }
+
LLAppearanceMgr::getInstance()->updateIsDirty();
LLAppearanceMgr::getInstance()->setOutfitLocked(false);
gAgentWearables.notifyLoadingFinished();
@@ -3101,7 +3140,21 @@ void appearance_mgr_update_dirty_state()
void update_base_outfit_after_ordering()
{
LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance();
-
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ gInventory.collectDescendents(app_mgr.getBaseOutfitUUID(),
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ app_mgr.setOutfitImage(linked_item->getLinkedUUID());
+ }
+ }
+
LLPointer<LLInventoryCallback> dirty_state_updater =
new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state);
@@ -3424,13 +3477,13 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
}
else
{
- if (cofVersion < lastRcv)
+ if (cofVersion <= lastRcv)
{
LL_WARNS("Avatar") << "Have already received update for cof version " << lastRcv
<< " but requesting for " << cofVersion << LL_ENDL;
return;
}
- if (lastReq > cofVersion)
+ if (lastReq >= cofVersion)
{
LL_WARNS("Avatar") << "Request already in flight for cof version " << lastReq
<< " but requesting for " << cofVersion << LL_ENDL;
@@ -3450,7 +3503,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
LL_WARNS("Avatar") << "Forcing version failure on COF Baking" << LL_ENDL;
}
- LL_INFOS() << "Requesting bake for COF version " << cofVersion << LL_ENDL;
+ LL_INFOS("Avatar") << "Requesting bake for COF version " << cofVersion << LL_ENDL;
LLSD postData;
if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
@@ -3916,6 +3969,10 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val)
LL_DEBUGS("Avatar") << "setAttachmentInvLinkEnable => " << (int) val << LL_ENDL;
mAttachmentInvLinkEnabled = val;
}
+boost::signals2::connection LLAppearanceMgr::setAttachmentsChangedCallback(attachments_changed_callback_t cb)
+{
+ return mAttachmentsChangeSignal.connect(cb);
+}
void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)
{
@@ -3942,6 +3999,8 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
LLAttachmentsMgr::instance().onAttachmentArrived(item_id);
+
+ mAttachmentsChangeSignal();
}
void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
@@ -3962,6 +4021,8 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
{
//LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL;
}
+
+ mAttachmentsChangeSignal();
}
BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 7069da7352..f0d3f80f59 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -61,6 +61,7 @@ public:
void changeOutfit(bool proceed, const LLUUID& category, bool append);
void replaceCurrentOutfit(const LLUUID& new_outfit);
void renameOutfit(const LLUUID& outfit_id);
+ void removeOutfitPhoto(const LLUUID& outfit_id);
void takeOffOutfit(const LLUUID& cat_id);
void addCategoryToCurrentOutfit(const LLUUID& cat_id);
S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
@@ -184,6 +185,9 @@ public:
void wearBaseOutfit();
+ void setOutfitImage(const LLUUID& image_id) {mCOFImageID = image_id;}
+ LLUUID getOutfitImage() {return mCOFImageID;}
+
// Overrides the base outfit with the content from COF
// @return false if there is no base outfit
bool updateBaseOutfit();
@@ -225,6 +229,10 @@ public:
void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; }
std::string getAppearanceServiceURL() const;
+ typedef boost::function<void ()> attachments_changed_callback_t;
+ typedef boost::signals2::signal<void ()> attachments_changed_signal_t;
+ boost::signals2::connection setAttachmentsChangedCallback(attachments_changed_callback_t cb);
+
private:
@@ -268,6 +276,10 @@ private:
LLTimer mInFlightTimer;
static bool mActive;
+ attachments_changed_signal_t mAttachmentsChangeSignal;
+
+ LLUUID mCOFImageID;
+
std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
// Set of temp attachment UUIDs that should be removed
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6bc1f67e32..0813f2c359 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -122,15 +122,20 @@
#include "llleap.h"
#include "stringize.h"
#include "llcoros.h"
+#include "llexception.h"
#if !LL_LINUX
#include "cef/llceflib.h"
-#endif
+#if LL_WINDOWS
+#include "vlc/libvlc_version.h"
+#endif // LL_WINDOWS
+#endif // LL_LINUX
// Third party library includes
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
+#include <boost/throw_exception.hpp>
#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in processMarkerFiles
@@ -201,6 +206,7 @@
#include "llcommandlineparser.h"
#include "llfloatermemleak.h"
#include "llfloaterreg.h"
+#include "llfloateroutfitsnapshot.h"
#include "llfloatersnapshot.h"
#include "llfloaterinventory.h"
@@ -231,7 +237,6 @@
#include "llcoproceduremanager.h"
#include "llviewereventrecorder.h"
-
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
// this app, or another 'component' of the viewer. App globals should be
@@ -696,7 +701,8 @@ LLAppViewer::LLAppViewer()
mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
mFastTimerLogThread(NULL),
mUpdater(new LLUpdaterService()),
- mSettingsLocationList(NULL)
+ mSettingsLocationList(NULL),
+ mIsFirstRun(false)
{
if(NULL != sInstance)
{
@@ -769,9 +775,6 @@ bool LLAppViewer::init()
//
// Start of the application
//
-#ifdef LL_DARWIN
- mMainLoopInitialized = false;
-#endif
// initialize LLWearableType translation bridge.
// Memory will be cleaned up in ::cleanupClass()
@@ -925,7 +928,7 @@ bool LLAppViewer::init()
// Provide the text fields with callbacks for opening Urls
LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
- LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
+ LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false));
LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
@@ -1122,17 +1125,23 @@ bool LLAppViewer::init()
#if LL_WINDOWS
if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
{
+ std::string url;
if (gGLManager.mIsIntel)
{
- LLNotificationsUtil::add("IntelOldDriver");
+ url = LLTrans::getString("IntelDriverPage");
}
else if (gGLManager.mIsNVIDIA)
{
- LLNotificationsUtil::add("NVIDIAOldDriver");
+ url = LLTrans::getString("NvidiaDriverPage");
}
else if (gGLManager.mIsATI)
{
- LLNotificationsUtil::add("AMDOldDriver");
+ url = LLTrans::getString("AMDDriverPage");
+ }
+
+ if (!url.empty())
+ {
+ LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url));
}
}
#endif
@@ -1220,6 +1229,25 @@ bool LLAppViewer::init()
boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),
boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS));
+ showReleaseNotesIfRequired();
+
+ /*----------------------------------------------------------------------*/
+ // nat 2016-06-29 moved the following here from the former mainLoop().
+ mMainloopTimeout = new LLWatchdogTimeout();
+
+ // Create IO Pump to use for HTTP Requests.
+ gServicePump = new LLPumpIO(gAPRPoolp);
+
+ // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
+
+ LLVoiceChannel::initClass();
+ LLVoiceClient::getInstance()->init(gServicePump);
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
+
+ joystick = LLViewerJoystick::getInstance();
+ joystick->setNeedsReset(true);
+ /*----------------------------------------------------------------------*/
+
return true;
}
@@ -1294,299 +1322,266 @@ static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");
// externally visible timers
LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
-bool LLAppViewer::mainLoop()
+bool LLAppViewer::frame()
{
-#ifdef LL_DARWIN
- if (!mMainLoopInitialized)
-#endif
- {
- LL_INFOS() << "Entering main_loop" << LL_ENDL;
- mMainloopTimeout = new LLWatchdogTimeout();
-
- //-------------------------------------------
- // Run main loop until time to quit
- //-------------------------------------------
-
- // Create IO Pump to use for HTTP Requests.
- gServicePump = new LLPumpIO(gAPRPoolp);
-
- // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
-
- LLVoiceChannel::initClass();
- LLVoiceClient::getInstance()->init(gServicePump);
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
-
- joystick = LLViewerJoystick::getInstance();
- joystick->setNeedsReset(true);
-
-#ifdef LL_DARWIN
- // Ensure that this section of code never gets called again on OS X.
- mMainLoopInitialized = true;
-#endif
- }
- // As we do not (yet) send data on the mainloop LLEventPump that varies
- // with each frame, no need to instantiate a new LLSD event object each
- // time. Obviously, if that changes, just instantiate the LLSD at the
- // point of posting.
-
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
-
- LLSD newFrame;
-
+ LLSD newFrame;
+
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
-
+
//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
//LLPrivateMemoryPoolTester::destroy() ;
- // Handle messages
-#ifdef LL_DARWIN
- if (!LLApp::isExiting())
-#else
- while (!LLApp::isExiting())
-#endif
+ LL_RECORD_BLOCK_TIME(FTM_FRAME);
+ LLTrace::BlockTimer::processTimes();
+ LLTrace::get_frame_recording().nextPeriod();
+ LLTrace::BlockTimer::logStats();
+
+ LLTrace::get_thread_recorder()->pullFromChildren();
+
+ //clear call stack records
+ LL_CLEAR_CALLSTACKS();
+
+ //check memory availability information
+ checkMemory() ;
+
+ try
{
- LL_RECORD_BLOCK_TIME(FTM_FRAME);
- LLTrace::BlockTimer::processTimes();
- LLTrace::get_frame_recording().nextPeriod();
- LLTrace::BlockTimer::logStats();
+ pingMainloopTimeout("Main:MiscNativeWindowEvents");
+
+ if (gViewerWindow)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+ gViewerWindow->getWindow()->processMiscNativeEvents();
+ }
- LLTrace::get_thread_recorder()->pullFromChildren();
+ pingMainloopTimeout("Main:GatherInput");
- //clear call stack records
- LL_CLEAR_CALLSTACKS();
+ if (gViewerWindow)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+ if (!restoreErrorTrap())
+ {
+ LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
+ }
- //check memory availability information
- checkMemory() ;
+ gViewerWindow->getWindow()->gatherInput();
+ }
+
+#if 1 && !LL_RELEASE_FOR_DOWNLOAD
+ // once per second debug info
+ if (debugTime.getElapsedTimeF32() > 1.f)
+ {
+ debugTime.reset();
+ }
- try
+#endif
+ //memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
{
- pingMainloopTimeout("Main:MiscNativeWindowEvents");
+ mem_leak_instance->idle() ;
+ }
- if (gViewerWindow)
+ // canonical per-frame event
+ mainloop.post(newFrame);
+
+ if (!LLApp::isExiting())
+ {
+ pingMainloopTimeout("Main:JoystickKeyboard");
+
+ // Scan keyboard for movement keys. Command keys and typing
+ // are handled by windows callbacks. Don't do this until we're
+ // done initializing. JC
+ if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
+ && gViewerWindow->getActive()
+ && !gViewerWindow->getWindow()->getMinimized()
+ && LLStartUp::getStartupState() == STATE_STARTED
+ && (gHeadlessClient || !gViewerWindow->getShowProgress())
+ && !gFocusMgr.focusLocked())
{
- LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
- gViewerWindow->getWindow()->processMiscNativeEvents();
+ joystick->scanJoystick();
+ gKeyboard->scanKeyboard();
}
-
- pingMainloopTimeout("Main:GatherInput");
-
- if (gViewerWindow)
+
+ // Update state based on messages, user input, object idle.
{
- LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
- if (!restoreErrorTrap())
- {
- LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
- }
+ pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
+
+ LL_RECORD_BLOCK_TIME(FTM_IDLE);
+ idle();
- gViewerWindow->getWindow()->gatherInput();
+ resumeMainloopTimeout();
}
-#if 1 && !LL_RELEASE_FOR_DOWNLOAD
- // once per second debug info
- if (debugTime.getElapsedTimeF32() > 1.f)
+ if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
- debugTime.reset();
+ pauseMainloopTimeout();
+ saveFinalSnapshot();
+ disconnectViewer();
+ resumeMainloopTimeout();
}
-
-#endif
- //memory leaking simulation
- LLFloaterMemLeak* mem_leak_instance =
- LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if(mem_leak_instance)
- {
- mem_leak_instance->idle() ;
- }
- // canonical per-frame event
- mainloop.post(newFrame);
-
- if (!LLApp::isExiting())
+ // Render scene.
+ // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
+ if (!LLApp::isExiting() && !gHeadlessClient)
{
- pingMainloopTimeout("Main:JoystickKeyboard");
-
- // Scan keyboard for movement keys. Command keys and typing
- // are handled by windows callbacks. Don't do this until we're
- // done initializing. JC
- if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
- && gViewerWindow->getActive()
- && !gViewerWindow->getWindow()->getMinimized()
- && LLStartUp::getStartupState() == STATE_STARTED
- && (gHeadlessClient || !gViewerWindow->getShowProgress())
- && !gFocusMgr.focusLocked())
- {
- joystick->scanJoystick();
- gKeyboard->scanKeyboard();
- }
+ pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
+ display();
+ pingMainloopTimeout("Main:Snapshot");
+ LLFloaterSnapshot::update(); // take snapshots
+ LLFloaterOutfitSnapshot::update();
+ gGLActive = FALSE;
+ }
+ }
- // Update state based on messages, user input, object idle.
- {
- pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
-
- LL_RECORD_BLOCK_TIME(FTM_IDLE);
- idle();
+ pingMainloopTimeout("Main:Sleep");
- resumeMainloopTimeout();
- }
-
- if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
- {
- pauseMainloopTimeout();
- saveFinalSnapshot();
- disconnectViewer();
- resumeMainloopTimeout();
- }
+ pauseMainloopTimeout();
+
+ // Sleep and run background threads
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SLEEP);
+
+ // yield some time to the os based on command line option
+ if(mYieldTime >= 0)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_YIELD);
+ ms_sleep(mYieldTime);
+ }
- // Render scene.
- // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
- if (!LLApp::isExiting() && !gHeadlessClient)
+ // yield cooperatively when not running as foreground window
+ if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
+ || !gFocusMgr.getAppHasFocus())
+ {
+ // Sleep if we're not rendering, or the window is minimized.
+ S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
+ // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
+ // of equal priority on Windows
+ if (milliseconds_to_sleep > 0)
{
- pingMainloopTimeout("Main:Display");
- gGLActive = TRUE;
- display();
- pingMainloopTimeout("Main:Snapshot");
- LLFloaterSnapshot::update(); // take snapshots
- gGLActive = FALSE;
+ ms_sleep(milliseconds_to_sleep);
+ // also pause worker threads during this wait period
+ LLAppViewer::getTextureCache()->pause();
+ LLAppViewer::getImageDecodeThread()->pause();
}
}
-
- pingMainloopTimeout("Main:Sleep");
- pauseMainloopTimeout();
+ if (mRandomizeFramerate)
+ {
+ ms_sleep(rand() % 200);
+ }
- // Sleep and run background threads
+ if (mPeriodicSlowFrame
+ && (gFrameCount % 10 == 0))
{
- LL_RECORD_BLOCK_TIME(FTM_SLEEP);
-
- // yield some time to the os based on command line option
- if(mYieldTime >= 0)
- {
- LL_RECORD_BLOCK_TIME(FTM_YIELD);
- ms_sleep(mYieldTime);
- }
+ LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
+ ms_sleep(500);
+ }
+
+ const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second
+ idleTimer.reset();
+ S32 total_work_pending = 0;
+ S32 total_io_pending = 0;
+ while(1)
+ {
+ S32 work_pending = 0;
+ S32 io_pending = 0;
+ F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
+
+ work_pending += updateTextureThreads(max_time);
- // yield cooperatively when not running as foreground window
- if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
- || !gFocusMgr.getAppHasFocus())
{
- // Sleep if we're not rendering, or the window is minimized.
- S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
- // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
- // of equal priority on Windows
- if (milliseconds_to_sleep > 0)
- {
- ms_sleep(milliseconds_to_sleep);
- // also pause worker threads during this wait period
- LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
- }
+ LL_RECORD_BLOCK_TIME(FTM_VFS);
+ io_pending += LLVFSThread::updateClass(1);
}
-
- if (mRandomizeFramerate)
{
- ms_sleep(rand() % 200);
+ LL_RECORD_BLOCK_TIME(FTM_LFS);
+ io_pending += LLLFSThread::updateClass(1);
}
- if (mPeriodicSlowFrame
- && (gFrameCount % 10 == 0))
+ if (io_pending > 1000)
{
- LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
- ms_sleep(500);
+ ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
}
- const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second
- idleTimer.reset();
- S32 total_work_pending = 0;
- S32 total_io_pending = 0;
- while(1)
- {
- S32 work_pending = 0;
- S32 io_pending = 0;
- F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
-
- work_pending += updateTextureThreads(max_time);
-
- {
- LL_RECORD_BLOCK_TIME(FTM_VFS);
- io_pending += LLVFSThread::updateClass(1);
- }
- {
- LL_RECORD_BLOCK_TIME(FTM_LFS);
- io_pending += LLLFSThread::updateClass(1);
- }
-
- if (io_pending > 1000)
- {
- ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
- }
-
- total_work_pending += work_pending ;
- total_io_pending += io_pending ;
-
- if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
- {
- break;
- }
- }
- gMeshRepo.update() ;
+ total_work_pending += work_pending ;
+ total_io_pending += io_pending ;
- if(!total_work_pending) //pause texture fetching threads if nothing to process.
+ if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
{
- LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
- LLAppViewer::getTextureFetch()->pause();
+ break;
}
- if(!total_io_pending) //pause file threads if nothing to process.
- {
- LLVFSThread::sLocal->pause();
- LLLFSThread::sLocal->pause();
- }
+ }
+ gMeshRepo.update() ;
+
+ if(!total_work_pending) //pause texture fetching threads if nothing to process.
+ {
+ LLAppViewer::getTextureCache()->pause();
+ LLAppViewer::getImageDecodeThread()->pause();
+ LLAppViewer::getTextureFetch()->pause();
+ }
+ if(!total_io_pending) //pause file threads if nothing to process.
+ {
+ LLVFSThread::sLocal->pause();
+ LLLFSThread::sLocal->pause();
+ }
- //texture fetching debugger
- if(LLTextureFetchDebugger::isEnabled())
+ //texture fetching debugger
+ if(LLTextureFetchDebugger::isEnabled())
+ {
+ LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
+ if(tex_fetch_debugger_instance)
{
- LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
- LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
- if(tex_fetch_debugger_instance)
- {
- tex_fetch_debugger_instance->idle() ;
- }
+ tex_fetch_debugger_instance->idle() ;
}
+ }
- if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
- (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
- {
- gFrameStalls++;
- }
- frameTimer.reset();
+ if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
+ (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
+ {
+ gFrameStalls++;
+ }
+ frameTimer.reset();
- resumeMainloopTimeout();
-
- pingMainloopTimeout("Main:End");
- }
+ resumeMainloopTimeout();
+
+ pingMainloopTimeout("Main:End");
}
- catch(std::bad_alloc)
- {
- LLMemory::logMemoryInfo(TRUE) ;
+ }
+ catch (const LLContinueError&)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
+ }
+ catch(std::bad_alloc)
+ {
+ LLMemory::logMemoryInfo(TRUE) ;
- //stop memory leaking simulation
- LLFloaterMemLeak* mem_leak_instance =
- LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if(mem_leak_instance)
- {
- mem_leak_instance->stop() ;
- LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
- }
- else
- {
- //output possible call stacks to log file.
- LLError::LLCallStacks::print() ;
+ //stop memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
+ {
+ mem_leak_instance->stop() ;
+ LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
+ }
+ else
+ {
+ //output possible call stacks to log file.
+ LLError::LLCallStacks::print() ;
- LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
- }
+ LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION("");
+ }
if (LLApp::isExiting())
{
@@ -1600,7 +1595,7 @@ bool LLAppViewer::mainLoop()
catch(std::bad_alloc)
{
LL_WARNS() << "Bad memory allocation when saveFinalSnapshot() is called!" << LL_ENDL ;
-
+
//stop memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
@@ -1609,16 +1604,20 @@ bool LLAppViewer::mainLoop()
mem_leak_instance->stop() ;
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION("saveFinalSnapshot()");
+ }
}
-
+
delete gServicePump;
-
+
destroyMainloopTimeout();
-
+
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
- return LLApp::isExiting();
+ return ! LLApp::isRunning();
}
S32 LLAppViewer::updateTextureThreads(F32 max_time)
@@ -2483,7 +2482,10 @@ bool LLAppViewer::initConfiguration()
if (gSavedSettings.getBOOL("FirstRunThisInstall"))
{
- // Note that the "FirstRunThisInstall" settings is currently unused.
+ // Set firstrun flag to indicate that some further init actiona should be taken
+ // like determining screen DPI value and so on
+ mIsFirstRun = true;
+
gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
}
@@ -3140,7 +3142,8 @@ bool LLAppViewer::initWindow()
.min_width(gSavedSettings.getU32("MinWindowWidth"))
.min_height(gSavedSettings.getU32("MinWindowHeight"))
.fullscreen(gSavedSettings.getBOOL("FullScreen"))
- .ignore_pixel_depth(ignorePixelDepth);
+ .ignore_pixel_depth(ignorePixelDepth)
+ .first_run(mIsFirstRun);
gViewerWindow = new LLViewerWindow(window_params);
@@ -3277,6 +3280,7 @@ LLSD LLAppViewer::getViewerInfo() const
if (build_config != "Release")
{
info["BUILD_CONFIG"] = build_config;
+ info["ADDRESS_SIZE"] = ADDRESS_SIZE;
}
// return a URL to the release notes for this viewer, such as:
@@ -3342,6 +3346,19 @@ LLSD LLAppViewer::getViewerInfo() const
info["LLCEFLIB_VERSION"] = LLCEFLIB_VERSION;
#else
info["LLCEFLIB_VERSION"] = "Undefined";
+
+#endif
+
+#if LL_WINDOWS
+ std::ostringstream ver_codec;
+ ver_codec << LIBVLC_VERSION_MAJOR;
+ ver_codec << ".";
+ ver_codec << LIBVLC_VERSION_MINOR;
+ ver_codec << ".";
+ ver_codec << LIBVLC_VERSION_REVISION;
+ info["LIBVLC_VERSION"] = ver_codec.str();
+#else
+ info["LIBVLC_VERSION"] = "Undefined";
#endif
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
@@ -5546,8 +5563,7 @@ void LLAppViewer::forceErrorInfiniteLoop()
void LLAppViewer::forceErrorSoftwareException()
{
LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL;
- // *FIX: Any way to insure it won't be handled?
- throw;
+ LLTHROW(LLException("User selected Force Software Exception"));
}
void LLAppViewer::forceErrorDriverCrash()
@@ -5799,6 +5815,20 @@ void LLAppViewer::launchUpdater()
// LLAppViewer::instance()->forceQuit();
}
+/**
+* Check if user is running a new version of the viewer.
+* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting.
+*/
+void LLAppViewer::showReleaseNotesIfRequired()
+{
+ if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion
+ && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")
+ && !gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ {
+ LLSD info(getViewerInfo());
+ LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]);
+ }
+}
//virtual
void LLAppViewer::setMasterSystemAudioMute(bool mute)
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index b5e674bd7b..948d316009 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -79,7 +79,7 @@ public:
//
virtual bool init(); // Override to do application initialization
virtual bool cleanup(); // Override to do application cleanup
- virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
+ virtual bool frame(); // Override for application body logic
// Application control
void flushVFSIO(); // waits for vfs transfers to complete
@@ -254,6 +254,8 @@ private:
void sendLogoutRequest();
void disconnectViewer();
+
+ void showReleaseNotesIfRequired();
// *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.
@@ -283,7 +285,6 @@ private:
std::string mSerialNumber;
bool mPurgeCache;
bool mPurgeOnExit;
- bool mMainLoopInitialized;
LLViewerJoystick* joystick;
bool mSavedFinalSnapshot;
@@ -316,6 +317,7 @@ private:
// llcorehttp library init/shutdown helper
LLAppCoreHttp mAppCoreHttp;
+ bool mIsFirstRun;
//---------------------------------------------
//*NOTE: Mani - legacy updater stuff
// Still useable?
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index f5742b29cf..6f32aab851 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -95,10 +95,8 @@ int main( int argc, char **argv )
}
// Run the application main loop
- if(!LLApp::isQuitting())
- {
- viewer_app_ptr->mainLoop();
- }
+ while (! viewer_app_ptr->frame())
+ {}
if (!LLApp::isError())
{
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index ca219fda59..4fe1e31668 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -117,12 +117,17 @@ void handleQuit()
LLAppViewer::instance()->userQuit();
}
-bool runMainLoop()
+// This function is called pumpMainLoop() rather than runMainLoop() because
+// it passes control to the viewer's main-loop logic for a single frame. Like
+// LLAppViewer::frame(), it returns 'true' when it's done. Until then, it
+// expects to be called again by the timer in LLAppDelegate
+// (llappdelegate-objc.mm).
+bool pumpMainLoop()
{
bool ret = LLApp::isQuitting();
if (!ret && gViewerAppPtr != NULL)
{
- ret = gViewerAppPtr->mainLoop();
+ ret = gViewerAppPtr->frame();
} else {
ret = true;
}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 4786f83bfd..5107030476 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -231,6 +231,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
DWORD heap_enable_lfh_error[MAX_HEAPS];
S32 num_heaps = 0;
+ LLWindowWin32::setDPIAwareness();
+
#if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit
#elif 0
@@ -317,10 +319,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
}
// Run the application main loop
- if(!LLApp::isQuitting())
- {
- viewer_app_ptr->mainLoop();
- }
+ while (! viewer_app_ptr->frame())
+ {}
if (!LLApp::isError())
{
@@ -330,33 +330,33 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
// app cleanup if there was a problem.
//
#if WINDOWS_CRT_MEM_CHECKS
- LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
- if (!_CrtCheckMemory())
- {
- LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " No corruption detected." << LL_ENDL;
- }
+ LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
+ if (!_CrtCheckMemory())
+ {
+ LL_WARNS() << "_CrtCheckMemory() failed at prior to cleanup!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " No corruption detected." << LL_ENDL;
+ }
#endif
-
- gGLActive = TRUE;
- viewer_app_ptr->cleanup();
-
+ gGLActive = TRUE;
+
+ viewer_app_ptr->cleanup();
+
#if WINDOWS_CRT_MEM_CHECKS
- LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
- if (!_CrtCheckMemory())
- {
- LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " No corruption detected." << LL_ENDL;
- }
+ LL_INFOS() << "CRT Checking memory:" << LL_ENDL;
+ if (!_CrtCheckMemory())
+ {
+ LL_WARNS() << "_CrtCheckMemory() failed after cleanup!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " No corruption detected." << LL_ENDL;
+ }
#endif
-
+
}
delete viewer_app_ptr;
viewer_app_ptr = NULL;
@@ -569,7 +569,7 @@ bool LLAppViewerWin32::initHardwareTest()
// Do driver verification and initialization based on DirectX
// hardware polling and driver versions
//
- if (FALSE == gSavedSettings.getBOOL("NoHardwareProbe"))
+ if (TRUE == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && FALSE == gSavedSettings.getBOOL("NoHardwareProbe"))
{
// per DEV-11631 - disable hardware probing for everything
// but vram.
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index a6e745448a..7b8c630837 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -950,15 +950,22 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL
const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList();
if (inventory_selected.empty()) return false; // nothing selected
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
bool can_share = true;
std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin();
const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end();
for (; it != it_end; ++it)
{
- LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());
- // any category can be offered.
+ LLUUID cat_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();
+ LLViewerInventoryCategory* inv_cat = gInventory.getCategory(cat_id);
+ // any category can be offered if it's not in trash.
if (inv_cat)
{
+ if ((cat_id == trash_id) || gInventory.isObjectDescendentOf(cat_id, trash_id))
+ {
+ can_share = false;
+ break;
+ }
continue;
}
diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp
index 24934fdb73..94584a623b 100644
--- a/indra/newview/llavatarrendernotifier.cpp
+++ b/indra/newview/llavatarrendernotifier.cpp
@@ -38,6 +38,7 @@
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llnotificationtemplate.h"
+#include "llslurl.h"
#include "lltimer.h"
#include "llvoavatarself.h"
#include "llviewercontrol.h"
@@ -51,6 +52,11 @@ static const F32 RENDER_ALLOWED_CHANGE_PCT = 0.1;
// wait seconds before processing over limit updates after last complexity change
static const U32 OVER_LIMIT_UPDATE_DELAY = 70;
+static const U32 WARN_HUD_OBJECTS_LIMIT = 1000;
+static const U32 WARN_HUD_TEXTURES_LIMIT = 200;
+static const U32 WARN_HUD_OVERSIZED_TEXTURES_LIMIT = 6;
+static const U32 WARN_HUD_TEXTURE_MEMORY_LIMIT = 32000000; // in bytes
+
LLAvatarRenderNotifier::LLAvatarRenderNotifier() :
mAgentsCount(0),
@@ -264,3 +270,220 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity)
}
}
+// LLHUDRenderNotifier
+
+static const char* e_hud_messages[] =
+{
+ "hud_render_textures_warning",
+ "hud_render_cramped_warning",
+ "hud_render_heavy_textures_warning",
+ "hud_render_cost_warning",
+ "hud_render_memory_warning",
+};
+
+LLHUDRenderNotifier::LLHUDRenderNotifier() :
+mReportedHUDWarning(WARN_NONE)
+{
+}
+
+LLHUDRenderNotifier::~LLHUDRenderNotifier()
+{
+}
+
+void LLHUDRenderNotifier::updateNotificationHUD(hud_complexity_list_t complexity)
+{
+ if (!isAgentAvatarValid() || !gAgentWearables.areWearablesLoaded())
+ {
+ // data not ready.
+ return;
+ }
+
+ // TODO:
+ // Find a way to show message with list of issues, but without making it too large
+ // and intrusive.
+
+ LLHUDComplexity new_total_complexity;
+ LLHUDComplexity report_complexity;
+
+ hud_complexity_list_t::iterator iter = complexity.begin();
+ hud_complexity_list_t::iterator end = complexity.end();
+ EWarnLevel warning_level = WARN_NONE;
+ for (; iter != end; ++iter)
+ {
+ LLHUDComplexity object_complexity = *iter;
+ EWarnLevel object_level = getWarningType(object_complexity, report_complexity);
+ if (object_level >= 0)
+ {
+ warning_level = object_level;
+ report_complexity = object_complexity;
+ }
+ new_total_complexity.objectsCost += object_complexity.objectsCost;
+ new_total_complexity.objectsCount += object_complexity.objectsCount;
+ new_total_complexity.texturesCost += object_complexity.texturesCost;
+ new_total_complexity.texturesCount += object_complexity.texturesCount;
+ new_total_complexity.largeTexturesCount += object_complexity.largeTexturesCount;
+ new_total_complexity.texturesMemoryTotal += object_complexity.texturesMemoryTotal;
+ }
+
+ if (mHUDPopUpDelayTimer.hasExpired() || isNotificationVisible())
+ {
+ if (warning_level >= 0)
+ {
+ // Display info about most complex HUD object
+ // make sure it shown only once unless object's complexity or object itself changed
+ if (mReportedHUDComplexity.objectId != report_complexity.objectId
+ || mReportedHUDWarning != warning_level)
+ {
+ displayHUDNotification(warning_level, report_complexity.objectId, report_complexity.objectName, report_complexity.jointName);
+ mReportedHUDComplexity = report_complexity;
+ mReportedHUDWarning = warning_level;
+ }
+ }
+ else
+ {
+ // Check if total complexity is above threshold and above previous warning
+ // Show warning with highest importance (5m delay between warnings by default)
+ if (!mReportedHUDComplexity.objectId.isNull())
+ {
+ mReportedHUDComplexity.reset();
+ mReportedHUDWarning = WARN_NONE;
+ }
+
+ warning_level = getWarningType(new_total_complexity, mReportedHUDComplexity);
+ if (warning_level >= 0 && mReportedHUDWarning != warning_level)
+ {
+ displayHUDNotification(warning_level);
+ }
+ mReportedHUDComplexity = new_total_complexity;
+ mReportedHUDWarning = warning_level;
+ }
+ }
+ else if (warning_level >= 0)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD individual warning postponed" << LL_ENDL;
+ }
+
+ if (mLatestHUDComplexity.objectsCost != new_total_complexity.objectsCost
+ || mLatestHUDComplexity.objectsCount != new_total_complexity.objectsCount
+ || mLatestHUDComplexity.texturesCost != new_total_complexity.texturesCost
+ || mLatestHUDComplexity.texturesCount != new_total_complexity.texturesCount
+ || mLatestHUDComplexity.largeTexturesCount != new_total_complexity.largeTexturesCount
+ || mLatestHUDComplexity.texturesMemoryTotal != new_total_complexity.texturesMemoryTotal)
+ {
+ LL_INFOS("HUDdetail") << "HUD textures count: " << new_total_complexity.texturesCount
+ << " HUD textures cost: " << new_total_complexity.texturesCost
+ << " Large textures: " << new_total_complexity.largeTexturesCount
+ << " HUD objects cost: " << new_total_complexity.objectsCost
+ << " HUD objects count: " << new_total_complexity.objectsCount << LL_ENDL;
+
+ mLatestHUDComplexity = new_total_complexity;
+ }
+}
+
+bool LLHUDRenderNotifier::isNotificationVisible()
+{
+ return mHUDNotificationPtr != NULL && mHUDNotificationPtr->isActive();
+}
+
+// private static
+LLHUDRenderNotifier::EWarnLevel LLHUDRenderNotifier::getWarningType(LLHUDComplexity object_complexity, LLHUDComplexity cmp_complexity)
+{
+ static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); // ties max HUD cost to avatar cost
+ static LLCachedControl<U32> max_objects_count(gSavedSettings, "RenderHUDObjectsWarning", WARN_HUD_OBJECTS_LIMIT);
+ static LLCachedControl<U32> max_textures_count(gSavedSettings, "RenderHUDTexturesWarning", WARN_HUD_TEXTURES_LIMIT);
+ static LLCachedControl<U32> max_oversized_count(gSavedSettings, "RenderHUDOversizedTexturesWarning", WARN_HUD_OVERSIZED_TEXTURES_LIMIT);
+ static LLCachedControl<U32> max_texture_memory(gSavedSettings, "RenderHUDTexturesMemoryWarning", WARN_HUD_TEXTURE_MEMORY_LIMIT);
+
+ if (cmp_complexity.texturesMemoryTotal < object_complexity.texturesMemoryTotal
+ && object_complexity.texturesMemoryTotal > (F64Bytes)max_texture_memory)
+ {
+ // Note: Memory might not be accurate since texture is still loading or discard level changes
+
+ LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " memory usage over limit, "
+ << " was " << cmp_complexity.texturesMemoryTotal
+ << " is " << object_complexity.texturesMemoryTotal << LL_ENDL;
+
+ return WARN_MEMORY;
+ }
+ else if ((cmp_complexity.objectsCost < object_complexity.objectsCost
+ || cmp_complexity.texturesCost < object_complexity.texturesCost)
+ && max_render_cost > 0
+ && object_complexity.objectsCost + object_complexity.texturesCost > max_render_cost)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " complexity over limit,"
+ << " HUD textures cost: " << object_complexity.texturesCost
+ << " HUD objects cost: " << object_complexity.objectsCost << LL_ENDL;
+
+ return WARN_COST;
+ }
+ else if (cmp_complexity.largeTexturesCount < object_complexity.largeTexturesCount
+ && object_complexity.largeTexturesCount > max_oversized_count)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains to many large textures: "
+ << object_complexity.largeTexturesCount << LL_ENDL;
+
+ return WARN_HEAVY;
+ }
+ else if (cmp_complexity.texturesCount < object_complexity.texturesCount
+ && object_complexity.texturesCount > max_textures_count)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains too many textures: "
+ << object_complexity.texturesCount << LL_ENDL;
+
+ return WARN_CRAMPED;
+ }
+ else if (cmp_complexity.objectsCount < object_complexity.objectsCount
+ && object_complexity.objectsCount > max_objects_count)
+ {
+ LL_DEBUGS("HUDdetail") << "HUD " << object_complexity.objectName << " contains too many objects: "
+ << object_complexity.objectsCount << LL_ENDL;
+
+ return WARN_TEXTURES;
+ }
+ return WARN_NONE;
+}
+
+void LLHUDRenderNotifier::displayHUDNotification(EWarnLevel warn_type, LLUUID obj_id, std::string obj_name, std::string joint_name)
+{
+ static LLCachedControl<U32> pop_up_delay(gSavedSettings, "ComplexityChangesPopUpDelay", 300);
+ static LLCachedControl<U32> expire_delay(gSavedSettings, "ShowMyComplexityChanges", 20);
+ LLDate expire_date(LLDate::now().secondsSinceEpoch() + expire_delay);
+
+ // Since we need working "ignoretext" there is no other way but to
+ // use single notification while constructing it from multiple pieces
+ LLSD reason_args;
+ if (obj_id.isNull())
+ {
+ reason_args["HUD_DETAILS"] = LLTrans::getString("hud_description_total");
+ }
+ else
+ {
+ if (obj_name.empty())
+ {
+ LL_WARNS("HUDdetail") << "Object name not assigned" << LL_ENDL;
+ }
+ if (joint_name.empty())
+ {
+ std::string verb = "select?name=" + LLURI::escape(obj_name);
+ reason_args["HUD_DETAILS"] = LLSLURL("inventory", obj_id, verb.c_str()).getSLURLString();
+ }
+ else
+ {
+ LLSD object_args;
+ std::string verb = "select?name=" + LLURI::escape(obj_name);
+ object_args["OBJ_NAME"] = LLSLURL("inventory", obj_id, verb.c_str()).getSLURLString();
+ object_args["JNT_NAME"] = LLTrans::getString(joint_name);
+ reason_args["HUD_DETAILS"] = LLTrans::getString("hud_name_with_joint", object_args);
+ }
+ }
+
+ LLSD msg_args;
+ msg_args["HUD_REASON"] = LLTrans::getString(e_hud_messages[warn_type], reason_args);
+
+ mHUDNotificationPtr = LLNotifications::instance().add(LLNotification::Params()
+ .name("HUDComplexityWarning")
+ .expiry(expire_date)
+ .substitutions(msg_args));
+ mHUDPopUpDelayTimer.resetWithExpiry(pop_up_delay);
+}
+
diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h
index 2a2704de28..a169baef40 100644
--- a/indra/newview/llavatarrendernotifier.h
+++ b/indra/newview/llavatarrendernotifier.h
@@ -33,6 +33,36 @@
class LLViewerRegion;
+struct LLHUDComplexity
+{
+ LLHUDComplexity()
+ {
+ reset();
+ }
+ void reset()
+ {
+ objectId = LLUUID::null;
+ objectName = "";
+ objectsCost = 0;
+ objectsCount = 0;
+ texturesCost = 0;
+ texturesCount = 0;
+ largeTexturesCount = 0;
+ texturesMemoryTotal = (F64Bytes)0;
+ }
+ LLUUID objectId;
+ std::string objectName;
+ std::string jointName;
+ U32 objectsCost;
+ U32 objectsCount;
+ U32 texturesCost;
+ U32 texturesCount;
+ U32 largeTexturesCount;
+ F64Bytes texturesMemoryTotal;
+};
+
+typedef std::list<LLHUDComplexity> hud_complexity_list_t;
+
// Class to notify user about drastic changes in agent's render weights or if other agents
// reported that user's agent is too 'heavy' for their settings
class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier>
@@ -81,4 +111,36 @@ private:
S32 mLastOutfitRezStatus;
};
+// Class to notify user about heavy set of HUD
+class LLHUDRenderNotifier : public LLSingleton<LLHUDRenderNotifier>
+{
+public:
+ LLHUDRenderNotifier();
+ ~LLHUDRenderNotifier();
+
+ void updateNotificationHUD(hud_complexity_list_t complexity);
+ bool isNotificationVisible();
+
+private:
+ enum EWarnLevel
+ {
+ WARN_NONE = -1,
+ WARN_TEXTURES = 0, // least important
+ WARN_CRAMPED,
+ WARN_HEAVY,
+ WARN_COST,
+ WARN_MEMORY, //most important
+ };
+
+ LLNotificationPtr mHUDNotificationPtr;
+
+ static EWarnLevel getWarningType(LLHUDComplexity object_complexity, LLHUDComplexity cmp_complexity);
+ void displayHUDNotification(EWarnLevel warn_type, LLUUID obj_id = LLUUID::null, std::string object_name = "", std::string joint_name = "");
+
+ LLHUDComplexity mReportedHUDComplexity;
+ EWarnLevel mReportedHUDWarning;
+ LLHUDComplexity mLatestHUDComplexity;
+ LLFrameTimer mHUDPopUpDelayTimer;
+};
+
#endif /* ! defined(LL_llavatarrendernotifier_H) */
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 00fa6dd979..54c6c985d6 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -311,7 +311,8 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel)
}
else if (mesg[0] == '/'
&& mesg[1]
- && LLStringOps::isDigit(mesg[1]))
+ && (LLStringOps::isDigit(mesg[1])
+ || (mesg[1] == '-' && mesg[2] && LLStringOps::isDigit(mesg[2]))))
{
// This a special "/20" speak on a channel
S32 pos = 0;
@@ -325,7 +326,7 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel)
channel_string.push_back(c);
pos++;
}
- while(c && pos < 64 && LLStringOps::isDigit(c));
+ while(c && pos < 64 && (LLStringOps::isDigit(c) || (pos == 1 && c == '-')));
// Move the pointer forward to the first non-whitespace char
// Check isspace before looping, so we can handle "/33foo"
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index 1819fc74ee..90a5483dc9 100644
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -26,6 +26,7 @@
#include "llviewerprecompiledheaders.h"
#include "llcommandlineparser.h"
+#include "llexception.h"
// *NOTE: The boost::lexical_cast generates
// the warning C4701(local used with out assignment) in VC7.1.
@@ -50,6 +51,7 @@
#include "llsdserialize.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
#include <string>
#include <set>
#include <iostream>
@@ -98,14 +100,14 @@ namespace
bool gPastLastOption = false;
}
-class LLCLPError : public std::logic_error {
+class LLCLPError : public LLException {
public:
- LLCLPError(const std::string& what) : std::logic_error(what) {}
+ LLCLPError(const std::string& what) : LLException(what) {}
};
-class LLCLPLastOption : public std::logic_error {
+class LLCLPLastOption : public LLException {
public:
- LLCLPLastOption(const std::string& what) : std::logic_error(what) {}
+ LLCLPLastOption(const std::string& what) : LLException(what) {}
};
class LLCLPValue : public po::value_semantic_codecvt_helper<char>
@@ -202,17 +204,17 @@ protected:
{
if(gPastLastOption)
{
- throw(LLCLPLastOption("Don't parse no more!"));
+ LLTHROW(LLCLPLastOption("Don't parse no more!"));
}
// Error checks. Needed?
if (!value_store.empty() && !is_composing())
{
- throw(LLCLPError("Non composing value with multiple occurences."));
+ LLTHROW(LLCLPError("Non composing value with multiple occurences."));
}
if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens())
{
- throw(LLCLPError("Illegal number of tokens specified."));
+ LLTHROW(LLCLPError("Illegal number of tokens specified."));
}
if(value_store.empty())
@@ -466,7 +468,7 @@ onevalue(const std::string& option,
{
// What does it mean when the user specifies a command-line switch
// that requires a value, but omits the value? Complain.
- throw LLCLPError(STRINGIZE("No value specified for --" << option << "!"));
+ LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));
}
else if (value.size() > 1)
{
@@ -484,9 +486,9 @@ void badvalue(const std::string& option,
// If the user passes an unusable value for a command-line switch, it
// seems like a really bad idea to just ignore it, even with a log
// warning.
- throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
- << "' for variable '" << varname << "' of type " << type
- << ": '" << value << "'"));
+ LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option
+ << "' for variable '" << varname << "' of type " << type
+ << ": '" << value << "'")));
}
template <typename T>
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 7721e67290..76e16f5a1f 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -67,7 +67,9 @@ namespace
const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue");
-
+ // ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged
+ // callback mechanism and the LLEventPump coroutine architecture allowing the
+ // coroutine to wait for the inventory event.
class ObjectInventoryFetcher: public LLVOInventoryListener
{
public:
@@ -144,7 +146,7 @@ public:
queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
}
- return LLSD().with("success", LLSD::Boolean(true));
+ return LLSDMap("success", LLSD::Boolean(true));
}
@@ -254,7 +256,6 @@ LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key)
setTitle(LLTrans::getString("CompileQueueTitle"));
setStartString(LLTrans::getString("CompileQueueStart"));
-// mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
}
LLFloaterCompileQueue::~LLFloaterCompileQueue()
@@ -267,7 +268,6 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content )
{
mExperienceIds.insert(it->asUUID());
}
-// nextObject();
}
BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
@@ -277,11 +277,6 @@ BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
// //Attempt to record this asset ID. If it can not be inserted into the set
// //then it has already been processed so return false.
-// bool LLFloaterCompileQueue::checkAssetId(const LLUUID &assetId)
-// {
-// std::pair<uuid_list_t::iterator, bool> result = mAssetIds.insert(assetId);
-// return result.second;
-// }
void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult)
{
@@ -331,8 +326,10 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren
queue->experienceIdsReceived(result["experience_ids"]);
+ // getDerived handle gets a handle that can be resolved to a parent class of the derived object.
LLHandle<LLFloaterScriptQueue> hFloater(queue->getDerivedHandle<LLFloaterScriptQueue>());
+ // note subtle difference here: getDerivedHandle in this case is for an LLFloaterCompileQueue
fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript,
queue->getDerivedHandle<LLFloaterCompileQueue>(), _1, _2, _3);
@@ -345,37 +342,35 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren
}
+/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
+/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
LLSD result;
- LLFloaterCompileQueue *that = hfloater.get();
- bool monocompile = that->mMono;
+ LLCheckedHandle<LLFloaterCompileQueue> floater(hfloater);
+ // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
+ // which is caught in objectScriptProcessingQueueCoro
+ bool monocompile = floater->mMono;
F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
- if (!that)
- return false;
// Initial test to see if we can (or should) attempt to compile the script.
LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory);
- {
- if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) ||
- !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
- {
- std::string buffer = "Skipping: " + item->getName() + "(Permissions)";
- that->addStringMessage(buffer);
- return true;
- }
+ if (!item)
+ {
+ LL_WARNS("SCRIPTQ") << "item retrieved is not an LLInventoryItem." << LL_ENDL;
+ return true;
+ }
-// if (!that->checkAssetId(item->getAssetUUID()))
-// {
-// std::string buffer = "Skipping: " + item->getName() + "(Repeat)";
-// that->addStringMessage(buffer);
-// return true;
-// }
+ if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) ||
+ !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+ {
+ std::string buffer = "Skipping: " + item->getName() + "(Permissions)";
+ floater->addStringMessage(buffer);
+ return true;
}
- that = NULL;
// Attempt to retrieve the experience
LLUUID experienceId;
@@ -384,37 +379,30 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1));
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
- LLSD().with("timeout", LLSD::Boolean(true)));
+ LLSDMap("timeout", LLSD::Boolean(true)));
- that = hfloater.get();
- if (!that)
- {
- return false;
- }
-
- if (result.has("timeout") && result["timeout"].asBoolean())
- {
+ if (result.has("timeout"))
+ { // A timeout filed in the result will always be true if present.
LLStringUtil::format_map_t args;
args["[OBJECT_NAME]"] = inventory->getName();
- std::string buffer = that->getString("Timeout", args);
- that->addStringMessage(buffer);
+ std::string buffer = floater->getString("Timeout", args);
+ floater->addStringMessage(buffer);
return true;
}
if (result.has(LLExperienceCache::EXPERIENCE_ID))
{
experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID();
- if (!that->hasExperience(experienceId))
+ if (!floater->hasExperience(experienceId))
{
- that->addProcessingMessage("CompileNoExperiencePerm", LLSD()
- .with("SCRIPT", inventory->getName())
- .with("EXPERIENCE", result[LLExperienceCache::NAME].asString()));
+ floater->addProcessingMessage("CompileNoExperiencePerm",
+ LLSDMap("SCRIPT", inventory->getName())
+ ("EXPERIENCE", result[LLExperienceCache::NAME].asString()));
return true;
}
}
}
- that = NULL;
{
HandleScriptUserData userData(pump.getName());
@@ -433,32 +421,23 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
&userData);
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
- LLSD().with("timeout", LLSD::Boolean(true)));
- }
-
- that = hfloater.get();
- if (!that)
- {
- return false;
+ LLSDMap("timeout", LLSD::Boolean(true)));
}
if (result.has("timeout"))
- {
- if (result.has("timeout") && result["timeout"].asBoolean())
- {
- LLStringUtil::format_map_t args;
- args["[OBJECT_NAME]"] = inventory->getName();
- std::string buffer = that->getString("Timeout", args);
- that->addStringMessage(buffer);
- return true;
- }
+ { // A timeout filed in the result will always be true if present.
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = floater->getString("Timeout", args);
+ floater->addStringMessage(buffer);
+ return true;
}
if (result.has("error"))
{
LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL;
std::string buffer = result["message"].asString() + " " + inventory->getName();
- that->addStringMessage(buffer);
+ floater->addStringMessage(buffer);
if (result.has("alert"))
{
@@ -470,12 +449,9 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
}
LLUUID assetId = result["asset_id"];
- that = NULL;
-
std::string url = object->getRegion()->getCapability("UpdateScriptTask");
-
{
LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(),
inventory->getUUID(),
@@ -490,24 +466,15 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
}
- result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSD().with("timeout", LLSD::Boolean(true)));
-
- that = hfloater.get();
- if (!that)
- {
- return false;
- }
+ result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSDMap("timeout", LLSD::Boolean(true)));
if (result.has("timeout"))
- {
- if (result.has("timeout") && result["timeout"].asBoolean())
- {
- LLStringUtil::format_map_t args;
- args["[OBJECT_NAME]"] = inventory->getName();
- std::string buffer = that->getString("Timeout", args);
- that->addStringMessage(buffer);
- return true;
- }
+ { // A timeout filed in the result will always be true if present.
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = floater->getString("Timeout", args);
+ floater->addStringMessage(buffer);
+ return true;
}
// Bytecode save completed
@@ -515,21 +482,21 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
{
std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded");
- that->addStringMessage(buffer);
+ floater->addStringMessage(buffer);
LL_INFOS() << buffer << LL_ENDL;
}
else
{
LLSD compile_errors = result["errors"];
std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:");
- that->addStringMessage(buffer);
+ floater->addStringMessage(buffer);
for (LLSD::array_const_iterator line = compile_errors.beginArray();
line < compile_errors.endArray(); line++)
{
std::string str = line->asString();
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
- that->addStringMessage(str);
+ floater->addStringMessage(str);
}
LL_INFOS() << result["errors"] << LL_ENDL;
}
@@ -576,16 +543,18 @@ LLFloaterResetQueue::~LLFloaterResetQueue()
{
}
-bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
+/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
+bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- LLFloaterScriptQueue *that = hfloater.get();
- if (that)
- {
- std::string buffer;
- buffer = that->getString("Resetting") + (": ") + inventory->getName();
- that->addStringMessage(buffer);
- }
+ LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
+ // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
+ // which is caught in objectScriptProcessingQueueCoro
+
+ std::string buffer;
+ buffer = floater->getString("Resetting") + (": ") + inventory->getName();
+ floater->addStringMessage(buffer);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ScriptReset);
@@ -602,6 +571,8 @@ bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hflo
bool LLFloaterResetQueue::startQueue()
{
+ // Bind the resetObjectScripts method into a QueueAction function and pass it
+ // into the object queue processing coroutine.
fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts,
getDerivedHandle<LLFloaterScriptQueue>(), _1, _2, _3);
@@ -629,16 +600,18 @@ LLFloaterRunQueue::~LLFloaterRunQueue()
{
}
-bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
+/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
+bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- LLFloaterScriptQueue *that = hfloater.get();
- if (that)
- {
- std::string buffer;
- buffer = that->getString("Running") + (": ") + inventory->getName();
- that->addStringMessage(buffer);
- }
+ LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
+ // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
+ // which is caught in objectScriptProcessingQueueCoro
+
+ std::string buffer;
+ buffer = floater->getString("Running") + (": ") + inventory->getName();
+ floater->addStringMessage(buffer);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_SetScriptRunning);
@@ -684,16 +657,18 @@ LLFloaterNotRunQueue::~LLFloaterNotRunQueue()
{
}
+/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro.
+/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception.
bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- LLFloaterScriptQueue *that = hfloater.get();
- if (that)
- {
- std::string buffer;
- buffer = that->getString("NotRunning") + (": ") + inventory->getName();
- that->addStringMessage(buffer);
- }
+ LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
+ // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
+ // which is caught in objectScriptProcessingQueueCoro
+
+ std::string buffer;
+ buffer = floater->getString("NotRunning") + (": ") + inventory->getName();
+ floater->addStringMessage(buffer);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_SetScriptRunning);
@@ -732,7 +707,7 @@ void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object,
mInventoryList.clear();
mInventoryList.assign(inventory->begin(), inventory->end());
- mPump.post(LLSD().with("changed", LLSD::Boolean(true)));
+ mPump.post(LLSDMap("changed", LLSD::Boolean(true)));
}
@@ -740,115 +715,97 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L
object_data_list_t objectList, fnQueueAction_t func)
{
LLCoros::set_consuming(true);
- LLFloaterScriptQueue * floater(NULL);
+ LLCheckedHandle<LLFloaterScriptQueue> floater(hfloater);
+ // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
+ // This is expected if the dialog closes.
LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true);
F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
-// floater = hfloater.get();
-// floater->addProcessingMessage("Starting",
-// LLSD()
-// .with("[START]", action)
-// .with("[COUNT]", LLSD::Integer(objectList.size())));
-// floater = NULL;
- for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj)
+ try
{
- bool firstForObject = true;
- LLUUID object_id = (*itObj).mObjectId;
- LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL;
-
- LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id);
- LLInventoryObject::object_list_t inventory;
- if (obj)
+ for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj)
{
- ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL));
+ bool firstForObject = true;
+ LLUUID object_id = (*itObj).mObjectId;
+ LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL;
- fetcher->fetchInventory();
-
- floater = hfloater.get();
- if (floater)
+ LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id);
+ LLInventoryObject::object_list_t inventory;
+ if (obj)
{
+ ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL));
+
+ fetcher->fetchInventory();
+
LLStringUtil::format_map_t args;
args["[OBJECT_NAME]"] = (*itObj).mObjectName;
floater->addStringMessage(floater->getString("LoadingObjInv", args));
- }
- LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
- LLSD().with("timeout", LLSD::Boolean(true)));
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
+ LLSDMap("timeout", LLSD::Boolean(true)));
- if (result.has("timeout") && result["timeout"].asBoolean())
- {
- LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() <<
- ". Skipping to next object." << LL_ENDL;
+ if (result.has("timeout"))
+ { // A timeout filed in the result will always be true if present.
+ LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() <<
+ ". Skipping to next object." << LL_ENDL;
- // floater could have been closed
- floater = hfloater.get();
- if (floater)
- {
LLStringUtil::format_map_t args;
args["[OBJECT_NAME]"] = (*itObj).mObjectName;
floater->addStringMessage(floater->getString("Timeout", args));
+
+ continue;
}
+ inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end());
+ }
+ else
+ {
+ LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id <<
+ ". Skipping to next." << LL_ENDL;
continue;
}
- inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end());
- }
- else
- {
- LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id <<
- ". Skipping to next." << LL_ENDL;
- continue;
- }
+ // TODO: Get the name of the object we are looking at here so that we can display it below.
+ //std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName();
+ LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL;
- // TODO: Get the name of the object we are looking at here so that we can display it below.
- //std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName();
- LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL;
-
- for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin();
- itInv != inventory.end(); ++itInv)
- {
- floater = hfloater.get();
- if (!floater)
+ for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin();
+ itInv != inventory.end(); ++itInv)
{
- LL_WARNS("SCRIPTQ") << "Script Queue floater closed! Canceling remaining ops" << LL_ENDL;
- break;
- }
+ floater.check();
- // note, we have a smart pointer to the obj above... but if we didn't we'd check that
- // it still exists here.
+ // note, we have a smart pointer to the obj above... but if we didn't we'd check that
+ // it still exists here.
- if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT))
- {
- LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL;
- if (firstForObject)
+ if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT))
{
- //floater->addStringMessage(objName + ":");
- firstForObject = false;
+ LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL;
+ if (firstForObject)
+ {
+ //floater->addStringMessage(objName + ":");
+ firstForObject = false;
+ }
+
+ if (!func(obj, (*itInv), maildrop))
+ {
+ continue;
+ }
}
- if (!func(obj, (*itInv), maildrop))
- {
- continue;
- }
+ // no other explicit suspension point in this loop. func(...) MIGHT suspend
+ // but offers no guarantee of doing so.
+ llcoro::suspend();
}
-
- llcoro::suspend();
- }
- // Just test to be sure the floater is still present before calling the func
- if (!hfloater.get())
- {
- LL_WARNS("SCRIPTQ") << "Script Queue floater dismissed." << LL_ENDL;
- break;
}
- }
-
- floater = hfloater.get();
- if (floater)
- {
floater->addStringMessage("Done");
floater->getChildView("close")->setEnabled(TRUE);
}
+ catch (LLCheckedHandleBase::Stale &)
+ {
+ // This is expected. It means that floater has been closed before
+ // processing was completed.
+ LL_DEBUGS("SCRIPTQ") << "LLExeceptionStaleHandle caught! Floater has most likely been closed." << LL_ENDL;
+ }
}
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 05c7e6caa5..4e69896b69 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -448,7 +448,12 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s
std::string LLConversationLog::getFileName()
{
std::string filename = "conversation";
- return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename) + ".log";
+ std::string log_address = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename);
+ if (!log_address.empty())
+ {
+ log_address += ".log";
+ }
+ return log_address;
}
bool LLConversationLog::saveToFile(const std::string& filename)
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index de349a03d4..481c66aaf5 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -2132,7 +2132,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLVector4a src;
U32 vec[4];
- vec[0] = vec[1] = vec[2] = vec[3] = color.mAll;
+ vec[0] = vec[1] = vec[2] = vec[3] = color.asRGBA();
src.loadua((F32*) vec);
@@ -2168,7 +2168,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLColor4U glow4u = LLColor4U(0,0,0,glow);
- U32 glow32 = glow4u.mAll;
+ U32 glow32 = glow4u.asRGBA();
U32 vec[4];
vec[0] = vec[1] = vec[2] = vec[3] = glow32;
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index bababca652..c2d0d9f06b 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -108,6 +108,7 @@ private:
static const std::string sCheckUpdateListenerName;
static void startFetchServerReleaseNotes();
+ static void fetchServerReleaseNotesCoro(const std::string& cap_url);
static void handleServerReleaseNotes(LLSD results);
};
@@ -224,35 +225,62 @@ void LLFloaterAbout::startFetchServerReleaseNotes()
// an URL suitable for external browsers in the "Location:" HTTP header.
std::string cap_url = region->getCapability("ServerReleaseNotes");
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(cap_url,
- &LLFloaterAbout::handleServerReleaseNotes, &LLFloaterAbout::handleServerReleaseNotes);
+ LLCoros::instance().launch("fetchServerReleaseNotesCoro", boost::bind(&LLFloaterAbout::fetchServerReleaseNotesCoro, cap_url));
}
/*static*/
+void LLFloaterAbout::fetchServerReleaseNotesCoro(const std::string& cap_url)
+{
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("fetchServerReleaseNotesCoro", LLCore::HttpRequest::DEFAULT_POLICY_ID));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ httpOpts->setWantHeaders(true);
+ httpOpts->setFollowRedirects(false);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ handleServerReleaseNotes(httpResults);
+ }
+ else
+ {
+ handleServerReleaseNotes(result);
+ }
+}
+
+/*static*/
void LLFloaterAbout::handleServerReleaseNotes(LLSD results)
{
-// LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about");
-// if (floater_about)
-// {
- LLSD http_headers;
- if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS))
- {
- LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
- }
- else
- {
- http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
- }
-
- std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString();
- if (location.empty())
- {
- location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
- }
- LLAppViewer::instance()->setServerReleaseNotesURL(location);
-// }
+ LLSD http_headers;
+ if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS))
+ {
+ LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+ }
+ else
+ {
+ http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+ }
+
+ std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString();
+ if (location.empty())
+ {
+ location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
+ }
+ LLAppViewer::instance()->setServerReleaseNotesURL(location);
+
+ LLFloaterAbout* floater_about = LLFloaterReg::findTypedInstance<LLFloaterAbout>("sl_about");
+ if (floater_about)
+ {
+ floater_about->setSupportText(location);
+ }
}
class LLFloaterAboutListener: public LLEventAPI
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 72892b47a4..aa7bfbfdb7 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -55,6 +55,8 @@
//#include "llsdserialize.h"
+static const U32 AVATAR_PICKER_SEARCH_TIMEOUT = 180U;
+
//put it back as a member once the legacy path is out?
static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
@@ -463,10 +465,13 @@ void LLFloaterAvatarPicker::findCoro(std::string url, LLUUID queryID, std::strin
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+ httpOpts->setTimeout(AVATAR_PICKER_SEARCH_TIMEOUT);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index e21a8594bc..91436e52fe 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -280,7 +280,7 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
void LLFloaterBuyCurrencyUI::onClickErrorWeb()
{
- LLWeb::loadURLExternal(mManager.errorURI());
+ LLWeb::loadURL(mManager.errorURI());
closeFloater();
// Update L$ balance
LLStatusBar::sendMoneyBalanceRequest();
diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index da85d378b2..b1d6d8be82 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -87,7 +87,7 @@ S32 compute_jpeg_quality(S32 width, S32 height)
{
F32 target_compression_ratio = (F32)(width * height * 3) / (F32)(TARGET_DATA_SIZE);
S32 quality = (S32)(110.0f - (2.0f * target_compression_ratio));
- return llclamp(quality,MIN_QUALITY,MAX_QUALITY);
+ return llclamp(quality, MIN_QUALITY, MAX_QUALITY);
}
///////////////////////////
@@ -95,52 +95,52 @@ S32 compute_jpeg_quality(S32 width, S32 height)
///////////////////////////
LLFacebookStatusPanel::LLFacebookStatusPanel() :
- mMessageTextEditor(NULL),
- mPostButton(NULL),
+ mMessageTextEditor(NULL),
+ mPostButton(NULL),
mCancelButton(NULL),
- mAccountCaptionLabel(NULL),
- mAccountNameLabel(NULL),
- mPanelButtons(NULL),
- mConnectButton(NULL),
- mDisconnectButton(NULL)
+ mAccountCaptionLabel(NULL),
+ mAccountNameLabel(NULL),
+ mPanelButtons(NULL),
+ mConnectButton(NULL),
+ mDisconnectButton(NULL)
{
- mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this));
- mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this));
+ mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookStatusPanel::onConnect, this));
+ mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookStatusPanel::onDisconnect, this));
- setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2));
+ setVisibleCallback(boost::bind(&LLFacebookStatusPanel::onVisibilityChange, this, _2));
- mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this));
+ mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this));
}
BOOL LLFacebookStatusPanel::postBuild()
{
- mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
- mAccountNameLabel = getChild<LLTextBox>("account_name_label");
- mPanelButtons = getChild<LLUICtrl>("panel_buttons");
- mConnectButton = getChild<LLUICtrl>("connect_btn");
- mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
+ mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
+ mAccountNameLabel = getChild<LLTextBox>("account_name_label");
+ mPanelButtons = getChild<LLUICtrl>("panel_buttons");
+ mConnectButton = getChild<LLUICtrl>("connect_btn");
+ mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
- mMessageTextEditor = getChild<LLUICtrl>("status_message");
- mPostButton = getChild<LLUICtrl>("post_status_btn");
- mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
+ mMessageTextEditor = getChild<LLUICtrl>("status_message");
+ mPostButton = getChild<LLUICtrl>("post_status_btn");
+ mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
- return LLPanel::postBuild();
+ return LLPanel::postBuild();
}
void LLFacebookStatusPanel::draw()
{
- LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
+ LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
- //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
- bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
- mDisconnectButton->setEnabled(!disconnecting);
+ //Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
+ bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
+ mDisconnectButton->setEnabled(!disconnecting);
- //Disable the 'connect' button when a connection is in progress
- bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
- mConnectButton->setEnabled(!connecting);
+ //Disable the 'connect' button when a connection is in progress
+ bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
+ mConnectButton->setEnabled(!connecting);
if (mMessageTextEditor && mPostButton && mCancelButton)
- {
+ {
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
std::string message = mMessageTextEditor->getValue().asString();
mMessageTextEditor->setEnabled(no_ongoing_connection);
@@ -148,175 +148,175 @@ void LLFacebookStatusPanel::draw()
mPostButton->setEnabled(no_ongoing_connection && !message.empty());
}
- LLPanel::draw();
+ LLPanel::draw();
}
void LLFacebookStatusPanel::onSend()
{
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1));
-
- // Connect to Facebook if necessary and then post
- if (LLFacebookConnect::instance().isConnected())
- {
- sendStatus();
- }
- else
- {
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
- }
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1));
+
+ // Connect to Facebook if necessary and then post
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ sendStatus();
+ }
+ else
+ {
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ }
}
bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data)
{
- switch (data.get("enum").asInteger())
- {
- case LLFacebookConnect::FB_CONNECTED:
- sendStatus();
- break;
-
- case LLFacebookConnect::FB_POSTED:
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel");
- clearAndClose();
- break;
- }
-
- return false;
+ switch (data.get("enum").asInteger())
+ {
+ case LLFacebookConnect::FB_CONNECTED:
+ sendStatus();
+ break;
+
+ case LLFacebookConnect::FB_POSTED:
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel");
+ clearAndClose();
+ break;
+ }
+
+ return false;
}
bool LLFacebookStatusPanel::onFacebookConnectAccountStateChange(const LLSD& data)
{
- if(LLFacebookConnect::instance().isConnected())
- {
- //In process of disconnecting so leave the layout as is
- if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
- {
- showConnectedLayout();
- }
- }
- else
- {
- showDisconnectedLayout();
- }
-
- return false;
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ //In process of disconnecting so leave the layout as is
+ if (data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
+ {
+ showConnectedLayout();
+ }
+ }
+ else
+ {
+ showDisconnectedLayout();
+ }
+
+ return false;
}
void LLFacebookStatusPanel::sendStatus()
{
- std::string message = mMessageTextEditor->getValue().asString();
- if (!message.empty())
- {
- LLFacebookConnect::instance().updateStatus(message);
- }
+ std::string message = mMessageTextEditor->getValue().asString();
+ if (!message.empty())
+ {
+ LLFacebookConnect::instance().updateStatus(message);
+ }
}
void LLFacebookStatusPanel::onVisibilityChange(BOOL visible)
{
- if(visible)
- {
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1));
-
- LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
- LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this));
-
- //Connected
- if(LLFacebookConnect::instance().isConnected())
- {
- showConnectedLayout();
- }
- //Check if connected (show disconnected layout in meantime)
- else
- {
- showDisconnectedLayout();
- }
+ if (visible)
+ {
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectAccountStateChange, this, _1));
+
+ LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
+ LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectInfoChange, this));
+
+ //Connected
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ showConnectedLayout();
+ }
+ //Check if connected (show disconnected layout in meantime)
+ else
+ {
+ showDisconnectedLayout();
+ }
if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
(LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
{
LLFacebookConnect::instance().checkConnectionToFacebook();
}
- }
- else
- {
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
- LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
- }
+ }
+ else
+ {
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
+ LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
+ }
}
bool LLFacebookStatusPanel::onFacebookConnectInfoChange()
{
- LLSD info = LLFacebookConnect::instance().getInfo();
- std::string clickable_name;
+ LLSD info = LLFacebookConnect::instance().getInfo();
+ std::string clickable_name;
- //Strings of format [http://www.somewebsite.com Click Me] become clickable text
- if(info.has("link") && info.has("name"))
- {
- clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
- }
+ //Strings of format [http://www.somewebsite.com Click Me] become clickable text
+ if (info.has("link") && info.has("name"))
+ {
+ clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
+ }
- mAccountNameLabel->setText(clickable_name);
+ mAccountNameLabel->setText(clickable_name);
- return false;
+ return false;
}
void LLFacebookStatusPanel::showConnectButton()
{
- if(!mConnectButton->getVisible())
- {
- mConnectButton->setVisible(TRUE);
- mDisconnectButton->setVisible(FALSE);
- }
+ if (!mConnectButton->getVisible())
+ {
+ mConnectButton->setVisible(TRUE);
+ mDisconnectButton->setVisible(FALSE);
+ }
}
void LLFacebookStatusPanel::hideConnectButton()
{
- if(mConnectButton->getVisible())
- {
- mConnectButton->setVisible(FALSE);
- mDisconnectButton->setVisible(TRUE);
- }
+ if (mConnectButton->getVisible())
+ {
+ mConnectButton->setVisible(FALSE);
+ mDisconnectButton->setVisible(TRUE);
+ }
}
void LLFacebookStatusPanel::showDisconnectedLayout()
{
- mAccountCaptionLabel->setText(getString("facebook_disconnected"));
- mAccountNameLabel->setText(std::string(""));
- showConnectButton();
+ mAccountCaptionLabel->setText(getString("facebook_disconnected"));
+ mAccountNameLabel->setText(std::string(""));
+ showConnectButton();
}
void LLFacebookStatusPanel::showConnectedLayout()
{
- LLFacebookConnect::instance().loadFacebookInfo();
+ LLFacebookConnect::instance().loadFacebookInfo();
- mAccountCaptionLabel->setText(getString("facebook_connected"));
- hideConnectButton();
+ mAccountCaptionLabel->setText(getString("facebook_connected"));
+ hideConnectButton();
}
void LLFacebookStatusPanel::onConnect()
{
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
- //Clear only the facebook browser cookies so that the facebook login screen appears
- LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
+ //Clear only the facebook browser cookies so that the facebook login screen appears
+ LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
}
void LLFacebookStatusPanel::onDisconnect()
{
- LLFacebookConnect::instance().disconnectFromFacebook();
+ LLFacebookConnect::instance().disconnectFromFacebook();
- LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
+ LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com");
}
void LLFacebookStatusPanel::clearAndClose()
{
- mMessageTextEditor->setValue("");
+ mMessageTextEditor->setValue("");
- LLFloater* floater = getParentByType<LLFloater>();
- if (floater)
- {
- floater->closeFloater();
- }
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
+ }
}
///////////////////////////
@@ -324,89 +324,89 @@ void LLFacebookStatusPanel::clearAndClose()
///////////////////////////
LLFacebookPhotoPanel::LLFacebookPhotoPanel() :
-mResolutionComboBox(NULL),
-mRefreshBtn(NULL),
-mBtnPreview(NULL),
-mWorkingLabel(NULL),
-mThumbnailPlaceholder(NULL),
-mCaptionTextBox(NULL),
-mPostButton(NULL),
-mBigPreviewFloater(NULL),
-mQuality(MAX_QUALITY)
+ mResolutionComboBox(NULL),
+ mRefreshBtn(NULL),
+ mBtnPreview(NULL),
+ mWorkingLabel(NULL),
+ mThumbnailPlaceholder(NULL),
+ mCaptionTextBox(NULL),
+ mPostButton(NULL),
+ mBigPreviewFloater(NULL),
+ mQuality(MAX_QUALITY)
{
- mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
- mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
- mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this));
+ mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
+ mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
+ mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this));
}
LLFacebookPhotoPanel::~LLFacebookPhotoPanel()
{
- if(mPreviewHandle.get())
- {
- mPreviewHandle.get()->die();
- }
+ if (mPreviewHandle.get())
+ {
+ mPreviewHandle.get()->die();
+ }
}
BOOL LLFacebookPhotoPanel::postBuild()
{
- setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2));
-
- mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
- mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw!
- mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
- mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
- mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
- mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
- mBtnPreview = getChild<LLButton>("big_preview_btn");
+ setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2));
+
+ mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+ mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw!
+ mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
+ mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
+ mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
+ mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+ mBtnPreview = getChild<LLButton>("big_preview_btn");
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
- mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
- mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
- mPostButton = getChild<LLUICtrl>("post_photo_btn");
- mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
- mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+ mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+ mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
+ mPostButton = getChild<LLUICtrl>("post_photo_btn");
+ mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+ mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
- // Update filter list
+ // Update filter list
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
- LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+ LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
for (U32 i = 0; i < filter_list.size(); i++)
- {
+ {
filterbox->add(filter_list[i]);
}
- return LLPanel::postBuild();
+ return LLPanel::postBuild();
}
// virtual
S32 LLFacebookPhotoPanel::notify(const LLSD& info)
{
- if (info.has("snapshot-updating"))
- {
+ if (info.has("snapshot-updating"))
+ {
// Disable the Post button and whatever else while the snapshot is not updated
// updateControls();
- return 1;
- }
-
- if (info.has("snapshot-updated"))
- {
+ return 1;
+ }
+
+ if (info.has("snapshot-updated"))
+ {
// Enable the send/post/save buttons.
updateControls();
-
- // The refresh button is initially hidden. We show it after the first update,
- // i.e. after snapshot is taken
- LLUICtrl * refresh_button = getRefreshBtn();
- if (!refresh_button->getVisible())
- {
- refresh_button->setVisible(true);
- }
- return 1;
- }
-
- return 0;
+
+ // The refresh button is initially hidden. We show it after the first update,
+ // i.e. after snapshot is taken
+ LLUICtrl * refresh_button = getRefreshBtn();
+ if (!refresh_button->getVisible())
+ {
+ refresh_button->setVisible(true);
+ }
+ return 1;
+ }
+
+ return 0;
}
void LLFacebookPhotoPanel::draw()
-{
- LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+{
+ LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
@@ -416,98 +416,98 @@ void LLFacebookPhotoPanel::draw()
mFilterComboBox->setEnabled(no_ongoing_connection);
mRefreshBtn->setEnabled(no_ongoing_connection);
mBtnPreview->setEnabled(no_ongoing_connection);
-
+
// Reassign the preview floater if we have the focus and the preview exists
if (hasFocus() && isPreviewVisible())
{
attachPreview();
}
-
+
// Toggle the button state as appropriate
bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
- mBtnPreview->setToggleState(preview_active);
-
+ mBtnPreview->setToggleState(preview_active);
+
// Display the thumbnail if one is available
- if (previewp && previewp->getThumbnailImage())
- {
- const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
- const S32 thumbnail_w = previewp->getThumbnailWidth();
- const S32 thumbnail_h = previewp->getThumbnailHeight();
-
- // calc preview offset within the preview rect
- const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
- const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
- S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
- S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- // Apply floater transparency to the texture unless the floater is focused.
- F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
- LLColor4 color = LLColor4::white;
- gl_draw_scaled_image(offset_x, offset_y,
- thumbnail_w, thumbnail_h,
- previewp->getThumbnailImage(), color % alpha);
- }
+ if (previewp && previewp->getThumbnailImage())
+ {
+ const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
+ const S32 thumbnail_w = previewp->getThumbnailWidth();
+ const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+ // calc preview offset within the preview rect
+ const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2;
+ const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2;
+ S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
+ S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ // Apply floater transparency to the texture unless the floater is focused.
+ F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+ LLColor4 color = LLColor4::white;
+ gl_draw_scaled_image(offset_x, offset_y,
+ thumbnail_w, thumbnail_h,
+ previewp->getThumbnailImage(), color % alpha);
+ }
// Update the visibility of the working (computing preview) label
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
-
+
// Enable Post if we have a preview to send and no on going connection being processed
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
-
+
// Draw the rest of the panel on top of it
- LLPanel::draw();
+ LLPanel::draw();
}
LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView()
{
- LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
- return previewp;
+ LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
+ return previewp;
}
void LLFacebookPhotoPanel::onVisibilityChange(BOOL visible)
{
- if (visible)
- {
- if (mPreviewHandle.get())
- {
- LLSnapshotLivePreview* preview = getPreviewView();
- if(preview)
- {
- LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
- preview->updateSnapshot(TRUE);
- }
- }
- else
- {
- LLRect full_screen_rect = getRootView()->getRect();
- LLSnapshotLivePreview::Params p;
- p.rect(full_screen_rect);
- LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
- mPreviewHandle = previewp->getHandle();
+ if (visible)
+ {
+ if (mPreviewHandle.get())
+ {
+ LLSnapshotLivePreview* preview = getPreviewView();
+ if (preview)
+ {
+ LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
+ preview->updateSnapshot(TRUE);
+ }
+ }
+ else
+ {
+ LLRect full_screen_rect = getRootView()->getRect();
+ LLSnapshotLivePreview::Params p;
+ p.rect(full_screen_rect);
+ LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+ mPreviewHandle = previewp->getHandle();
mQuality = MAX_QUALITY;
previewp->setContainer(this);
- previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
- previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
- previewp->setSnapshotQuality(mQuality, false);
+ previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
+ previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
+ previewp->setSnapshotQuality(mQuality, false);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
- previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
+ previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
- updateControls();
- }
- }
+ updateControls();
+ }
+ }
}
void LLFacebookPhotoPanel::onClickNewSnapshot()
{
- LLSnapshotLivePreview* previewp = getPreviewView();
- if (previewp)
- {
- previewp->updateSnapshot(TRUE);
- }
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ if (previewp)
+ {
+ previewp->updateSnapshot(TRUE);
+ }
}
void LLFacebookPhotoPanel::onClickBigPreview()
@@ -541,167 +541,167 @@ void LLFacebookPhotoPanel::attachPreview()
void LLFacebookPhotoPanel::onSend()
{
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1));
-
- // Connect to Facebook if necessary and then post
- if (LLFacebookConnect::instance().isConnected())
- {
- sendPhoto();
- }
- else
- {
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
- }
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1));
+
+ // Connect to Facebook if necessary and then post
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ sendPhoto();
+ }
+ else
+ {
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ }
}
bool LLFacebookPhotoPanel::onFacebookConnectStateChange(const LLSD& data)
{
- switch (data.get("enum").asInteger())
- {
- case LLFacebookConnect::FB_CONNECTED:
- sendPhoto();
- break;
-
- case LLFacebookConnect::FB_POSTED:
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel");
- clearAndClose();
- break;
- }
-
- return false;
+ switch (data.get("enum").asInteger())
+ {
+ case LLFacebookConnect::FB_CONNECTED:
+ sendPhoto();
+ break;
+
+ case LLFacebookConnect::FB_POSTED:
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel");
+ clearAndClose();
+ break;
+ }
+
+ return false;
}
void LLFacebookPhotoPanel::sendPhoto()
{
- // Get the caption
- std::string caption = mCaptionTextBox->getValue().asString();
+ // Get the caption
+ std::string caption = mCaptionTextBox->getValue().asString();
- // Get the image
- LLSnapshotLivePreview* previewp = getPreviewView();
-
- // Post to Facebook
- LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
+ // Get the image
+ LLSnapshotLivePreview* previewp = getPreviewView();
- updateControls();
+ // Post to Facebook
+ LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
+
+ updateControls();
}
void LLFacebookPhotoPanel::clearAndClose()
{
- mCaptionTextBox->setValue("");
+ mCaptionTextBox->setValue("");
- LLFloater* floater = getParentByType<LLFloater>();
- if (floater)
- {
- floater->closeFloater();
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
if (mBigPreviewFloater)
{
mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
}
- }
+ }
}
void LLFacebookPhotoPanel::updateControls()
{
- LLSnapshotLivePreview* previewp = getPreviewView();
- BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-
- // *TODO: Separate maximum size for Web images from postcards
- LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
-
- updateResolution(FALSE);
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+
+ // *TODO: Separate maximum size for Web images from postcards
+ LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
+
+ updateResolution(FALSE);
}
void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
{
- LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
- LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+ LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+ LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
- std::string sdstring = combobox->getSelectedValue();
- LLSD sdres;
- std::stringstream sstream(sdstring);
- LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
+ std::string sdstring = combobox->getSelectedValue();
+ LLSD sdres;
+ std::stringstream sstream(sdstring);
+ LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
- S32 width = sdres[0];
- S32 height = sdres[1];
+ S32 width = sdres[0];
+ S32 height = sdres[1];
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
- LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
- if (previewp && combobox->getCurrentIndex() >= 0)
- {
- S32 original_width = 0 , original_height = 0 ;
- previewp->getSize(original_width, original_height) ;
-
- if (width == 0 || height == 0)
- {
- // take resolution from current window size
- LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL;
- previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
- }
- else
- {
- // use the resolution from the selected pre-canned drop-down choice
- LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
- previewp->setSize(width, height);
- }
-
- checkAspectRatio(width);
-
- previewp->getSize(width, height);
-
+ LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+ if (previewp && combobox->getCurrentIndex() >= 0)
+ {
+ S32 original_width = 0, original_height = 0;
+ previewp->getSize(original_width, original_height);
+
+ if (width == 0 || height == 0)
+ {
+ // take resolution from current window size
+ LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL;
+ previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+ }
+ else
+ {
+ // use the resolution from the selected pre-canned drop-down choice
+ LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
+ previewp->setSize(width, height);
+ }
+
+ checkAspectRatio(width);
+
+ previewp->getSize(width, height);
+
// Recompute quality setting
mQuality = compute_jpeg_quality(width, height);
previewp->setSnapshotQuality(mQuality, false);
-
- if (original_width != width || original_height != height)
- {
- previewp->setSize(width, height);
- if (do_update)
- {
+
+ if (original_width != width || original_height != height)
+ {
+ previewp->setSize(width, height);
+ if (do_update)
+ {
previewp->updateSnapshot(TRUE);
- updateControls();
- }
- }
+ updateControls();
+ }
+ }
// Get the old filter, compare to the current one "filter_name" and set if changed
std::string original_filter = previewp->getFilter();
- if (original_filter != filter_name)
- {
+ if (original_filter != filter_name)
+ {
previewp->setFilter(filter_name);
- if (do_update)
- {
+ if (do_update)
+ {
previewp->updateSnapshot(FALSE, TRUE);
- updateControls();
- }
- }
- }
+ updateControls();
+ }
+ }
+ }
}
void LLFacebookPhotoPanel::checkAspectRatio(S32 index)
{
- LLSnapshotLivePreview *previewp = getPreviewView() ;
-
- BOOL keep_aspect = FALSE;
-
- if (0 == index) // current window size
- {
- keep_aspect = TRUE;
- }
- else // predefined resolution
- {
- keep_aspect = FALSE;
- }
-
- if (previewp)
- {
- previewp->mKeepAspectRatio = keep_aspect;
- }
+ LLSnapshotLivePreview *previewp = getPreviewView();
+
+ BOOL keep_aspect = FALSE;
+
+ if (0 == index) // current window size
+ {
+ keep_aspect = TRUE;
+ }
+ else // predefined resolution
+ {
+ keep_aspect = FALSE;
+ }
+
+ if (previewp)
+ {
+ previewp->mKeepAspectRatio = keep_aspect;
+ }
}
LLUICtrl* LLFacebookPhotoPanel::getRefreshBtn()
{
- return mRefreshBtn;
+ return mRefreshBtn;
}
////////////////////////
@@ -712,21 +712,21 @@ LLFacebookCheckinPanel::LLFacebookCheckinPanel() :
mMapUrl(""),
mReloadingMapTexture(false)
{
- mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this));
+ mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this));
}
BOOL LLFacebookCheckinPanel::postBuild()
{
// Keep pointers to widgets so we don't traverse the UI hierarchy too often
- mPostButton = getChild<LLUICtrl>("post_place_btn");
- mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
- mMessageTextEditor = getChild<LLUICtrl>("place_caption");
+ mPostButton = getChild<LLUICtrl>("post_place_btn");
+ mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
+ mMessageTextEditor = getChild<LLUICtrl>("place_caption");
mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator");
mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder");
mMapDefault = getChild<LLIconCtrl>("map_default");
mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb");
-
- return LLPanel::postBuild();
+
+ return LLPanel::postBuild();
}
void LLFacebookCheckinPanel::draw()
@@ -767,101 +767,101 @@ void LLFacebookCheckinPanel::draw()
// This will hide/show the loading indicator and/or tile underneath
mMapDefault->setVisible(!(mMapCheckBox->get()));
- LLPanel::draw();
+ LLPanel::draw();
}
void LLFacebookCheckinPanel::onSend()
{
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1));
-
- // Connect to Facebook if necessary and then post
- if (LLFacebookConnect::instance().isConnected())
- {
- sendCheckin();
- }
- else
- {
- LLFacebookConnect::instance().checkConnectionToFacebook(true);
- }
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1));
+
+ // Connect to Facebook if necessary and then post
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ sendCheckin();
+ }
+ else
+ {
+ LLFacebookConnect::instance().checkConnectionToFacebook(true);
+ }
}
bool LLFacebookCheckinPanel::onFacebookConnectStateChange(const LLSD& data)
{
- switch (data.get("enum").asInteger())
- {
- case LLFacebookConnect::FB_CONNECTED:
- sendCheckin();
- break;
-
- case LLFacebookConnect::FB_POSTED:
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel");
- clearAndClose();
- break;
- }
-
- return false;
+ switch (data.get("enum").asInteger())
+ {
+ case LLFacebookConnect::FB_CONNECTED:
+ sendCheckin();
+ break;
+
+ case LLFacebookConnect::FB_POSTED:
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel");
+ clearAndClose();
+ break;
+ }
+
+ return false;
}
void LLFacebookCheckinPanel::sendCheckin()
{
- // Get the location SLURL
- LLSLURL slurl;
- LLAgentUI::buildSLURL(slurl);
- std::string slurl_string = slurl.getSLURLString();
-
- // Use a valid http:// URL if the scheme is secondlife://
- LLURI slurl_uri(slurl_string);
- if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
- {
- slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
- }
-
- // Add query parameters so Google Analytics can track incoming clicks!
- slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
-
- // Get the region name
- std::string region_name("");
+ // Get the location SLURL
+ LLSLURL slurl;
+ LLAgentUI::buildSLURL(slurl);
+ std::string slurl_string = slurl.getSLURLString();
+
+ // Use a valid http:// URL if the scheme is secondlife://
+ LLURI slurl_uri(slurl_string);
+ if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
+ {
+ slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
+ }
+
+ // Add query parameters so Google Analytics can track incoming clicks!
+ slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
+
+ // Get the region name
+ std::string region_name("");
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
region_name = regionp->getName();
}
-
- // Get the region description
- std::string description;
- LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
-
- // Optionally add the region map view
- bool add_map_view = mMapCheckBox->getValue().asBoolean();
+
+ // Get the region description
+ std::string description;
+ LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
+
+ // Optionally add the region map view
+ bool add_map_view = mMapCheckBox->getValue().asBoolean();
std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL);
-
- // Get the caption
- std::string caption = mMessageTextEditor->getValue().asString();
- // Post to Facebook
- LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
+ // Get the caption
+ std::string caption = mMessageTextEditor->getValue().asString();
+
+ // Post to Facebook
+ LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
}
void LLFacebookCheckinPanel::clearAndClose()
{
- mMessageTextEditor->setValue("");
+ mMessageTextEditor->setValue("");
- LLFloater* floater = getParentByType<LLFloater>();
- if (floater)
- {
- floater->closeFloater();
- }
+ LLFloater* floater = getParentByType<LLFloater>();
+ if (floater)
+ {
+ floater->closeFloater();
+ }
}
///////////////////////////
//LLFacebookFriendsPanel//////
///////////////////////////
-LLFacebookFriendsPanel::LLFacebookFriendsPanel() :
-mFriendsStatusCaption(NULL),
-mSecondLifeFriends(NULL),
-mSuggestedFriends(NULL)
+LLFacebookFriendsPanel::LLFacebookFriendsPanel() :
+ mFriendsStatusCaption(NULL),
+ mSecondLifeFriends(NULL),
+ mSuggestedFriends(NULL)
{
}
@@ -872,55 +872,55 @@ LLFacebookFriendsPanel::~LLFacebookFriendsPanel()
BOOL LLFacebookFriendsPanel::postBuild()
{
- mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status");
+ mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status");
+
+ mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
+ mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
- mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
- mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
-
- mSuggestedFriends = getChild<LLAvatarList>("suggested_friends");
- mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
-
- setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));
+ mSuggestedFriends = getChild<LLAvatarList>("suggested_friends");
+ mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
+
+ setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));
LLAvatarTracker::instance().addObserver(this);
-
- return LLPanel::postBuild();
+
+ return LLPanel::postBuild();
}
bool LLFacebookFriendsPanel::updateSuggestedFriendList()
{
- const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
- uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs();
- second_life_friends.clear();
- uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
- suggested_friends.clear();
-
- //Add suggested friends
- LLSD friends = LLFacebookConnect::instance().getContent();
- for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
- {
- LLUUID agent_id = (*i).asUUID();
- if (agent_id.notNull())
- {
- bool second_life_buddy = av_tracker.isBuddy(agent_id);
- if (second_life_buddy)
- {
- second_life_friends.push_back(agent_id);
- }
- else
- {
- //FB+SL but not SL friend
- suggested_friends.push_back(agent_id);
- }
- }
- }
-
- //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
- mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches());
- mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
- showFriendsAccordionsIfNeeded();
-
- return false;
+ const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
+ uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs();
+ second_life_friends.clear();
+ uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
+ suggested_friends.clear();
+
+ //Add suggested friends
+ LLSD friends = LLFacebookConnect::instance().getContent();
+ for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
+ {
+ LLUUID agent_id = (*i).asUUID();
+ if (agent_id.notNull())
+ {
+ bool second_life_buddy = av_tracker.isBuddy(agent_id);
+ if (second_life_buddy)
+ {
+ second_life_friends.push_back(agent_id);
+ }
+ else
+ {
+ //FB+SL but not SL friend
+ suggested_friends.push_back(agent_id);
+ }
+ }
+ }
+
+ //Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
+ mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches());
+ mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
+ showFriendsAccordionsIfNeeded();
+
+ return false;
}
void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
@@ -949,15 +949,15 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
{
// We have something in the lists, hide the explanatory text
mFriendsStatusCaption->setVisible(false);
-
+
// Show the lists
LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
accordion->setVisible(true);
-
+
// Expand and show accordions if needed, else - hide them
getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches());
getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches());
-
+
// Rearrange accordions
accordion->arrange();
}
@@ -965,56 +965,56 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
void LLFacebookFriendsPanel::changed(U32 mask)
{
- if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
- {
+ if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
+ {
LLFacebookConnect::instance().loadFacebookFriends();
- updateFacebookList(true);
- }
+ updateFacebookList(true);
+ }
}
void LLFacebookFriendsPanel::updateFacebookList(bool visible)
{
- if (visible)
- {
+ if (visible)
+ {
// We want this to be called to fetch the friends list once a connection is established
- LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel");
- LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
-
+ LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel");
+ LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
+
// We then want this to be called to update the displayed lists once the list of friends is received
- LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening
- LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
-
- // Try to connect to Facebook
+ LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening
+ LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
+
+ // Try to connect to Facebook
if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
(LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
{
LLFacebookConnect::instance().checkConnectionToFacebook();
}
- // Loads FB friends
- if (LLFacebookConnect::instance().isConnected())
- {
- LLFacebookConnect::instance().loadFacebookFriends();
- }
+ // Loads FB friends
+ if (LLFacebookConnect::instance().isConnected())
+ {
+ LLFacebookConnect::instance().loadFacebookFriends();
+ }
// Sort the FB friends and update the lists
- updateSuggestedFriendList();
- }
+ updateSuggestedFriendList();
+ }
}
bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data)
{
- LLSD::Integer connection_state = data.get("enum").asInteger();
-
- if (connection_state == LLFacebookConnect::FB_CONNECTED)
- {
- LLFacebookConnect::instance().loadFacebookFriends();
- }
- else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
- {
- updateSuggestedFriendList();
- }
-
- return false;
+ LLSD::Integer connection_state = data.get("enum").asInteger();
+
+ if (connection_state == LLFacebookConnect::FB_CONNECTED)
+ {
+ LLFacebookConnect::instance().loadFacebookFriends();
+ }
+ else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
+ {
+ updateSuggestedFriendList();
+ }
+
+ return false;
}
////////////////////////
@@ -1027,7 +1027,7 @@ LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key),
mStatusLoadingText(NULL),
mStatusLoadingIndicator(NULL)
{
- mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));
+ mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));
}
void LLFloaterFacebook::onClose(bool app_quitting)
@@ -1037,7 +1037,7 @@ void LLFloaterFacebook::onClose(bool app_quitting)
{
big_preview_floater->closeOnFloaterOwnerClosing(this);
}
- LLFloater::onClose(app_quitting);
+ LLFloater::onClose(app_quitting);
}
void LLFloaterFacebook::onCancel()
@@ -1053,24 +1053,24 @@ void LLFloaterFacebook::onCancel()
BOOL LLFloaterFacebook::postBuild()
{
// Keep tab of the Photo Panel
- mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo"));
+ mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo"));
// Connection status widgets
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
- return LLFloater::postBuild();
+ return LLFloater::postBuild();
}
void LLFloaterFacebook::showPhotoPanel()
{
- LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent());
- if (!parent)
- {
- LL_WARNS() << "Cannot find panel container" << LL_ENDL;
- return;
- }
-
- parent->selectTabPanel(mFacebookPhotoPanel);
+ LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent());
+ if (!parent)
+ {
+ LL_WARNS() << "Cannot find panel container" << LL_ENDL;
+ return;
+ }
+
+ parent->selectTabPanel(mFacebookPhotoPanel);
}
void LLFloaterFacebook::draw()
@@ -1082,7 +1082,7 @@ void LLFloaterFacebook::draw()
mStatusLoadingIndicator->setVisible(false);
LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
std::string status_text;
-
+
switch (connection_state)
{
case LLFacebookConnect::FB_NOT_CONNECTED:
@@ -1105,7 +1105,7 @@ void LLFloaterFacebook::draw()
status_text = LLTrans::getString("SocialFacebookPosting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
- break;
+ break;
case LLFacebookConnect::FB_CONNECTION_FAILED:
// Error connecting to the service
mStatusErrorText->setVisible(true);
@@ -1118,21 +1118,21 @@ void LLFloaterFacebook::draw()
status_text = LLTrans::getString("SocialFacebookErrorPosting");
mStatusErrorText->setValue(status_text);
break;
- case LLFacebookConnect::FB_DISCONNECTING:
- // Disconnecting loading indicator
- mStatusLoadingText->setVisible(true);
- status_text = LLTrans::getString("SocialFacebookDisconnecting");
- mStatusLoadingText->setValue(status_text);
- mStatusLoadingIndicator->setVisible(true);
- break;
- case LLFacebookConnect::FB_DISCONNECT_FAILED:
- // Error disconnecting from the service
- mStatusErrorText->setVisible(true);
- status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
- mStatusErrorText->setValue(status_text);
- break;
+ case LLFacebookConnect::FB_DISCONNECTING:
+ // Disconnecting loading indicator
+ mStatusLoadingText->setVisible(true);
+ status_text = LLTrans::getString("SocialFacebookDisconnecting");
+ mStatusLoadingText->setValue(status_text);
+ mStatusLoadingIndicator->setVisible(true);
+ break;
+ case LLFacebookConnect::FB_DISCONNECT_FAILED:
+ // Error disconnecting from the service
+ mStatusErrorText->setVisible(true);
+ status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
+ mStatusErrorText->setValue(status_text);
+ break;
}
}
- LLFloater::draw();
+ LLFloater::draw();
}
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index cd132b843d..15b7c7fafa 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -238,8 +238,8 @@ void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible)
mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
- previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
- previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG);
+ previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
+ previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index d842106146..b840d37c4d 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -328,7 +328,7 @@ void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gestur
element["columns"][0]["font"]["name"] = "SANSSERIF";
element["columns"][0]["font"]["style"] = font_style;
- std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
+ std::string key_string;
std::string buffer;
if (gesture->mKey == KEY_NONE)
@@ -338,6 +338,7 @@ void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gestur
}
else
{
+ key_string = LLKeyboard::stringFromKey(gesture->mKey);
buffer = LLKeyboard::stringFromAccelerator(gesture->mMask,
gesture->mKey);
}
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 7a989806a1..257b39a7dd 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -798,7 +798,8 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32*
}
else if (mesg[0] == '/'
&& mesg[1]
- && LLStringOps::isDigit(mesg[1]))
+ && (LLStringOps::isDigit(mesg[1])
+ || (mesg[1] == '-' && mesg[2] && LLStringOps::isDigit(mesg[2]))))
{
// This a special "/20" speak on a channel
S32 pos = 0;
@@ -812,7 +813,7 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32*
channel_string.push_back(c);
pos++;
}
- while(c && pos < 64 && LLStringOps::isDigit(c));
+ while(c && pos < 64 && (LLStringOps::isDigit(c) || (pos==1 && c =='-')));
// Move the pointer forward to the first non-whitespace char
// Check isspace before looping, so we can handle "/33foo"
@@ -837,19 +838,36 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32*
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
{
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ChatFromViewer);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ChatData);
- msg->addStringFast(_PREHASH_Message, utf8_out_text);
- msg->addU8Fast(_PREHASH_Type, type);
- msg->addS32("Channel", channel);
-
- gAgent.sendReliableMessage();
-
- add(LLStatViewer::CHAT_COUNT, 1);
+ LLMessageSystem* msg = gMessageSystem;
+
+ if (channel >= 0)
+ {
+ msg->newMessageFast(_PREHASH_ChatFromViewer);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ChatData);
+ msg->addStringFast(_PREHASH_Message, utf8_out_text);
+ msg->addU8Fast(_PREHASH_Type, type);
+ msg->addS32("Channel", channel);
+
+ }
+ else
+ {
+ // Hack: ChatFromViewer doesn't allow negative channels
+ msg->newMessage("ScriptDialogReply");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgentID);
+ msg->addUUID("SessionID", gAgentSessionID);
+ msg->nextBlock("Data");
+ msg->addUUID("ObjectID", gAgentID);
+ msg->addS32("ChatChannel", channel);
+ msg->addS32("ButtonIndex", 0);
+ msg->addString("ButtonLabel", utf8_out_text);
+ }
+
+ gAgent.sendReliableMessage();
+ add(LLStatViewer::CHAT_COUNT, 1);
}
class LLChatCommandHandler : public LLCommandHandler
diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp
new file mode 100644
index 0000000000..d80793f9e4
--- /dev/null
+++ b/indra/newview/llfloateroutfitsnapshot.cpp
@@ -0,0 +1,377 @@
+/**
+ * @file llfloateroutfitsnapshot.cpp
+ * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2016, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatersnapshot.h"
+#include "llfloateroutfitsnapshot.h"
+
+#include "llagent.h"
+#include "llfacebookconnect.h"
+#include "llfloaterreg.h"
+#include "llfloaterfacebook.h"
+#include "llfloaterflickr.h"
+#include "llfloatertwitter.h"
+#include "llimagefiltersmanager.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llpostcard.h"
+#include "llresmgr.h" // LLLocale
+#include "llsdserialize.h"
+#include "llsidetraypanelcontainer.h"
+#include "llspinctrl.h"
+#include "llviewercontrol.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "llwebprofile.h"
+
+///----------------------------------------------------------------------------
+/// Local function declarations, constants, enums, and typedefs
+///----------------------------------------------------------------------------
+LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView = NULL;
+
+const S32 OUTFIT_SNAPSHOT_WIDTH = 256;
+const S32 OUTFIT_SNAPSHOT_HEIGHT = 256;
+
+static LLDefaultChildRegistry::Register<LLOutfitSnapshotFloaterView> r("snapshot_outfit_floater_view");
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot::Impl
+///----------------------------------------------------------------------------
+
+// virtual
+LLPanelSnapshot* LLFloaterOutfitSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found)
+{
+ LLPanel* panel = floater->getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel);
+ if (!ok_if_not_found)
+ {
+ llassert_always(active_panel != NULL);
+ }
+ return active_panel;
+}
+
+// virtual
+LLSnapshotModel::ESnapshotFormat LLFloaterOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
+{
+ return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
+}
+
+// virtual
+LLSnapshotModel::ESnapshotLayerType LLFloaterOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
+{
+ return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
+}
+
+// This is the main function that keeps all the GUI controls in sync with the saved settings.
+// It should be called anytime a setting is changed that could affect the controls.
+// No other methods should be changing any of the controls directly except for helpers called by this method.
+// The basic pattern for programmatically changing the GUI settings is to first set the
+// appropriate saved settings and then call this method to sync the GUI with them.
+// FIXME: The above comment seems obsolete now.
+// virtual
+void LLFloaterOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
+{
+ LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater);
+ LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater);
+
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+
+ // *TODO: Separate maximum size for Web images from postcards
+ LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
+
+ LLLocale locale(LLLocale::USER_LOCALE);
+ std::string bytes_string;
+ if (got_snap)
+ {
+ LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10);
+ }
+
+ // Update displayed image resolution.
+ LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text");
+ image_res_tb->setVisible(got_snap);
+ if (got_snap)
+ {
+ image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth()));
+ image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight()));
+ }
+
+ floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
+ floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor("LabelTextColor"));
+
+ updateResolution(floater);
+
+ if (previewp)
+ {
+ previewp->setSnapshotType(shot_type);
+ previewp->setSnapshotFormat(shot_format);
+ previewp->setSnapshotBufferType(layer_type);
+ }
+
+ LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
+ if (current_panel)
+ {
+ LLSD info;
+ info["have-snapshot"] = got_snap;
+ current_panel->updateControls(info);
+ }
+ LL_DEBUGS() << "finished updating controls" << LL_ENDL;
+}
+
+// virtual
+std::string LLFloaterOutfitSnapshot::Impl::getSnapshotPanelPrefix()
+{
+ return "panel_outfit_snapshot_";
+}
+
+// Show/hide upload status message.
+// virtual
+void LLFloaterOutfitSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg)
+{
+ mFloater->setSuccessLabelPanelVisible(finished && ok);
+ mFloater->setFailureLabelPanelVisible(finished && !ok);
+
+ if (finished)
+ {
+ LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
+ std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
+ finished_lbl->setValue(result_text);
+
+ LLPanel* snapshot_panel = mFloater->getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ snapshot_panel->onOpen(LLSD());
+ }
+}
+
+void LLFloaterOutfitSnapshot::Impl::updateResolution(void* data)
+{
+ LLFloaterOutfitSnapshot *view = (LLFloaterOutfitSnapshot *)data;
+
+ if (!view)
+ {
+ llassert(view);
+ return;
+ }
+
+ S32 width = OUTFIT_SNAPSHOT_WIDTH;
+ S32 height = OUTFIT_SNAPSHOT_HEIGHT;
+
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ if (previewp)
+ {
+ S32 original_width = 0, original_height = 0;
+ previewp->getSize(original_width, original_height);
+
+ if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
+ { //clamp snapshot resolution to window size when showing UI or HUD in snapshot
+ width = llmin(width, gViewerWindow->getWindowWidthRaw());
+ height = llmin(height, gViewerWindow->getWindowHeightRaw());
+ }
+
+
+ llassert(width > 0 && height > 0);
+
+ // use the resolution from the selected pre-canned drop-down choice
+ LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
+ previewp->setSize(width, height);
+
+ if (original_width != width || original_height != height)
+ {
+ // hide old preview as the aspect ratio could be wrong
+ checkAutoSnapshot(previewp, FALSE);
+ LL_DEBUGS() << "updating thumbnail" << LL_ENDL;
+ previewp->updateSnapshot(TRUE);
+ }
+ }
+}
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLFloaterOutfitSnapshot::LLFloaterOutfitSnapshot(const LLSD& key)
+: LLFloaterSnapshotBase(key),
+mOutfitGallery(NULL)
+{
+ impl = new Impl(this);
+}
+
+LLFloaterOutfitSnapshot::~LLFloaterOutfitSnapshot()
+{
+}
+
+// virtual
+BOOL LLFloaterOutfitSnapshot::postBuild()
+{
+ mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+ childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
+ mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
+ mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
+ mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
+
+ childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);
+ getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
+
+ childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);
+ getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
+
+ getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));
+ childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this);
+
+ getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
+ childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this);
+
+ getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
+ getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this));
+
+ // Filters
+ LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
+ std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+ for (U32 i = 0; i < filter_list.size(); i++)
+ {
+ filterbox->add(filter_list[i]);
+ }
+ childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this);
+
+ mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+
+ // create preview window
+ LLRect full_screen_rect = getRootView()->getRect();
+ LLSnapshotLivePreview::Params p;
+ p.rect(full_screen_rect);
+ LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+ LLView* parent_view = gSnapshotFloaterView->getParent();
+
+ parent_view->removeChild(gSnapshotFloaterView);
+ // make sure preview is below snapshot floater
+ parent_view->addChild(previewp);
+ parent_view->addChild(gSnapshotFloaterView);
+
+ //move snapshot floater to special purpose snapshotfloaterview
+ gFloaterView->removeChild(this);
+ gSnapshotFloaterView->addChild(this);
+
+ impl->mPreviewHandle = previewp->getHandle();
+ previewp->setContainer(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+ impl->updateLayout(this);
+
+ previewp->mKeepAspectRatio = FALSE;
+ previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterOutfitSnapshot::onOpen(const LLSD& key)
+{
+ LLSnapshotLivePreview* preview = getPreviewView();
+ if (preview)
+ {
+ LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
+ preview->updateSnapshot(TRUE);
+ }
+ focusFirstItem(FALSE);
+ gSnapshotFloaterView->setEnabled(TRUE);
+ gSnapshotFloaterView->setVisible(TRUE);
+ gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
+
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+ impl->updateLayout(this);
+
+ LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory");
+ snapshot_panel->onOpen(LLSD());
+ postPanelSwitch();
+
+}
+
+void LLFloaterOutfitSnapshot::onExtendFloater()
+{
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot"));
+}
+
+// static
+void LLFloaterOutfitSnapshot::update()
+{
+ LLFloaterOutfitSnapshot* inst = findInstance();
+ if (inst != NULL)
+ {
+ inst->impl->updateLivePreview();
+ }
+}
+
+
+// static
+LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::findInstance()
+{
+ return LLFloaterReg::findTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot");
+}
+
+// static
+LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot");
+}
+
+// virtual
+void LLFloaterOutfitSnapshot::saveTexture()
+{
+ LL_DEBUGS() << "saveTexture" << LL_ENDL;
+
+ LLSnapshotLivePreview* previewp = getPreviewView();
+ if (!previewp)
+ {
+ llassert(previewp != NULL);
+ return;
+ }
+
+ if (mOutfitGallery)
+ {
+ mOutfitGallery->onBeforeOutfitSnapshotSave();
+ }
+ previewp->saveTexture(TRUE, getOutfitID().asString());
+ if (mOutfitGallery)
+ {
+ mOutfitGallery->onAfterOutfitSnapshotSave();
+ }
+ closeFloater();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLOutfitSnapshotFloaterView
+///----------------------------------------------------------------------------
+
+LLOutfitSnapshotFloaterView::LLOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p)
+{
+}
+
+LLOutfitSnapshotFloaterView::~LLOutfitSnapshotFloaterView()
+{
+}
diff --git a/indra/newview/llfloateroutfitsnapshot.h b/indra/newview/llfloateroutfitsnapshot.h
new file mode 100644
index 0000000000..bee386ec63
--- /dev/null
+++ b/indra/newview/llfloateroutfitsnapshot.h
@@ -0,0 +1,123 @@
+/**
+ * @file llfloateroutfitsnapshot.h
+ * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2016, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATEROUTFITSNAPSHOT_H
+#define LL_LLFLOATEROUTFITSNAPSHOT_H
+
+#include "llfloater.h"
+#include "llfloatersnapshot.h"
+#include "lloutfitgallery.h"
+#include "llsnapshotlivepreview.h"
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot
+///----------------------------------------------------------------------------
+
+class LLFloaterOutfitSnapshot : public LLFloaterSnapshotBase
+{
+ LOG_CLASS(LLFloaterOutfitSnapshot);
+
+public:
+
+ LLFloaterOutfitSnapshot(const LLSD& key);
+ /*virtual*/ ~LLFloaterOutfitSnapshot();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ static void update();
+
+ void onExtendFloater();
+
+ static LLFloaterOutfitSnapshot* getInstance();
+ static LLFloaterOutfitSnapshot* findInstance();
+ /*virtual*/ void saveTexture();
+
+ const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+
+ void setOutfitID(LLUUID id) { mOutfitID = id; }
+ LLUUID getOutfitID() { return mOutfitID; }
+ void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; }
+
+ class Impl;
+ friend class Impl;
+private:
+
+ LLUUID mOutfitID;
+ LLOutfitGallery* mOutfitGallery;
+};
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterOutfitSnapshot::Impl
+///----------------------------------------------------------------------------
+
+class LLFloaterOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
+{
+ LOG_CLASS(LLFloaterOutfitSnapshot::Impl);
+public:
+ Impl(LLFloaterSnapshotBase* floater)
+ : LLFloaterSnapshotBase::ImplBase(floater)
+ {}
+ ~Impl()
+ {}
+ void updateResolution(void* data);
+
+ static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status);
+
+ /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true);
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater);
+ /*virtual*/ std::string getSnapshotPanelPrefix();
+
+ /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater);
+
+private:
+ /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater);
+ /*virtual*/ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
+};
+
+///----------------------------------------------------------------------------
+/// Class LLOutfitSnapshotFloaterView
+///----------------------------------------------------------------------------
+
+class LLOutfitSnapshotFloaterView : public LLFloaterView
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLFloaterView::Params>
+ {
+ };
+
+protected:
+ LLOutfitSnapshotFloaterView(const Params& p);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLOutfitSnapshotFloaterView();
+};
+
+extern LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView;
+
+#endif // LL_LLFLOATEROUTFITSNAPSHOT_H
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index 31245db344..dfe462c8d1 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -72,6 +72,8 @@ struct LLGiveMoneyInfo
mFloater(floater), mAmount(amount){}
};
+typedef boost::shared_ptr<LLGiveMoneyInfo> give_money_ptr;
+
///----------------------------------------------------------------------------
/// Class LLFloaterPay
///----------------------------------------------------------------------------
@@ -94,18 +96,18 @@ public:
bool is_group);
static bool payConfirmationCallback(const LLSD& notification,
const LLSD& response,
- LLGiveMoneyInfo* info);
+ give_money_ptr info);
private:
static void onCancel(void* data);
static void onKeystroke(LLLineEditor* editor, void* data);
- static void onGive(void* data);
+ static void onGive(give_money_ptr info);
void give(S32 amount);
static void processPayPriceReply(LLMessageSystem* msg, void **userdata);
void finishPayUI(const LLUUID& target_id, BOOL is_group);
protected:
- std::vector<LLGiveMoneyInfo*> mCallbackData;
+ std::vector<give_money_ptr> mCallbackData;
money_callback mCallback;
LLTextBox* mObjectNameText;
LLUUID mTargetUUID;
@@ -113,7 +115,7 @@ protected:
BOOL mHaveName;
LLButton* mQuickPayButton[MAX_PAY_BUTTONS];
- LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS];
+ give_money_ptr mQuickPayInfo[MAX_PAY_BUTTONS];
LLSafeHandle<LLObjectSelection> mObjectSelection;
};
@@ -136,7 +138,11 @@ LLFloaterPay::LLFloaterPay(const LLSD& key)
// Destroys the object
LLFloaterPay::~LLFloaterPay()
{
- std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer());
+ std::vector<give_money_ptr>::iterator iter;
+ for (iter = mCallbackData.begin(); iter != mCallbackData.end(); ++iter)
+ {
+ (*iter)->mFloater = NULL;
+ }
mCallbackData.clear();
// Name callbacks will be automatically disconnected since LLFloater is trackable
@@ -148,40 +154,40 @@ BOOL LLFloaterPay::postBuild()
{
S32 i = 0;
- LLGiveMoneyInfo* info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0);
+ give_money_ptr info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0));
mCallbackData.push_back(info);
- childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 1", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 1")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 1");
mQuickPayInfo[i] = info;
++i;
- info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1));
mCallbackData.push_back(info);
- childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 5", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 5")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 5");
mQuickPayInfo[i] = info;
++i;
- info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2));
mCallbackData.push_back(info);
- childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 10", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 10")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 10");
mQuickPayInfo[i] = info;
++i;
- info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3));
mCallbackData.push_back(info);
- childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
+ childSetAction("fastpay 20", boost::bind(LLFloaterPay::onGive, info));
getChildView("fastpay 20")->setVisible(FALSE);
mQuickPayButton[i] = getChild<LLButton>("fastpay 20");
@@ -195,10 +201,10 @@ BOOL LLFloaterPay::postBuild()
getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this);
getChild<LLLineEditor>("amount")->setPrevalidate(LLTextValidate::validateNonNegativeS32);
- info = new LLGiveMoneyInfo(this, 0);
+ info = give_money_ptr(new LLGiveMoneyInfo(this, 0));
mCallbackData.push_back(info);
- childSetAction("pay btn",&LLFloaterPay::onGive,info);
+ childSetAction("pay btn", boost::bind(LLFloaterPay::onGive, info));
setDefaultBtn("pay btn");
getChildView("pay btn")->setVisible(FALSE);
getChildView("pay btn")->setEnabled(FALSE);
@@ -415,9 +421,9 @@ void LLFloaterPay::payDirectly(money_callback callback,
floater->finishPayUI(target_id, is_group);
}
-bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, LLGiveMoneyInfo* info)
+bool LLFloaterPay::payConfirmationCallback(const LLSD& notification, const LLSD& response, give_money_ptr info)
{
- if (!info || !info->mFloater)
+ if (!info.get() || !info->mFloater)
{
return false;
}
@@ -479,54 +485,61 @@ void LLFloaterPay::onKeystroke(LLLineEditor*, void* data)
}
// static
-void LLFloaterPay::onGive(void* data)
+void LLFloaterPay::onGive(give_money_ptr info)
{
- LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data);
- LLFloaterPay* floater = info->mFloater;
- if(info && floater)
- {
- S32 amount = info->mAmount;
- if(amount == 0)
- {
- amount = atoi(floater->getChild<LLUICtrl>("amount")->getValue().asString().c_str());
- }
- if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount)
- {
- LLUUID payee_id = LLUUID::null;
- BOOL is_group = false;
- if (floater->mObjectSelection.notNull())
- {
- LLSelectNode* node = floater->mObjectSelection->getFirstRootNode();
- if (node)
- {
- node->mPermissions->getOwnership(payee_id, is_group);
- }
- else
- {
- // object no longer exists
- LLNotificationsUtil::add("PayObjectFailed");
- floater->closeFloater();
- return;
- }
- }
- else
- {
- is_group = floater->mTargetIsGroup;
- payee_id = floater->mTargetUUID;
- }
-
- LLSD args;
- args["TARGET"] = LLSLURL( is_group ? "group" : "agent", payee_id, "completename").getSLURLString();
- args["AMOUNT"] = amount;
-
- LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info));
- }
- else
- {
- floater->give(amount);
- floater->closeFloater();
- }
- }
+ if (!info.get() || !info->mFloater)
+ {
+ return;
+ }
+
+ LLFloaterPay* floater = info->mFloater;
+ S32 amount = info->mAmount;
+ if (amount == 0)
+ {
+ LLUICtrl* text_field = floater->getChild<LLUICtrl>("amount");
+ if (!text_field)
+ {
+ return;
+ }
+ amount = atoi(text_field->getValue().asString().c_str());
+ }
+
+ if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount)
+ {
+ LLUUID payee_id = LLUUID::null;
+ BOOL is_group = false;
+ if (floater->mObjectSelection.notNull())
+ {
+ LLSelectNode* node = floater->mObjectSelection->getFirstRootNode();
+ if (node)
+ {
+ node->mPermissions->getOwnership(payee_id, is_group);
+ }
+ else
+ {
+ // object no longer exists
+ LLNotificationsUtil::add("PayObjectFailed");
+ floater->closeFloater();
+ return;
+ }
+ }
+ else
+ {
+ is_group = floater->mTargetIsGroup;
+ payee_id = floater->mTargetUUID;
+ }
+
+ LLSD args;
+ args["TARGET"] = LLSLURL(is_group ? "group" : "agent", payee_id, "completename").getSLURLString();
+ args["AMOUNT"] = amount;
+
+ LLNotificationsUtil::add("PayConfirmation", args, LLSD(), boost::bind(&LLFloaterPay::payConfirmationCallback, _1, _2, info));
+ }
+ else
+ {
+ floater->give(amount);
+ floater->closeFloater();
+ }
}
void LLFloaterPay::give(S32 amount)
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 36bdcf4d89..75f5e87a2b 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1232,6 +1232,9 @@ void LLFloaterPreference::refreshEnabledState()
(ctrl_wind_light->get()) ? TRUE : FALSE;
ctrl_deferred->setEnabled(enabled);
+
+ // Cannot have floater active until caps have been received
+ getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true);
}
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
@@ -1369,9 +1372,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
disableUnavailableSettings();
getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess());
-
- // Cannot have floater active until caps have been received
- getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true);
}
// static
@@ -1411,7 +1411,7 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
else
{
// This is the inverse of the calculation in updateMaxComplexity
- indirect_max_arc = (U32)((log(max_arc) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE) + MIN_INDIRECT_ARC_LIMIT;
+ indirect_max_arc = (U32)ll_round(((log(F32(max_arc)) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE)) + MIN_INDIRECT_ARC_LIMIT;
}
gSavedSettings.setU32("IndirectMaxComplexity", indirect_max_arc);
}
@@ -1930,7 +1930,7 @@ void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* valu
{
// if this is changed, the inverse calculation in setIndirectMaxArc
// must be changed to match
- max_arc = (U32)exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT)));
+ max_arc = (U32)ll_round(exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT))));
}
gSavedSettings.setU32("RenderAvatarMaxComplexity", (U32)max_arc);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index ed6f4ede9f..a6ce0ba678 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -192,7 +192,6 @@ BOOL LLFloaterReporter::postBuild()
mOwnerName = LLStringUtil::null;
getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
- getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE);
mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
@@ -246,8 +245,6 @@ LLFloaterReporter::~LLFloaterReporter()
// virtual
void LLFloaterReporter::draw()
{
- getChildView("screen_check")->setEnabled(TRUE );
-
LLFloater::draw();
}
@@ -255,7 +252,6 @@ void LLFloaterReporter::enableControls(BOOL enable)
{
getChildView("category_combo")->setEnabled(enable);
getChildView("chat_check")->setEnabled(enable);
- getChildView("screen_check")->setEnabled(enable);
getChildView("screenshot")->setEnabled(FALSE);
getChildView("pick_btn")->setEnabled(enable);
getChildView("summary_edit")->setEnabled(enable);
@@ -448,23 +444,15 @@ void LLFloaterReporter::onClickSend(void *userdata)
if(!url.empty() || !sshot_url.empty())
{
self->sendReportViaCaps(url, sshot_url, self->gatherReport());
+ LLNotificationsUtil::add("HelpReportAbuseConfirm");
self->closeFloater();
}
else
{
- if(self->getChild<LLUICtrl>("screen_check")->getValue())
- {
- self->getChildView("send_btn")->setEnabled(FALSE);
- self->getChildView("cancel_btn")->setEnabled(FALSE);
- // the callback from uploading the image calls sendReportViaLegacy()
- self->uploadImage();
- }
- else
- {
- self->sendReportViaLegacy(self->gatherReport());
- LLUploadDialog::modalUploadFinished();
- self->closeFloater();
- }
+ self->getChildView("send_btn")->setEnabled(FALSE);
+ self->getChildView("cancel_btn")->setEnabled(FALSE);
+ // the callback from uploading the image calls sendReportViaLegacy()
+ self->uploadImage();
}
}
}
@@ -713,10 +701,7 @@ LLSD LLFloaterReporter::gatherReport()
// only send a screenshot ID if we're asked to and the email is
// going to LL - Estate Owners cannot see the screenshot asset
LLUUID screenshot_id = LLUUID::null;
- if (getChild<LLUICtrl>("screen_check")->getValue())
- {
- screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
- };
+ screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
LLSD report = LLSD::emptyMap();
report["report-type"] = (U8) mReportType;
@@ -770,7 +755,7 @@ void LLFloaterReporter::finishedARPost(const LLSD &)
void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
{
- if(getChild<LLUICtrl>("screen_check")->getValue().asBoolean() && !sshot_url.empty())
+ if(!sshot_url.empty())
{
// try to upload screenshot
LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType));
@@ -885,6 +870,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
self->mScreenID = uuid;
LL_INFOS() << "Got screen shot " << uuid << LL_ENDL;
self->sendReportViaLegacy(self->gatherReport());
+ LLNotificationsUtil::add("HelpReportAbuseConfirm");
self->closeFloater();
}
}
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 7b8fc5b35b..eae16b9f03 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -660,6 +660,8 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild()
{
return FALSE;
}
+ list->setCommitCallback(boost::bind(&LLPanelScriptLimitsRegionMemory::checkButtonsEnabled, this));
+ checkButtonsEnabled();
//set all columns to resizable mode even if some columns will be empty
for(S32 column = 0; column < list->getNumColumns(); column++)
@@ -750,6 +752,14 @@ void LLPanelScriptLimitsRegionMemory::clearList()
getChild<LLUICtrl>("parcels_listed")->setValue(LLSD(msg_empty_string));
mObjectListItems.clear();
+ checkButtonsEnabled();
+}
+
+void LLPanelScriptLimitsRegionMemory::checkButtonsEnabled()
+{
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
+ getChild<LLButton>("highlight_btn")->setEnabled(list->getNumSelected() > 0);
+ getChild<LLButton>("return_btn")->setEnabled(list->getNumSelected() > 0);
}
// static
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index e3cbbd185f..2ac3862b4f 100644
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -113,6 +113,7 @@ public:
void showBeacon();
void returnObjectsFromParcel(S32 local_id);
void returnObjects();
+ void checkButtonsEnabled();
private:
void onNameCache(const LLUUID& id,
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 0cb37dabe7..b139e5daf5 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -257,7 +257,6 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
static std::string badgeOK("badge_ok.j2c");
static std::string badgeNote("badge_note.j2c");
static std::string badgeWarn("badge_warn.j2c");
- static std::string badgeError("badge_error.j2c");
std::string badgeName;
switch (badge)
@@ -266,7 +265,7 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
case BADGE_OK: badgeName = badgeOK; break;
case BADGE_NOTE: badgeName = badgeNote; break;
case BADGE_WARN: badgeName = badgeWarn; break;
- case BADGE_ERROR: badgeName = badgeError; break;
+ case BADGE_ERROR: badgeName = badgeWarn; break;
}
getChild<LLUICtrl>(id)->setValue(badgeName);
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index b906671c7f..b5ba64716d 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2016, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -28,7 +28,6 @@
#include "llfloatersnapshot.h"
-#include "llagent.h"
#include "llfacebookconnect.h"
#include "llfloaterreg.h"
#include "llfloaterfacebook.h"
@@ -51,7 +50,6 @@
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
-LLUICtrl* LLFloaterSnapshot::sThumbnailPlaceholder = NULL;
LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
@@ -61,92 +59,8 @@ const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterSnapshot::Impl
-///----------------------------------------------------------------------------
-
-class LLFloaterSnapshot::Impl
-{
- LOG_CLASS(LLFloaterSnapshot::Impl);
-public:
- typedef enum e_status
- {
- STATUS_READY,
- STATUS_WORKING,
- STATUS_FINISHED
- } EStatus;
-
- Impl()
- : mAvatarPauseHandles(),
- mLastToolset(NULL),
- mAspectRatioCheckOff(false),
- mNeedRefresh(false),
- mStatus(STATUS_READY)
- {
- }
- ~Impl()
- {
- //unpause avatars
- mAvatarPauseHandles.clear();
-
- }
- static void onClickNewSnapshot(void* data);
- static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
- static void onClickFilter(LLUICtrl *ctrl, void* data);
- //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data);
- static void onClickUICheck(LLUICtrl *ctrl, void* data);
- static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
- static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked);
- static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
- static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
- static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
- static void onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val);
- static void onImageFormatChange(LLFloaterSnapshot* view);
- static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h);
- static void onSnapshotUploadFinished(bool status);
- static void onSendingPostcardFinished(bool status);
- static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
- static void setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height) ;
- static void updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed);
-
- static LLPanelSnapshot* getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found = true);
- static LLSnapshotLivePreview::ESnapshotType getActiveSnapshotType(LLFloaterSnapshot* floater);
- static LLFloaterSnapshot::ESnapshotFormat getImageFormat(LLFloaterSnapshot* floater);
- static LLSpinCtrl* getWidthSpinner(LLFloaterSnapshot* floater);
- static LLSpinCtrl* getHeightSpinner(LLFloaterSnapshot* floater);
- static void enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable);
- static void setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked);
-
- static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
- static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);
- static void updateControls(LLFloaterSnapshot* floater);
- static void updateLayout(LLFloaterSnapshot* floater);
- static void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
- EStatus getStatus() const { return mStatus; }
- static void setNeedRefresh(LLFloaterSnapshot* floater, bool need);
-
-private:
- static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
- static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);
- static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
- static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ;
- static void setWorking(LLFloaterSnapshot* floater, bool working);
- static void setFinished(LLFloaterSnapshot* floater, bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
-
-
-public:
- std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
-
- LLToolset* mLastToolset;
- LLHandle<LLView> mPreviewHandle;
- bool mAspectRatioCheckOff ;
- bool mNeedRefresh;
- EStatus mStatus;
-};
-
-// static
-LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found)
+// virtual
+LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found)
{
LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel());
@@ -157,58 +71,40 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floa
return active_panel;
}
-// static
-LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater)
+// virtual
+LLSnapshotModel::ESnapshotType LLFloaterSnapshotBase::ImplBase::getActiveSnapshotType(LLFloaterSnapshotBase* floater)
{
- LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB;
- std::string name;
LLPanelSnapshot* spanel = getActivePanel(floater);
- if (spanel)
- {
- name = spanel->getName();
- }
-
- if (name == "panel_snapshot_postcard")
- {
- type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD;
- }
- else if (name == "panel_snapshot_inventory")
- {
- type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE;
- }
- else if (name == "panel_snapshot_local")
- {
- type = LLSnapshotLivePreview::SNAPSHOT_LOCAL;
- }
-
- return type;
+ //return type;
+ if (spanel)
+ {
+ return spanel->getSnapshotType();
+ }
+ return LLSnapshotModel::SNAPSHOT_WEB;
}
-// static
-LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater)
+// virtual
+LLSnapshotModel::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
// FIXME: if the default is not PNG, profile uploads may fail.
- return active_panel ? active_panel->getImageFormat() : LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
+ return active_panel ? active_panel->getImageFormat() : LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
-// static
-LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater)
+LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshotBase* floater)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width");
}
-// static
-LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater)
+LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshotBase* floater)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
return active_panel ? active_panel->getHeightSpinner() : floater->getChild<LLSpinCtrl>("snapshot_height");
}
-// static
-void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable)
+void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
if (active_panel)
@@ -217,8 +113,7 @@ void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* float
}
}
-// static
-void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* floater, BOOL checked)
+void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked)
{
LLPanelSnapshot* active_panel = getActivePanel(floater);
if (active_panel)
@@ -227,40 +122,41 @@ void LLFloaterSnapshot::Impl::setAspectRatioCheckboxValue(LLFloaterSnapshot* flo
}
}
-// static
-LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
+LLSnapshotLivePreview* LLFloaterSnapshotBase::getPreviewView()
{
- LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get();
+ return impl->getPreviewView();
+}
+
+LLSnapshotLivePreview* LLFloaterSnapshotBase::ImplBase::getPreviewView()
+{
+ LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
return previewp;
}
-// static
-LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater)
+// virtual
+LLSnapshotModel::ESnapshotLayerType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
{
- LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
LLSD value = floater->getChild<LLUICtrl>("layer_types")->getValue();
const std::string id = value.asString();
if (id == "colors")
- type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
else if (id == "depth")
- type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
+ type = LLSnapshotModel::SNAPSHOT_TYPE_DEPTH;
return type;
}
-// static
-void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname)
+void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname)
{
LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
combo->setVisible(TRUE);
updateResolution(combo, floater, FALSE); // to sync spinners with combo
}
-//static
-void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
+//virtual
+void LLFloaterSnapshotBase::ImplBase::updateLayout(LLFloaterSnapshotBase* floaterp)
{
- LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
-
- BOOL advanced = gSavedSettings.getBOOL("AdvanceSnapshot");
+ LLSnapshotLivePreview* previewp = getPreviewView();
//BD - Automatically calculate the size of our snapshot window to enlarge
// the snapshot preview to its maximum size, this is especially helpfull
@@ -277,16 +173,16 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
}
S32 floater_width = 224.f;
- if(advanced)
+ if(mAdvanced)
{
floater_width = floater_width + panel_width;
}
LLUICtrl* thumbnail_placeholder = floaterp->getChild<LLUICtrl>("thumbnail_placeholder");
- thumbnail_placeholder->setVisible(advanced);
+ thumbnail_placeholder->setVisible(mAdvanced);
thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight());
- floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(advanced);
- floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(advanced);
+ floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(mAdvanced);
+ floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(mAdvanced);
if(!floaterp->isMinimized())
{
floaterp->reshape(floater_width, floaterp->getRect().getHeight());
@@ -316,7 +212,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
iter != LLCharacter::sInstances.end(); ++iter)
{
avatarp = *iter;
- floaterp->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
+ floaterp->impl->mAvatarPauseHandles.push_back(avatarp->requestPause());
}
// freeze everything else
@@ -324,7 +220,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)
{
- floaterp->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
+ floaterp->impl->mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);
}
}
@@ -340,15 +236,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
}
//RN: thaw all avatars
- floaterp->impl.mAvatarPauseHandles.clear();
+ floaterp->impl->mAvatarPauseHandles.clear();
// thaw everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
// restore last tool (e.g. pie menu, etc)
- if (floaterp->impl.mLastToolset)
+ if (floaterp->impl->mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl->mLastToolset);
}
}
}
@@ -359,15 +255,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
// The basic pattern for programmatically changing the GUI settings is to first set the
// appropriate saved settings and then call this method to sync the GUI with them.
// FIXME: The above comment seems obsolete now.
-// static
-void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
+// virtual
+void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
{
- LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater);
- ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
- LLViewerWindow::ESnapshotType layer_type = getLayerType(floater);
+ LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater);
+ LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater);
floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat"));
- floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
+ floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotModel::SNAPSHOT_LOCAL);
LLPanelSnapshot* active_panel = getActivePanel(floater);
if (active_panel)
@@ -381,7 +277,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
S32 w = gViewerWindow->getWindowWidthRaw();
LL_DEBUGS() << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << LL_ENDL;
width_ctrl->setValue(w);
- if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
width_ctrl->setIncrement(w >> 1);
}
@@ -391,7 +287,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
S32 h = gViewerWindow->getWindowHeightRaw();
LL_DEBUGS() << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << LL_ENDL;
height_ctrl->setValue(h);
- if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(floater) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
height_ctrl->setIncrement(h >> 1);
}
@@ -423,7 +319,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
}
}
- LLSnapshotLivePreview* previewp = getPreviewView(floater);
+ LLSnapshotLivePreview* previewp = getPreviewView();
BOOL got_bytes = previewp && previewp->getDataSize() > 0;
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
@@ -448,35 +344,35 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
floater->getChild<LLUICtrl>("file_size_label")->setColor(
- shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD
+ shot_type == LLSnapshotModel::SNAPSHOT_POSTCARD
&& got_bytes
&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
// Update the width and height spinners based on the corresponding resolution combos. (?)
switch(shot_type)
{
- case LLSnapshotLivePreview::SNAPSHOT_WEB:
- layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ case LLSnapshotModel::SNAPSHOT_WEB:
+ layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "profile_size_combo");
break;
- case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
- layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ case LLSnapshotModel::SNAPSHOT_POSTCARD:
+ layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "postcard_size_combo");
break;
- case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
- layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
+ case LLSnapshotModel::SNAPSHOT_TEXTURE:
+ layer_type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
floater->getChild<LLUICtrl>("layer_types")->setValue("colors");
setResolution(floater, "texture_size_combo");
break;
- case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
+ case LLSnapshotModel::SNAPSHOT_LOCAL:
setResolution(floater, "local_size_combo");
break;
default:
break;
}
- setAspectRatioCheckboxValue(floater, !floater->impl.mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot"));
+ setAspectRatioCheckboxValue(floater, !floater->impl->mAspectRatioCheckOff && gSavedSettings.getBOOL("KeepAspectForSnapshot"));
if (previewp)
{
@@ -495,33 +391,32 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
LL_DEBUGS() << "finished updating controls" << LL_ENDL;
}
-// static
-void LLFloaterSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
+//virtual
+void LLFloaterSnapshotBase::ImplBase::setStatus(EStatus status, bool ok, const std::string& msg)
{
- LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();
switch (status)
{
case STATUS_READY:
- setWorking(floater, false);
- setFinished(floater, false);
+ setWorking(false);
+ setFinished(false);
break;
case STATUS_WORKING:
- setWorking(floater, true);
- setFinished(floater, false);
+ setWorking(true);
+ setFinished(false);
break;
case STATUS_FINISHED:
- setWorking(floater, false);
- setFinished(floater, true, ok, msg);
+ setWorking(false);
+ setFinished(true, ok, msg);
break;
}
- floater->impl.mStatus = status;
+ mStatus = status;
}
-// static
-void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool need)
+// virtual
+void LLFloaterSnapshotBase::ImplBase::setNeedRefresh(bool need)
{
- if (!floater) return;
+ if (!mFloater) return;
// Don't display the "Refresh to save" message if we're in auto-refresh mode.
if (gSavedSettings.getBOOL("AutoSnapshot"))
@@ -529,12 +424,12 @@ void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool ne
need = false;
}
- floater->mRefreshLabel->setVisible(need);
- floater->impl.mNeedRefresh = need;
+ mFloater->setRefreshLabelVisible(need);
+ mNeedRefresh = need;
}
-// static
-void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
+// virtual
+void LLFloaterSnapshotBase::ImplBase::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
{
if (previewp)
{
@@ -545,43 +440,43 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp,
}
// static
-void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickNewSnapshot(void* data)
{
- LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data);
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
- if (previewp && view)
+ LLFloaterSnapshotBase* floater = (LLFloaterSnapshotBase *)data;
+ LLSnapshotLivePreview* previewp = floater->getPreviewView();
+ if (previewp)
{
- view->impl.setStatus(Impl::STATUS_READY);
+ floater->impl->setStatus(ImplBase::STATUS_READY);
LL_DEBUGS() << "updating snapshot" << LL_ENDL;
previewp->mForceUpdateSnapshot = TRUE;
}
}
// static
-void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickAutoSnap(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
gSavedSettings.setBOOL( "AutoSnapshot", check->get() );
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+ LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;
if (view)
{
- checkAutoSnapshot(getPreviewView(view));
- updateControls(view);
+ view->impl->checkAutoSnapshot(view->getPreviewView());
+ view->impl->updateControls(view);
}
}
// static
-void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickFilter(LLUICtrl *ctrl, void* data)
{
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+ LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;
if (view)
{
- updateControls(view);
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ view->impl->updateControls(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if (previewp)
{
- checkAutoSnapshot(previewp);
+ view->impl->checkAutoSnapshot(previewp);
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
LLComboBox* filterbox = static_cast<LLComboBox *>(view->getChild<LLComboBox>("filters_combobox"));
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
@@ -592,7 +487,7 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
}
// static
-void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickUICheck(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() );
@@ -600,17 +495,17 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
if (view)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if(previewp)
{
previewp->updateSnapshot(TRUE, TRUE);
}
- updateControls(view);
+ view->impl->updateControls(view);
}
}
// static
-void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickHUDCheck(LLUICtrl *ctrl, void* data)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() );
@@ -618,17 +513,16 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
if (view)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if(previewp)
{
previewp->updateSnapshot(TRUE, TRUE);
}
- updateControls(view);
+ view->impl->updateControls(view);
}
}
-// static
-void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked)
+void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked)
{
gSavedSettings.setBOOL("KeepAspectForSnapshot", checked);
@@ -641,7 +535,7 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL
combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index
}
- LLSnapshotLivePreview* previewp = getPreviewView(view) ;
+ LLSnapshotLivePreview* previewp = getPreviewView() ;
if(previewp)
{
previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
@@ -659,11 +553,11 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL
}
// static
-void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
{
LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLFloaterSnapshotBase *view = (LLFloaterSnapshotBase *)data;
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if (!view || !check_box || !previewp)
{
@@ -677,16 +571,15 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
previewp->prepareFreezeFrame();
}
- updateLayout(view);
+ view->impl->updateLayout(view);
}
-// static
-void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index)
+void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshotBase *view, S32 index)
{
- LLSnapshotLivePreview *previewp = getPreviewView(view) ;
+ LLSnapshotLivePreview *previewp = getPreviewView() ;
// Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here
- if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))
+ if (LLSnapshotModel::SNAPSHOT_TEXTURE == getActiveSnapshotType(view))
{
previewp->mKeepAspectRatio = FALSE ;
return ;
@@ -710,7 +603,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
keep_aspect = FALSE;
}
- view->impl.mAspectRatioCheckOff = !enable_cb;
+ view->impl->mAspectRatioCheckOff = !enable_cb;
if (previewp)
{
@@ -719,51 +612,55 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
}
// Show/hide upload progress indicators.
-// static
-void LLFloaterSnapshot::Impl::setWorking(LLFloaterSnapshot* floater, bool working)
+void LLFloaterSnapshotBase::ImplBase::setWorking(bool working)
{
- LLUICtrl* working_lbl = floater->getChild<LLUICtrl>("working_lbl");
+ LLUICtrl* working_lbl = mFloater->getChild<LLUICtrl>("working_lbl");
working_lbl->setVisible(working);
- floater->getChild<LLUICtrl>("working_indicator")->setVisible(working);
+ mFloater->getChild<LLUICtrl>("working_indicator")->setVisible(working);
if (working)
{
- const std::string panel_name = getActivePanel(floater, false)->getName();
- const std::string prefix = panel_name.substr(std::string("panel_snapshot_").size());
- std::string progress_text = floater->getString(prefix + "_" + "progress_str");
+ const std::string panel_name = getActivePanel(mFloater, false)->getName();
+ const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size());
+ std::string progress_text = mFloater->getString(prefix + "_" + "progress_str");
working_lbl->setValue(progress_text);
}
// All controls should be disabled while posting.
- floater->setCtrlsEnabled(!working);
- LLPanelSnapshot* active_panel = getActivePanel(floater);
+ mFloater->setCtrlsEnabled(!working);
+ LLPanelSnapshot* active_panel = getActivePanel(mFloater);
if (active_panel)
{
active_panel->enableControls(!working);
}
}
+//virtual
+std::string LLFloaterSnapshot::Impl::getSnapshotPanelPrefix()
+{
+ return "panel_snapshot_";
+}
+
// Show/hide upload status message.
-// static
-void LLFloaterSnapshot::Impl::setFinished(LLFloaterSnapshot* floater, bool finished, bool ok, const std::string& msg)
+// virtual
+void LLFloaterSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg)
{
- floater->mSucceessLblPanel->setVisible(finished && ok);
- floater->mFailureLblPanel->setVisible(finished && !ok);
+ mFloater->setSuccessLabelPanelVisible(finished && ok);
+ mFloater->setFailureLabelPanelVisible(finished && !ok);
if (finished)
{
- LLUICtrl* finished_lbl = floater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
- std::string result_text = floater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
+ LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl");
+ std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str"));
finished_lbl->setValue(result_text);
- LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
+ LLSideTrayPanelContainer* panel_container = mFloater->getChild<LLSideTrayPanelContainer>("panel_container");
panel_container->openPreviousPanel();
panel_container->getCurrentPanel()->onOpen(LLSD());
}
}
// Apply a new resolution selected from the given combobox.
-// static
void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update)
{
LLComboBox* combobox = (LLComboBox*)ctrl;
@@ -783,7 +680,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
S32 width = sdres[0];
S32 height = sdres[1];
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && combobox->getCurrentIndex() >= 0)
{
S32 original_width = 0 , original_height = 0 ;
@@ -813,7 +710,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
new_height = spanel->getTypedPreviewHeight();
// Limit custom size for inventory snapshots to 512x512 px.
- if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
new_width = llmin(new_width, MAX_TEXTURE_SIZE);
new_height = llmin(new_height, MAX_TEXTURE_SIZE);
@@ -851,7 +748,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
{
getWidthSpinner(view)->setValue(width);
getHeightSpinner(view)->setValue(height);
- if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
getWidthSpinner(view)->setIncrement(width >> 1);
getHeightSpinner(view)->setIncrement(height >> 1);
@@ -865,7 +762,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
// hide old preview as the aspect ratio could be wrong
checkAutoSnapshot(previewp, FALSE);
LL_DEBUGS() << "updating thumbnail" << LL_ENDL;
- getPreviewView(view)->updateSnapshot(TRUE);
+ getPreviewView()->updateSnapshot(TRUE);
if(do_update)
{
LL_DEBUGS() << "Will update controls" << LL_ENDL;
@@ -884,40 +781,37 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)
if (view)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = view->getPreviewView();
if (previewp)
{
- previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex());
+ previewp->setSnapshotBufferType((LLSnapshotModel::ESnapshotLayerType)combobox->getCurrentIndex());
}
- checkAutoSnapshot(previewp, TRUE);
+ view->impl->checkAutoSnapshot(previewp, TRUE);
}
}
-// static
-void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val)
+void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val)
{
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
previewp->setSnapshotQuality(quality_val);
}
}
-// static
-void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view)
+void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshotBase* view)
{
if (view)
{
gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));
LL_DEBUGS() << "image format changed, updating snapshot" << LL_ENDL;
- getPreviewView(view)->updateSnapshot(TRUE);
+ getPreviewView()->updateSnapshot(TRUE);
updateControls(view);
}
}
// Sets the named size combo to "custom" mode.
-// static
-void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname)
+void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshotBase* floater, const std::string& comboname)
{
LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index
@@ -925,7 +819,6 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s
}
// Update supplied width and height according to the constrain proportions flag; limit them by max_val.
-//static
BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)
{
S32 w = width ;
@@ -970,20 +863,18 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3
return (w != width || h != height) ;
}
-//static
-void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshot *view, S32 width, S32 height)
+void LLFloaterSnapshot::Impl::setImageSizeSpinnersValues(LLFloaterSnapshotBase* view, S32 width, S32 height)
{
getWidthSpinner(view)->forceSetValue(width);
getHeightSpinner(view)->forceSetValue(height);
- if (getActiveSnapshotType(view) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
+ if (getActiveSnapshotType(view) == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
getWidthSpinner(view)->setIncrement(width >> 1);
getHeightSpinner(view)->setIncrement(height >> 1);
}
}
-// static
-void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed)
+void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed)
{
getWidthSpinner(view)->resetDirty();
getHeightSpinner(view)->resetDirty();
@@ -993,13 +884,12 @@ void LLFloaterSnapshot::Impl::updateSpinners(LLFloaterSnapshot* view, LLSnapshot
}
}
-// static
-void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h)
+void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h)
{
LL_DEBUGS() << "applyCustomResolution(" << w << ", " << h << ")" << LL_ENDL;
if (!view) return;
- LLSnapshotLivePreview* previewp = getPreviewView(view);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
S32 curw,curh;
@@ -1023,90 +913,104 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32
}
// static
-void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(bool status)
+void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status)
{
- setStatus(STATUS_FINISHED, status, "profile");
+ floater->impl->setStatus(STATUS_FINISHED, status, "profile");
}
-
// static
-void LLFloaterSnapshot::Impl::onSendingPostcardFinished(bool status)
+void LLFloaterSnapshot::Impl::onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status)
{
- setStatus(STATUS_FINISHED, status, "postcard");
+ floater->impl->setStatus(STATUS_FINISHED, status, "postcard");
}
///----------------------------------------------------------------------------
-/// Class LLFloaterSnapshot
+/// Class LLFloaterSnapshotBase
///----------------------------------------------------------------------------
// Default constructor
-LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
- : LLFloater(key),
+LLFloaterSnapshotBase::LLFloaterSnapshotBase(const LLSD& key)
+ : LLFloater(key),
mRefreshBtn(NULL),
mRefreshLabel(NULL),
mSucceessLblPanel(NULL),
- mFailureLblPanel(NULL),
- impl (*(new Impl))
+ mFailureLblPanel(NULL)
{
}
-// Destroys the object
-LLFloaterSnapshot::~LLFloaterSnapshot()
+LLFloaterSnapshotBase::~LLFloaterSnapshotBase()
{
- if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die();
+ if (impl->mPreviewHandle.get()) impl->mPreviewHandle.get()->die();
//unfreeze everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
- if (impl.mLastToolset)
+ if (impl->mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset);
}
- delete &impl;
+ delete impl;
}
+///----------------------------------------------------------------------------
+/// Class LLFloaterSnapshot
+///----------------------------------------------------------------------------
+// Default constructor
+LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
+ : LLFloaterSnapshotBase(key)
+{
+ impl = new Impl(this);
+}
+
+LLFloaterSnapshot::~LLFloaterSnapshot()
+{
+}
+
+// virtual
BOOL LLFloaterSnapshot::postBuild()
{
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
- childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this);
+ childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
mRefreshLabel = getChild<LLUICtrl>("refresh_lbl");
mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
- childSetCommitCallback("ui_check", Impl::onClickUICheck, this);
+ childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);
getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
- childSetCommitCallback("hud_check", Impl::onClickHUDCheck, this);
+ childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);
getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
- impl.setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
+ ((Impl*)impl)->setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this);
getChild<LLUICtrl>("layer_types")->setValue("colors");
getChildView("layer_types")->setEnabled(FALSE);
getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame"));
- childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this);
+ childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this);
getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
- childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
-
+ childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this);
+
+ getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this));
+ getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterSnapshot::onExtendFloater, this));
// Filters
LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
- std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
- for (U32 i = 0; i < filter_list.size(); i++)
- {
- filterbox->add(filter_list[i]);
- }
- childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
+ std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+ for (U32 i = 0; i < filter_list.size(); i++)
+ {
+ filterbox->add(filter_list[i]);
+ }
+ childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this);
- LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
- LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1));
+ LLWebProfile::setImageUploadResultCallback(boost::bind(&Impl::onSnapshotUploadFinished, this, _1));
+ LLPostCard::setPostResultCallback(boost::bind(&Impl::onSendingPostcardFinished, this, _1));
- sThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+ mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
// create preview window
LLRect full_screen_rect = getRootView()->getRect();
@@ -1131,10 +1035,11 @@ BOOL LLFloaterSnapshot::postBuild()
getChild<LLComboBox>("local_size_combo")->selectNthItem(8);
getChild<LLComboBox>("local_format_combo")->selectNthItem(0);
- impl.mPreviewHandle = previewp->getHandle();
+ impl->mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
- impl.updateControls(this);
- impl.updateLayout(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+ impl->updateLayout(this);
previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
@@ -1142,9 +1047,10 @@ BOOL LLFloaterSnapshot::postBuild()
return TRUE;
}
-void LLFloaterSnapshot::draw()
+// virtual
+void LLFloaterSnapshotBase::draw()
{
- LLSnapshotLivePreview* previewp = impl.getPreviewView(this);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
{
@@ -1154,11 +1060,11 @@ void LLFloaterSnapshot::draw()
LLFloater::draw();
- if (previewp && !isMinimized() && sThumbnailPlaceholder->getVisible())
+ if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())
{
if(previewp->getThumbnailImage())
{
- bool working = impl.getStatus() == Impl::STATUS_WORKING;
+ bool working = impl->getStatus() == ImplBase::STATUS_WORKING;
const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
@@ -1183,16 +1089,17 @@ void LLFloaterSnapshot::draw()
gGL.pushUIMatrix();
LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
- sThumbnailPlaceholder->draw();
+ mThumbnailPlaceholder->draw();
gGL.popUIMatrix();
}
}
- impl.updateLayout(this);
+ impl->updateLayout(this);
}
+//virtual
void LLFloaterSnapshot::onOpen(const LLSD& key)
{
- LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(this);
+ LLSnapshotLivePreview* preview = getPreviewView();
if(preview)
{
LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
@@ -1203,19 +1110,26 @@ void LLFloaterSnapshot::onOpen(const LLSD& key)
gSnapshotFloaterView->setVisible(TRUE);
gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
- impl.updateControls(this);
- impl.updateLayout(this);
+ impl->updateControls(this);
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+ impl->updateLayout(this);
// Initialize default tab.
getChild<LLSideTrayPanelContainer>("panel_container")->getCurrentPanel()->onOpen(LLSD());
}
-void LLFloaterSnapshot::onClose(bool app_quitting)
+void LLFloaterSnapshot::onExtendFloater()
+{
+ impl->setAdvanced(gSavedSettings.getBOOL("AdvanceSnapshot"));
+}
+
+//virtual
+void LLFloaterSnapshotBase::onClose(bool app_quitting)
{
getParent()->setMouseOpaque(FALSE);
//unfreeze everything, hide fullscreen preview
- LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
previewp->setVisible(FALSE);
@@ -1223,125 +1137,145 @@ void LLFloaterSnapshot::onClose(bool app_quitting)
}
gSavedSettings.setBOOL("FreezeTime", FALSE);
- impl.mAvatarPauseHandles.clear();
+ impl->mAvatarPauseHandles.clear();
- if (impl.mLastToolset)
+ if (impl->mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(impl->mLastToolset);
}
}
// virtual
-S32 LLFloaterSnapshot::notify(const LLSD& info)
+S32 LLFloaterSnapshotBase::notify(const LLSD& info)
{
- // A child panel wants to change snapshot resolution.
- if (info.has("combo-res-change"))
+ if (info.has("set-ready"))
{
- std::string combo_name = info["combo-res-change"]["control-name"].asString();
- impl.updateResolution(getChild<LLUICtrl>(combo_name), this);
+ impl->setStatus(ImplBase::STATUS_READY);
return 1;
}
- if (info.has("custom-res-change"))
+ if (info.has("set-working"))
{
- LLSD res = info["custom-res-change"];
- impl.applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger());
+ impl->setStatus(ImplBase::STATUS_WORKING);
return 1;
}
- if (info.has("keep-aspect-change"))
+ if (info.has("set-finished"))
{
- impl.applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean());
+ LLSD data = info["set-finished"];
+ impl->setStatus(ImplBase::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());
return 1;
}
- if (info.has("image-quality-change"))
+ if (info.has("snapshot-updating"))
{
- impl.onImageQualityChange(this, info["image-quality-change"].asInteger());
+ // Disable the send/post/save buttons until snapshot is ready.
+ impl->updateControls(this);
return 1;
}
- if (info.has("image-format-change"))
+ if (info.has("snapshot-updated"))
{
- impl.onImageFormatChange(this);
+ // Enable the send/post/save buttons.
+ impl->updateControls(this);
+ // We've just done refresh.
+ impl->setNeedRefresh(false);
+
+ // The refresh button is initially hidden. We show it after the first update,
+ // i.e. when preview appears.
+ if (!mRefreshBtn->getVisible())
+ {
+ mRefreshBtn->setVisible(true);
+ }
return 1;
}
- if (info.has("set-ready"))
+ return 0;
+}
+
+// virtual
+S32 LLFloaterSnapshot::notify(const LLSD& info)
+{
+ bool res = LLFloaterSnapshotBase::notify(info);
+ if (res)
+ return res;
+ // A child panel wants to change snapshot resolution.
+ if (info.has("combo-res-change"))
{
- impl.setStatus(Impl::STATUS_READY);
+ std::string combo_name = info["combo-res-change"]["control-name"].asString();
+ ((Impl*)impl)->updateResolution(getChild<LLUICtrl>(combo_name), this);
return 1;
}
- if (info.has("set-working"))
+ if (info.has("custom-res-change"))
{
- impl.setStatus(Impl::STATUS_WORKING);
+ LLSD res = info["custom-res-change"];
+ ((Impl*)impl)->applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger());
return 1;
}
- if (info.has("set-finished"))
+ if (info.has("keep-aspect-change"))
{
- LLSD data = info["set-finished"];
- impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());
+ ((Impl*)impl)->applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean());
return 1;
}
-
- if (info.has("snapshot-updating"))
+
+ if (info.has("image-quality-change"))
{
- // Disable the send/post/save buttons until snapshot is ready.
- impl.updateControls(this);
+ ((Impl*)impl)->onImageQualityChange(this, info["image-quality-change"].asInteger());
return 1;
}
- if (info.has("snapshot-updated"))
+ if (info.has("image-format-change"))
{
- // Enable the send/post/save buttons.
- impl.updateControls(this);
- // We've just done refresh.
- impl.setNeedRefresh(this, false);
-
- // The refresh button is initially hidden. We show it after the first update,
- // i.e. when preview appears.
- if (!mRefreshBtn->getVisible())
- {
- mRefreshBtn->setVisible(true);
- }
+ ((Impl*)impl)->onImageFormatChange(this);
return 1;
- }
+ }
return 0;
}
-//static
-void LLFloaterSnapshot::update()
+BOOL LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized)
{
- LLFloaterSnapshot* inst = findInstance();
- LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
- LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
- LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
+ LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
+ LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
+ LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
+
+ if (!initialized && !floater_facebook && !floater_flickr && !floater_twitter)
+ return FALSE;
- if (!inst && !floater_facebook && !floater_flickr && !floater_twitter)
- return;
-
BOOL changed = FALSE;
LL_DEBUGS() << "npreviews: " << LLSnapshotLivePreview::sList.size() << LL_ENDL;
for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin();
- iter != LLSnapshotLivePreview::sList.end(); ++iter)
+ iter != LLSnapshotLivePreview::sList.end(); ++iter)
{
changed |= LLSnapshotLivePreview::onIdle(*iter);
}
-
- if (inst && changed)
+ return changed;
+}
+
+
+void LLFloaterSnapshotBase::ImplBase::updateLivePreview()
+{
+ if (ImplBase::updatePreviewList(true) && mFloater)
{
LL_DEBUGS() << "changed" << LL_ENDL;
- inst->impl.updateControls(inst);
+ updateControls(mFloater);
}
}
-// static
-LLFloaterSnapshot* LLFloaterSnapshot::getInstance()
+//static
+void LLFloaterSnapshot::update()
{
- return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot");
+ LLFloaterSnapshot* inst = findInstance();
+ if (inst != NULL)
+ {
+ inst->impl->updateLivePreview();
+ }
+ else
+ {
+ ImplBase::updatePreviewList(false);
+ }
}
// static
@@ -1351,18 +1285,17 @@ LLFloaterSnapshot* LLFloaterSnapshot::findInstance()
}
// static
+LLFloaterSnapshot* LLFloaterSnapshot::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot");
+}
+
+// virtual
void LLFloaterSnapshot::saveTexture()
{
LL_DEBUGS() << "saveTexture" << LL_ENDL;
- // FIXME: duplicated code
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return;
- }
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1372,18 +1305,10 @@ void LLFloaterSnapshot::saveTexture()
previewp->saveTexture();
}
-// static
BOOL LLFloaterSnapshot::saveLocal()
{
LL_DEBUGS() << "saveLocal" << LL_ENDL;
- // FIXME: duplicated code
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return FALSE;
- }
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1393,57 +1318,32 @@ BOOL LLFloaterSnapshot::saveLocal()
return previewp->saveLocal();
}
-// static
-void LLFloaterSnapshot::postSave()
+void LLFloaterSnapshotBase::postSave()
{
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return;
- }
-
- instance->impl.updateControls(instance);
- instance->impl.setStatus(Impl::STATUS_WORKING);
+ impl->updateControls(this);
+ impl->setStatus(ImplBase::STATUS_WORKING);
}
-// static
-void LLFloaterSnapshot::postPanelSwitch()
+// virtual
+void LLFloaterSnapshotBase::postPanelSwitch()
{
- LLFloaterSnapshot* instance = getInstance();
- instance->impl.updateControls(instance);
+ impl->updateControls(this);
// Remove the success/failure indicator whenever user presses a snapshot option button.
- instance->impl.setStatus(Impl::STATUS_READY);
+ impl->setStatus(ImplBase::STATUS_READY);
}
-// static
-void LLFloaterSnapshot::inventorySaveFailed()
+void LLFloaterSnapshotBase::inventorySaveFailed()
{
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return;
- }
-
- instance->impl.updateControls(instance);
- instance->impl.setStatus(Impl::STATUS_FINISHED, false, "inventory");
+ impl->updateControls(this);
+ impl->setStatus(ImplBase::STATUS_FINISHED, false, "inventory");
}
-// static
-LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData()
+LLPointer<LLImageFormatted> LLFloaterSnapshotBase::getImageData()
{
// FIXME: May not work for textures.
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return NULL;
- }
-
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1460,17 +1360,9 @@ LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData()
return img;
}
-// static
-const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal()
+const LLVector3d& LLFloaterSnapshotBase::getPosTakenGlobal()
{
- LLFloaterSnapshot* instance = findInstance();
- if (!instance)
- {
- llassert(instance != NULL);
- return LLVector3d::zero;
- }
-
- LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance);
+ LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
@@ -1504,6 +1396,7 @@ LLSnapshotFloaterView::~LLSnapshotFloaterView()
{
}
+// virtual
BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
// use default handler when not in freeze-frame mode
@@ -1525,6 +1418,7 @@ BOOL LLSnapshotFloaterView::handleKey(KEY key, MASK mask, BOOL called_from_paren
return TRUE;
}
+// virtual
BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
{
// use default handler when not in freeze-frame mode
@@ -1540,6 +1434,7 @@ BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
return TRUE;
}
+// virtual
BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
{
// use default handler when not in freeze-frame mode
@@ -1555,6 +1450,7 @@ BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
+// virtual
BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)
{
// use default handler when not in freeze-frame mode
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index eb3a94999b..1f303ea4d6 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2016, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,54 +27,184 @@
#ifndef LL_LLFLOATERSNAPSHOT_H
#define LL_LLFLOATERSNAPSHOT_H
+#include "llagent.h"
#include "llfloater.h"
+#include "llpanelsnapshot.h"
+#include "llsnapshotmodel.h"
class LLSpinCtrl;
+class LLSnapshotLivePreview;
-class LLFloaterSnapshot : public LLFloater
+class LLFloaterSnapshotBase : public LLFloater
{
- LOG_CLASS(LLFloaterSnapshot);
+ LOG_CLASS(LLFloaterSnapshotBase);
+
+public:
+
+ LLFloaterSnapshotBase(const LLSD& key);
+ virtual ~LLFloaterSnapshotBase();
+
+ /*virtual*/ void draw();
+ /*virtual*/ void onClose(bool app_quitting);
+ virtual S32 notify(const LLSD& info);
+
+ // TODO: create a snapshot model instead
+ virtual void saveTexture() = 0;
+ void postSave();
+ virtual void postPanelSwitch();
+ LLPointer<LLImageFormatted> getImageData();
+ LLSnapshotLivePreview* getPreviewView();
+ const LLVector3d& getPosTakenGlobal();
+
+ const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); }
+ void setRefreshLabelVisible(bool value) { mRefreshLabel->setVisible(value); }
+ void setSuccessLabelPanelVisible(bool value) { mSucceessLblPanel->setVisible(value); }
+ void setFailureLabelPanelVisible(bool value) { mFailureLblPanel->setVisible(value); }
+ void inventorySaveFailed();
+
+ class ImplBase;
+ friend class ImplBase;
+ ImplBase* impl;
+
+protected:
+ LLUICtrl* mThumbnailPlaceholder;
+ LLUICtrl *mRefreshBtn, *mRefreshLabel;
+ LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
+};
+
+class LLFloaterSnapshotBase::ImplBase
+{
public:
- typedef enum e_snapshot_format
+ typedef enum e_status
{
- SNAPSHOT_FORMAT_PNG,
- SNAPSHOT_FORMAT_JPEG,
- SNAPSHOT_FORMAT_BMP
- } ESnapshotFormat;
+ STATUS_READY,
+ STATUS_WORKING,
+ STATUS_FINISHED
+ } EStatus;
+
+ ImplBase(LLFloaterSnapshotBase* floater) : mAvatarPauseHandles(),
+ mLastToolset(NULL),
+ mAspectRatioCheckOff(false),
+ mNeedRefresh(false),
+ mStatus(STATUS_READY),
+ mFloater(floater)
+ {}
+ virtual ~ImplBase()
+ {
+ //unpause avatars
+ mAvatarPauseHandles.clear();
+ }
+
+ static void onClickNewSnapshot(void* data);
+ static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
+ static void onClickFilter(LLUICtrl *ctrl, void* data);
+ static void onClickUICheck(LLUICtrl *ctrl, void* data);
+ static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
+ static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
+
+ virtual LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) = 0;
+ virtual LLSnapshotModel::ESnapshotType getActiveSnapshotType(LLFloaterSnapshotBase* floater);
+ virtual LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater) = 0;
+ virtual std::string getSnapshotPanelPrefix() = 0;
+
+ LLSnapshotLivePreview* getPreviewView();
+ virtual void updateControls(LLFloaterSnapshotBase* floater) = 0;
+ virtual void updateLayout(LLFloaterSnapshotBase* floater);
+ virtual void updateLivePreview();
+ virtual void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null);
+ virtual EStatus getStatus() const { return mStatus; }
+ virtual void setNeedRefresh(bool need);
+
+ static BOOL updatePreviewList(bool initialized);
+
+ void setAdvanced(bool advanced) { mAdvanced = advanced; }
+
+ virtual LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater) = 0;
+ virtual void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
+ void setWorking(bool working);
+ virtual void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null) = 0;
+
+public:
+ LLFloaterSnapshotBase* mFloater;
+ std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
+
+ LLToolset* mLastToolset;
+ LLHandle<LLView> mPreviewHandle;
+ bool mAspectRatioCheckOff;
+ bool mNeedRefresh;
+ bool mAdvanced;
+ EStatus mStatus;
+};
+
+class LLFloaterSnapshot : public LLFloaterSnapshotBase
+{
+ LOG_CLASS(LLFloaterSnapshot);
+public:
LLFloaterSnapshot(const LLSD& key);
- virtual ~LLFloaterSnapshot();
+ /*virtual*/ ~LLFloaterSnapshot();
/*virtual*/ BOOL postBuild();
- /*virtual*/ void draw();
/*virtual*/ void onOpen(const LLSD& key);
- /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ S32 notify(const LLSD& info);
static void update();
- // TODO: create a snapshot model instead
+ void onExtendFloater();
+
static LLFloaterSnapshot* getInstance();
static LLFloaterSnapshot* findInstance();
- static void saveTexture();
- static BOOL saveLocal();
- static void postSave();
- static void postPanelSwitch();
- static void inventorySaveFailed();
- static LLPointer<LLImageFormatted> getImageData();
- static const LLVector3d& getPosTakenGlobal();
+ /*virtual*/ void saveTexture();
+ BOOL saveLocal();
static void setAgentEmail(const std::string& email);
- static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholder->getRect(); }
+ class Impl;
+ friend class Impl;
+};
-private:
- static LLUICtrl* sThumbnailPlaceholder;
- LLUICtrl *mRefreshBtn, *mRefreshLabel;
- LLUICtrl *mSucceessLblPanel, *mFailureLblPanel;
+///----------------------------------------------------------------------------
+/// Class LLFloaterSnapshot::Impl
+///----------------------------------------------------------------------------
- class Impl;
- Impl& impl;
+class LLFloaterSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase
+{
+ LOG_CLASS(LLFloaterSnapshot::Impl);
+public:
+ Impl(LLFloaterSnapshotBase* floater)
+ : LLFloaterSnapshotBase::ImplBase(floater)
+ {}
+ ~Impl()
+ {}
+
+ void applyKeepAspectCheck(LLFloaterSnapshotBase* view, BOOL checked);
+ void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE);
+ static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
+ void onImageQualityChange(LLFloaterSnapshotBase* view, S32 quality_val);
+ void onImageFormatChange(LLFloaterSnapshotBase* view);
+ void applyCustomResolution(LLFloaterSnapshotBase* view, S32 w, S32 h);
+ static void onSendingPostcardFinished(LLFloaterSnapshotBase* floater, bool status);
+ BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
+ void setImageSizeSpinnersValues(LLFloaterSnapshotBase *view, S32 width, S32 height);
+ void updateSpinners(LLFloaterSnapshotBase* view, LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL is_width_changed);
+ static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status);
+
+ /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true);
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater);
+ LLSpinCtrl* getWidthSpinner(LLFloaterSnapshotBase* floater);
+ LLSpinCtrl* getHeightSpinner(LLFloaterSnapshotBase* floater);
+ void enableAspectRatioCheckbox(LLFloaterSnapshotBase* floater, BOOL enable);
+ void setAspectRatioCheckboxValue(LLFloaterSnapshotBase* floater, BOOL checked);
+ /*virtual*/ std::string getSnapshotPanelPrefix();
+
+ void setResolution(LLFloaterSnapshotBase* floater, const std::string& comboname);
+ /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater);
+
+private:
+ /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater);
+ void comboSetCustom(LLFloaterSnapshotBase *floater, const std::string& comboname);
+ void checkAspectRatio(LLFloaterSnapshotBase *view, S32 index);
+ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null);
};
class LLSnapshotFloaterView : public LLFloaterView
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index c48b1a3325..4bab89ace2 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -241,8 +241,8 @@ void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible)
mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
- previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
- previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+ previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
+ previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 024e315632..dece3fc1ea 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -55,7 +55,8 @@ LLFloaterWebContent::_Params::_Params()
preferred_media_size("preferred_media_size"),
trusted_content("trusted_content", false),
show_page_title("show_page_title", true),
- clean_browser("clean_browser", false)
+ clean_browser("clean_browser", false),
+ dev_mode("dev_mode", false)
{}
LLFloaterWebContent::LLFloaterWebContent( const Params& params )
@@ -74,14 +75,16 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )
mShowPageTitle(params.show_page_title),
mAllowNavigation(true),
mCurrentURL(""),
- mDisplayURL("")
+ mDisplayURL(""),
+ mDevelopMode(params.dev_mode) // if called from "Develop" Menu, set a flag and change things to be more useful for devs
{
mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
- mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
+ mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind(&LLFloaterWebContent::onPopExternal, this));
+ mCommitCallbackRegistrar.add( "WebContent.TestURL", boost::bind(&LLFloaterWebContent::onTestURL, this, _2));
}
BOOL LLFloaterWebContent::postBuild()
@@ -195,8 +198,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
width + getRect().getWidth() - browser_rect.getWidth(),
height + getRect().getHeight() - browser_rect.getHeight());
- LL_DEBUGS() << "geometry change: " << geom << LL_ENDL;
-
LLRect new_rect;
getParent()->screenRectToLocal(geom, &new_rect);
setShape(new_rect);
@@ -205,8 +206,6 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
// static
void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
{
- LL_DEBUGS() << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << LL_ENDL;
-
if (!p.id.isProvided())
{
p.id = LLUUID::generateNewID().asString();
@@ -224,12 +223,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
// and close the least recently opened one if this will put us over the limit.
LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class);
- LL_DEBUGS() << "total instance count is " << instances.size() << LL_ENDL;
-
- for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
- {
- LL_DEBUGS() << " " << (*iter)->getKey()["target"] << LL_ENDL;
- }
if(instances.size() >= (size_t)browser_window_limit)
{
@@ -241,16 +234,19 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
void LLFloaterWebContent::open_media(const Params& p)
{
- // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
LLViewerMedia::proxyWindowOpened(p.target(), p.id());
- mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML);
+ mWebBrowser->setHomePageUrl(p.url);
mWebBrowser->setTarget(p.target);
- mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser);
+ mWebBrowser->navigateTo(p.url);
set_current_url(p.url);
getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);
getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome);
+
+ // turn additional debug controls on but only for Develop mode (Develop menu open)
+ getChild<LLLayoutPanel>("debug_controls")->setVisible(mDevelopMode);
+
bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;
mAllowNavigation = p.allow_back_forward_navigation;
getChildView("address")->setEnabled(address_entry_enabled);
@@ -499,7 +495,7 @@ void LLFloaterWebContent::onEnterAddress()
LLStringUtil::trim(url);
if ( url.length() > 0 )
{
- mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
+ mWebBrowser->navigateTo(url);
};
}
@@ -508,9 +504,18 @@ void LLFloaterWebContent::onPopExternal()
// make sure there is at least something there.
// (perhaps this test should be for minimum length of a URL)
std::string url = mAddressCombo->getValue().asString();
- LLStringUtil::trim(url);
- if ( url.length() > 0 )
+ LLStringUtil::trim(url);
+ if (url.length() > 0)
+ {
+ LLWeb::loadURLExternal(url);
+ };
+}
+
+void LLFloaterWebContent::onTestURL(std::string url)
+{
+ LLStringUtil::trim(url);
+ if (url.length() > 0)
{
- LLWeb::loadURLExternal( url );
+ mWebBrowser->navigateTo(url);
};
}
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index 4291fd9f2c..0bf93504c2 100644
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -58,7 +58,8 @@ public:
allow_back_forward_navigation,
trusted_content,
show_page_title,
- clean_browser;
+ clean_browser,
+ dev_mode;
Optional<LLRect> preferred_media_size;
_Params();
@@ -92,6 +93,7 @@ protected:
void onClickStop();
void onEnterAddress();
void onPopExternal();
+ void onTestURL(std::string url);
static void preCreate(Params& p);
void open_media(const Params& );
@@ -113,6 +115,7 @@ protected:
std::string mUUID;
bool mShowPageTitle;
bool mAllowNavigation;
+ bool mDevelopMode;
};
#endif // LL_LLFLOATERWEBCONTENT_H
diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp
index 271dd44c1f..7c2a3cad43 100644
--- a/indra/newview/llgroupiconctrl.cpp
+++ b/indra/newview/llgroupiconctrl.cpp
@@ -74,9 +74,16 @@ LLGroupIconCtrl::~LLGroupIconCtrl()
LLGroupMgr::getInstance()->removeObserver(this);
}
-void LLGroupIconCtrl::setIconId(const LLSD& value)
+void LLGroupIconCtrl::setIconId(const LLUUID& icon_id)
{
- LLIconCtrl::setValue(value);
+ if (icon_id.notNull())
+ {
+ LLIconCtrl::setValue(icon_id);
+ }
+ else
+ {
+ LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI);
+ }
}
void LLGroupIconCtrl::setValue(const LLSD& value)
@@ -122,14 +129,7 @@ bool LLGroupIconCtrl::updateFromCache()
LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId);
if (!group_data) return false;
- if (group_data->mInsigniaID.notNull())
- {
- LLIconCtrl::setValue(group_data->mInsigniaID);
- }
- else
- {
- LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI);
- }
+ setIconId(group_data->mInsigniaID);
if (mDrawTooltip && !group_data->mName.empty())
{
diff --git a/indra/newview/llgroupiconctrl.h b/indra/newview/llgroupiconctrl.h
index f8b22cf581..43e384d3e2 100644
--- a/indra/newview/llgroupiconctrl.h
+++ b/indra/newview/llgroupiconctrl.h
@@ -66,7 +66,13 @@ public:
*/
virtual void setValue(const LLSD& value);
- void setIconId(const LLSD& value);
+ /**
+ * Sets icon_id as icon value directly. Avoids LLGroupMgr cache checks for group id
+ * Uses default icon in case id is null.
+ *
+ * @params icon_id - it is processed as icon id, default image will be used in case id is null.
+ */
+ void setIconId(const LLUUID& icon_id);
// LLGroupMgrObserver observer trigger
virtual void changed(LLGroupChange gc);
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 6126db2988..62414d3bbb 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -379,10 +379,7 @@ void LLGroupListItem::setGroupID(const LLUUID& group_id)
void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id)
{
- if (group_icon_id.notNull())
- {
- mGroupIcon->setIconId(group_icon_id);
- }
+ mGroupIcon->setIconId(group_icon_id);
}
void LLGroupListItem::setGroupIconVisible(bool visible)
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 52e83fe412..6b1e196182 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -53,7 +53,7 @@ const F32 VERTICAL_PADDING = 12.f;
const F32 BUFFER_SIZE = 2.f;
const F32 HUD_TEXT_MAX_WIDTH = 190.f;
const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
-const F32 MAX_DRAW_DISTANCE = 64.f;
+const F32 MAX_DRAW_DISTANCE = 300.f;
std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects;
std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects;
@@ -394,7 +394,20 @@ void LLHUDText::updateVisibility()
LLVector3 pos_agent_center = gAgent.getPosAgentFromGlobal(mPositionGlobal) - dir_from_camera;
F32 last_distance_center = (pos_agent_center - LLViewerCamera::getInstance()->getOrigin()).magVec();
- if(last_distance_center > MAX_DRAW_DISTANCE)
+ F32 max_draw_distance = gSavedSettings.getF32("PrimTextMaxDrawDistance");
+
+ if(max_draw_distance < 0)
+ {
+ max_draw_distance = 0;
+ gSavedSettings.setF32("PrimTextMaxDrawDistance", max_draw_distance);
+ }
+ else if(max_draw_distance > MAX_DRAW_DISTANCE)
+ {
+ max_draw_distance = MAX_DRAW_DISTANCE;
+ gSavedSettings.setF32("PrimTextMaxDrawDistance", MAX_DRAW_DISTANCE);
+ }
+
+ if(last_distance_center > max_draw_distance)
{
mVisible = FALSE;
return;
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp
index 8e91af321e..a4fce36783 100644
--- a/indra/newview/llinspectgroup.cpp
+++ b/indra/newview/llinspectgroup.cpp
@@ -41,6 +41,7 @@
#include "lltooltip.h" // positionViewNearMouse()
#include "lltrans.h"
#include "lluictrl.h"
+#include "llgroupiconctrl.h"
//////////////////////////////////////////////////////////////////////////////
// LLInspectGroup
@@ -233,7 +234,7 @@ void LLInspectGroup::processGroupData()
getChild<LLUICtrl>("group_details")->setValue( LLSD(data->mCharter) );
- getChild<LLUICtrl>("group_icon")->setValue( LLSD(data->mInsigniaID) );
+ getChild<LLGroupIconCtrl>("group_icon")->setIconId(data->mInsigniaID);
std::string cost;
bool is_member = LLGroupActions::isInGroup(mGroupID);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 26c9b40fb1..eebb6a0384 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -286,6 +286,16 @@ BOOL LLInvFVBridge::cutToClipboard()
return FALSE;
}
+// virtual
+bool LLInvFVBridge::isCutToClipboard()
+{
+ if (LLClipboard::instance().isCutMode())
+ {
+ return LLClipboard::instance().isOnClipboard(mUUID);
+ }
+ return false;
+}
+
// Callback for cutToClipboard if DAMA required...
BOOL LLInvFVBridge::callback_cutToClipboard(const LLSD& notification, const LLSD& response)
{
@@ -307,9 +317,7 @@ BOOL LLInvFVBridge::perform_cutToClipboard()
if (obj && isItemMovable() && isItemRemovable())
{
LLClipboard::instance().setCutMode(true);
- BOOL added_to_clipboard = LLClipboard::instance().addToClipboard(mUUID);
- removeObject(&gInventory, mUUID); // Always perform the remove even if the object couldn't make it to the clipboard
- return added_to_clipboard;
+ return LLClipboard::instance().addToClipboard(mUUID);
}
return FALSE;
}
@@ -1390,6 +1398,12 @@ bool LLInvFVBridge::canShare() const
// Categories can be given.
can_share = (model->getCategory(mUUID) != NULL);
}
+
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if ((mUUID == trash_id) || gInventory.isObjectDescendentOf(mUUID, trash_id))
+ {
+ can_share = false;
+ }
}
}
@@ -1925,13 +1939,15 @@ BOOL LLItemBridge::removeItem()
}
// move it to the trash
- LLPreview::hide(mUUID, TRUE);
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLViewerInventoryItem* item = getItem();
if (!item) return FALSE;
-
+ if (item->getType() != LLAssetType::AT_LSL_TEXT)
+ {
+ LLPreview::hide(mUUID, TRUE);
+ }
// Already in trash
if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE;
@@ -4358,10 +4374,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
// Returns true if the item can be moved to Current Outfit or any outfit folder.
static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
{
- if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) &&
- (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) &&
- (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) &&
- (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT))
+ LLInventoryType::EType inv_type = inv_item->getInventoryType();
+ if ((inv_type != LLInventoryType::IT_WEARABLE) &&
+ (inv_type != LLInventoryType::IT_GESTURE) &&
+ (inv_type != LLInventoryType::IT_ATTACHMENT) &&
+ (inv_type != LLInventoryType::IT_OBJECT) &&
+ (inv_type != LLInventoryType::IT_SNAPSHOT) &&
+ (inv_type != LLInventoryType::IT_TEXTURE))
{
return FALSE;
}
@@ -4372,6 +4391,11 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr
return FALSE;
}
+ if((inv_type == LLInventoryType::IT_TEXTURE) || (inv_type == LLInventoryType::IT_SNAPSHOT))
+ {
+ return TRUE;
+ }
+
if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID()))
{
return FALSE;
@@ -4422,6 +4446,14 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
{
+ if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT))
+ {
+ LLAppearanceMgr::instance().removeOutfitPhoto(mUUID);
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
+ return;
+ }
+
// BAP - should skip if dup.
if (move_is_into_current_outfit)
{
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 9053c61171..df25e01688 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -116,6 +116,7 @@ public:
virtual BOOL isItemCopyable() const { return FALSE; }
virtual BOOL copyToClipboard() const;
virtual BOOL cutToClipboard();
+ virtual bool isCutToClipboard();
virtual BOOL isClipboardPasteable() const;
virtual BOOL isClipboardPasteableAsLink() const;
virtual void pasteFromClipboard() {}
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 003bbcafed..e995c138b4 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -84,21 +84,18 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
{
const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item);
- // Clipboard cut items are *always* filtered so we need this value upfront
- const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE);
// If it's a folder and we're showing all folders, return automatically.
const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;
if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))
{
- return passed_clipboard;
+ return true;
}
bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true);
passed = passed && checkAgainstFilterType(listener);
passed = passed && checkAgainstPermissions(listener);
passed = passed && checkAgainstFilterLinks(listener);
- passed = passed && passed_clipboard;
return passed;
}
@@ -108,9 +105,8 @@ bool LLInventoryFilter::check(const LLInventoryItem* item)
const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);
const bool passed_filtertype = checkAgainstFilterType(item);
const bool passed_permissions = checkAgainstPermissions(item);
- const bool passed_clipboard = checkAgainstClipboard(item->getUUID());
- return passed_filtertype && passed_permissions && passed_clipboard && passed_string;
+ return passed_filtertype && passed_permissions && passed_string;
}
bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const
@@ -129,13 +125,10 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const
bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
{
- // Always check against the clipboard
- const BOOL passed_clipboard = checkAgainstClipboard(folder_id);
-
// we're showing all folders, overriding filter
if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
{
- return passed_clipboard;
+ return true;
}
// when applying a filter, matching folders get their contents downloaded first
@@ -201,7 +194,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
LLViewerInventoryItem* item = gInventory.getItem(folder_id);
if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER)
{
- return passed_clipboard;
+ return true;
}
if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
@@ -216,7 +209,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
return false;
}
- return passed_clipboard;
+ return true;
}
bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 9a33e210ff..503fa28a33 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -582,7 +582,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
// Add the category to the internal representation
LLPointer<LLViewerInventoryCategory> cat =
new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID());
- cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
+ cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
cat->setDescendentCount(0);
LLCategoryUpdate update(cat->getParentUUID(), 1);
accountForUpdate(update);
@@ -640,7 +640,7 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(),
result["name"].asString(), gAgent.getID());
- cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
+ cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
cat->setDescendentCount(0);
LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
@@ -914,8 +914,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id);
if( item_array )
{
+ LLInventoryModel::LLCategoryUpdate update(category_id, 1);
+ gInventory.accountForUpdate(update);
+
// *FIX: bit of a hack to call update server from here...
- new_item->updateServer(TRUE);
+ new_item->updateParentOnServer(FALSE);
item_array->push_back(new_item);
}
else
@@ -956,9 +959,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
if(item_array)
{
+ LLInventoryModel::LLCategoryUpdate update(parent_id, 1);
+ gInventory.accountForUpdate(update);
// *FIX: bit of a hack to call update server from
// here...
- new_item->updateServer(TRUE);
+ new_item->updateParentOnServer(FALSE);
item_array->push_back(new_item);
}
else
@@ -1045,7 +1050,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32
if(old_cat)
{
// We already have an old category, modify its values
- U32 mask = LLInventoryObserver::NONE;
LLUUID old_parent_id = old_cat->getParentUUID();
LLUUID new_parent_id = cat->getParentUUID();
if(old_parent_id != new_parent_id)
@@ -1100,7 +1104,8 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32
item_array_t* itemsp = new item_array_t;
mParentChildCategoryTree[new_cat->getUUID()] = catsp;
mParentChildItemTree[new_cat->getUUID()] = itemsp;
- addChangedMask(LLInventoryObserver::ADD, cat->getUUID());
+ mask |= LLInventoryObserver::ADD;
+ addChangedMask(mask, cat->getUUID());
}
}
@@ -1390,7 +1395,11 @@ void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool f
}
// From purgeObject()
- LLPreview::hide(object_id);
+ LLViewerInventoryItem *item = getItem(object_id);
+ if (item && (item->getType() != LLAssetType::AT_LSL_TEXT))
+ {
+ LLPreview::hide(object_id, TRUE);
+ }
deleteObject(object_id, fix_broken_links, do_notify_observers);
}
}
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index aa934f95a1..a55938f334 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -181,7 +181,12 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
if (gDirUtilp->fileExists(mFilename))
{
// verifying that the file has indeed been modified
+
+#ifndef LL_WINDOWS
const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename));
+#else
+ const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(utf8str_to_utf16str(mFilename)));
+#endif
LLSD new_last_modified = asctime(localtime(&temp_time));
if (mLastModified.asString() != new_last_modified.asString())
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 53b2ca2b74..11bc1425f9 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -243,7 +243,7 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
params.commit_on_focus_lost(false);
params.follows.flags(FOLLOWS_ALL);
mTextEntry = LLUICtrlFactory::create<LLURLLineEditor>(params);
- mTextEntry->setContextMenu(NULL);
+ mTextEntry->resetContextMenu();
addChild(mTextEntry);
// LLLineEditor is replaced with LLLocationLineEditor
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 639641d1c2..485d4677b1 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -244,7 +244,10 @@ std::string LLLogChat::makeLogFileName(std::string filename)
filename = cleanFileName(filename);
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename);
- filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION;
+ if (!filename.empty())
+ {
+ filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION;
+ }
return filename;
}
diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h
index 1fb05e047a..69881e8589 100644
--- a/indra/newview/llmanip.h
+++ b/indra/newview/llmanip.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmanip.h
* @brief LLManip class definition
*
@@ -37,7 +37,7 @@ class LLToolComposite;
class LLVector3;
class LLObjectSelection;
-const S32 MIN_DIVISION_PIXEL_WIDTH = 9;
+const S32 MIN_DIVISION_PIXEL_WIDTH = 3;
class LLManip : public LLTool
{
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index b4259a456c..3975d3980b 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmaniptranslate.cpp
* @brief LLManipTranslate class implementation
*
@@ -548,12 +548,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
if (off_axis_magnitude > mSnapOffsetMeters)
{
mInSnapRegime = TRUE;
- LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal);
LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line);
- if (!gSavedSettings.getBOOL("SnapToMouseCursor"))
- {
- cursor_snap_agent -= mouse_down_offset;
- }
F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f;
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 6cc7a0fc99..54f95520db 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -773,7 +773,9 @@ void LLMarketplaceData::getMerchantStatusCoro()
std::string url = getSLMConnectURL("/merchant");
if (url.empty())
{
- LL_INFOS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL;
+ LL_WARNS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL;
+ setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE);
+ return;
}
LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 9cf3249983..00043d1e72 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -1007,7 +1007,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
std::string uuid = self->getClickUUID();
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
- LLWeb::loadURL(url, target, std::string());
+ // try as slurl first
+ if (!LLURLDispatcher::dispatch(url, "clicked", NULL, mTrusted))
+ {
+ LLWeb::loadURL(url, target, std::string());
+ }
// CP: removing this code because we no longer support popups so this breaks the flow.
// replaced with a bare call to LLWeb::LoadURL(...)
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 54f8fb93d0..e42647739f 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1753,6 +1753,11 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
{
+ if (data == NULL || data_size == 0)
+ {
+ return false;
+ }
+
LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
std::string mesh_string((char*) data, data_size);
std::istringstream stream(mesh_string);
@@ -3010,12 +3015,23 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
}
else if (data && data_size > 0)
{
- // header was successfully retrieved from sim, cache in vfs
- LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id];
+ // header was successfully retrieved from sim and parsed, cache in vfs
+ S32 header_bytes = 0;
+ LLSD header;
- S32 version = header["version"].asInteger();
+ gMeshRepo.mThread->mHeaderMutex->lock();
+ LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id);
+ if (iter != gMeshRepo.mThread->mMeshHeader.end())
+ {
+ header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
+ header = iter->second;
+ }
+ gMeshRepo.mThread->mHeaderMutex->unlock();
- if (version <= MAX_MESH_VERSION)
+ if (header_bytes > 0
+ && !header.has("404")
+ && header.has("version")
+ && header["version"].asInteger() <= MAX_MESH_VERSION)
{
std::stringstream str;
@@ -3064,6 +3080,17 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
}
}
}
+ else
+ {
+ LL_WARNS(LOG_MESH) << "Trying to cache nonexistent mesh, mesh id: " << mesh_id << LL_ENDL;
+
+ // headerReceived() parsed header, but header's data is invalid so none of the LODs will be available
+ LLMutexLock lock(gMeshRepo.mThread->mMutex);
+ for (int i(0); i < 4; ++i)
+ {
+ gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+ }
+ }
}
}
@@ -4115,7 +4142,7 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32
}
}
- F32 max_area = 102932.f; //area of circle that encompasses region
+ F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559)
F32 min_area = 1.f;
F32 high_area = llmin(F_PI*dmid*dmid, max_area);
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 70035bcc74..c3dd08c327 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -252,7 +252,7 @@ void LLFloaterMove::setSittingMode(BOOL bSitting)
LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
}
}
- enableInstance(!bSitting);
+ enableInstance();
}
// protected
@@ -459,7 +459,7 @@ void LLFloaterMove::showModeButtons(BOOL bShow)
}
//static
-void LLFloaterMove::enableInstance(BOOL bEnable)
+void LLFloaterMove::enableInstance()
{
LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
if (instance)
@@ -470,7 +470,7 @@ void LLFloaterMove::enableInstance(BOOL bEnable)
}
else
{
- instance->showModeButtons(bEnable);
+ instance->showModeButtons(isAgentAvatarValid() && !gAgentAvatarp->isSitting());
}
}
}
@@ -566,7 +566,7 @@ BOOL LLPanelStandStopFlying::postBuild()
{
mStandButton = getChild<LLButton>("stand_btn");
mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this));
- mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE));
+ mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance));
mStandButton->setVisible(FALSE);
LLHints::registerHintTarget("stand_btn", mStandButton->getHandle());
@@ -685,8 +685,7 @@ void LLPanelStandStopFlying::onStandButtonClick()
LLSelectMgr::getInstance()->deselectAllForStandingUp();
gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
- setFocus(FALSE); // EXT-482
- mStandButton->setVisible(FALSE); // force visibility changing to avoid seeing Stand & Move buttons at once.
+ setFocus(FALSE);
}
void LLPanelStandStopFlying::onStopFlyingButtonClick()
@@ -694,7 +693,6 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick()
gAgent.setFlying(FALSE);
setFocus(FALSE); // EXT-482
- mStopFlyingButton->setVisible(FALSE);
}
/**
diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h
index c525d9dfdb..4a31f2a814 100644
--- a/indra/newview/llmoveview.h
+++ b/indra/newview/llmoveview.h
@@ -56,7 +56,7 @@ public:
static void setAlwaysRunMode(bool run);
void setAlwaysRunModeImpl(bool run);
static void setSittingMode(BOOL bSitting);
- static void enableInstance(BOOL bEnable);
+ static void enableInstance();
/*virtual*/ void onOpen(const LLSD& key);
static void sUpdateFlyingStatus();
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 5fc73c67d1..72faa5a9e7 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -735,7 +735,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
continue;
}
S32 offset = px + py * image_width;
- ((U32*)datap)[offset] = color.mAll;
+ ((U32*)datap)[offset] = color.asRGBA();
}
// top line
@@ -748,7 +748,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
continue;
}
S32 offset = px + py * image_width;
- ((U32*)datap)[offset] = color.mAll;
+ ((U32*)datap)[offset] = color.asRGBA();
}
}
else
@@ -770,7 +770,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
continue;
}
S32 offset = p_x + p_y * image_width;
- ((U32*)datap)[offset] = color.mAll;
+ ((U32*)datap)[offset] = color.asRGBA();
}
}
}
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 2657b84ef3..63ab88da42 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -96,17 +96,21 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)
LLUUID from_id = notification->getPayload()["from_id"];
- //Will not play a notification sound for inventory and teleport offer based upon chat preference
- bool playSound = (!notification->isDND()
- && ((notification->getName() == "UserGiveItem"
- && gSavedSettings.getBOOL("PlaySoundInventoryOffer"))
- || (notification->getName() == "TeleportOffered"
- && gSavedSettings.getBOOL("PlaySoundTeleportOffer"))));
-
- if(playSound)
- {
- notification->playSound();
- }
+ if (!notification->isDND())
+ {
+ //Will not play a notification sound for inventory and teleport offer based upon chat preference
+ bool playSound = (notification->getName() == "UserGiveItem"
+ && gSavedSettings.getBOOL("PlaySoundInventoryOffer"))
+ || ((notification->getName() == "TeleportOffered"
+ || notification->getName() == "TeleportOffered_MaturityExceeded"
+ || notification->getName() == "TeleportOffered_MaturityBlocked")
+ && gSavedSettings.getBOOL("PlaySoundTeleportOffer"));
+
+ if (playSound)
+ {
+ notification->playSound();
+ }
+ }
LLHandlerUtil::spawnIMSession(name, from_id);
LLHandlerUtil::addNotifPanelToIM(notification);
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
new file mode 100644
index 0000000000..de6a36ce2f
--- /dev/null
+++ b/indra/newview/lloutfitgallery.cpp
@@ -0,0 +1,1288 @@
+/**
+ * @file lloutfitgallery.cpp
+ * @author Pavlo Kryvych
+ * @brief Visual gallery of agent's outfits for My Appearance side panel
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+#include "lloutfitgallery.h"
+
+#include <boost/foreach.hpp>
+
+// llcommon
+#include "llcommonutils.h"
+#include "llvfile.h"
+
+#include "llappearancemgr.h"
+#include "lleconomy.h"
+#include "llerror.h"
+#include "llfilepicker.h"
+#include "llfloaterperms.h"
+#include "llfloaterreg.h"
+#include "llfloateroutfitsnapshot.h"
+#include "llimagedimensionsinfo.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "lllocalbitmaps.h"
+#include "llnotificationsutil.h"
+#include "lltexturectrl.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llviewermenufile.h"
+#include "llviewertexturelist.h"
+#include "llwearableitemslist.h"
+
+static LLPanelInjector<LLOutfitGallery> t_outfit_gallery("outfit_gallery");
+
+#define MAX_OUTFIT_PHOTO_WIDTH 256
+#define MAX_OUTFIT_PHOTO_HEIGHT 256
+
+LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p)
+ : LLOutfitListBase(),
+ mTexturesObserver(NULL),
+ mOutfitsObserver(NULL),
+ mScrollPanel(NULL),
+ mGalleryPanel(NULL),
+ mGalleryCreated(false),
+ mRowCount(0),
+ mItemsAddedCount(0),
+ mOutfitLinkPending(NULL),
+ mOutfitRenamePending(NULL),
+ mRowPanelHeight(p.row_panel_height),
+ mVerticalGap(p.vertical_gap),
+ mHorizontalGap(p.horizontal_gap),
+ mItemWidth(p.item_width),
+ mItemHeight(p.item_height),
+ mItemHorizontalGap(p.item_horizontal_gap),
+ mItemsInRow(p.items_in_row),
+ mRowPanWidthFactor(p.row_panel_width_factor),
+ mGalleryWidthFactor(p.gallery_width_factor),
+ mTextureSelected(NULL)
+{
+ updateGalleryWidth();
+}
+
+LLOutfitGallery::Params::Params()
+ : row_panel_height("row_panel_height", 180),
+ vertical_gap("vertical_gap", 10),
+ horizontal_gap("horizontal_gap", 10),
+ item_width("item_width", 150),
+ item_height("item_height", 175),
+ item_horizontal_gap("item_horizontal_gap", 16),
+ items_in_row("items_in_row", 3),
+ row_panel_width_factor("row_panel_width_factor", 166),
+ gallery_width_factor("gallery_width_factor", 163)
+{
+ addSynonym(row_panel_height, "row_height");
+}
+
+const LLOutfitGallery::Params& LLOutfitGallery::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLOutfitGallery>();
+}
+
+BOOL LLOutfitGallery::postBuild()
+{
+ BOOL rv = LLOutfitListBase::postBuild();
+ mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel");
+ mGalleryPanel = getChild<LLPanel>("gallery_panel");
+ mMessageTextBox = getChild<LLTextBox>("no_outfits_txt");
+ mOutfitGalleryMenu = new LLOutfitGalleryContextMenu(this);
+ return rv;
+}
+
+void LLOutfitGallery::onOpen(const LLSD& info)
+{
+ LLOutfitListBase::onOpen(info);
+ if (!mGalleryCreated)
+ {
+ loadPhotos();
+ uuid_vec_t cats;
+ getCurrentCategories(cats);
+ int n = cats.size();
+ buildGalleryPanel(n);
+ mScrollPanel->addChild(mGalleryPanel);
+ for (int i = 0; i < n; i++)
+ {
+ addToGallery(mOutfitMap[cats[i]]);
+ }
+ reArrangeRows();
+ mGalleryCreated = true;
+ }
+}
+
+void LLOutfitGallery::draw()
+{
+ LLPanel::draw();
+ if (mGalleryCreated)
+ {
+ updateRowsIfNeeded();
+ }
+}
+
+void LLOutfitGallery::updateRowsIfNeeded()
+{
+ if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1)
+ {
+ reArrangeRows(1);
+ }
+ else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > 3)
+ {
+ reArrangeRows(-1);
+ }
+}
+
+bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)
+{
+ if(gSavedSettings.getBOOL("OutfitGallerySortByName") ||
+ ((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage())))
+ {
+ std::string name1 = item1->getItemName();
+ std::string name2 = item2->getItemName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+ return name1 < name2;
+ }
+ else
+ {
+ return item2->isDefaultImage();
+ }
+}
+
+void LLOutfitGallery::reArrangeRows(S32 row_diff)
+{
+
+ std::vector<LLOutfitGalleryItem*> buf_items = mItems;
+ for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it)
+ {
+ removeFromGalleryLast(*it);
+ }
+ for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it)
+ {
+ buf_items.push_back(*it);
+ }
+ mHiddenItems.clear();
+
+ mItemsInRow+= row_diff;
+ updateGalleryWidth();
+ std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem);
+
+ for (std::vector<LLOutfitGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it)
+ {
+ (*it)->setHidden(false);
+ applyFilter(*it,sFilterSubString);
+ addToGallery(*it);
+ }
+ updateMessageVisibility();
+}
+
+void LLOutfitGallery::updateGalleryWidth()
+{
+ mRowPanelWidth = mRowPanWidthFactor * mItemsInRow - mItemHorizontalGap;
+ mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap;
+}
+
+LLPanel* LLOutfitGallery::addLastRow()
+{
+ mRowCount++;
+ int row = 0;
+ int vgap = mVerticalGap * row;
+ LLPanel* result = buildRowPanel(0, row * mRowPanelHeight + vgap);
+ mGalleryPanel->addChild(result);
+ return result;
+}
+
+void LLOutfitGallery::moveRowUp(int row)
+{
+ moveRow(row, mRowCount - 1 - row + 1);
+}
+
+void LLOutfitGallery::moveRowDown(int row)
+{
+ moveRow(row, mRowCount - 1 - row - 1);
+}
+
+void LLOutfitGallery::moveRow(int row, int pos)
+{
+ int vgap = mVerticalGap * pos;
+ moveRowPanel(mRowPanels[row], 0, pos * mRowPanelHeight + vgap);
+}
+
+void LLOutfitGallery::removeLastRow()
+{
+ mRowCount--;
+ mGalleryPanel->removeChild(mLastRowPanel);
+ mRowPanels.pop_back();
+ mLastRowPanel = mRowPanels.back();
+}
+
+LLPanel* LLOutfitGallery::addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap)
+{
+ LLPanel* lpanel = buildItemPanel(pos * mItemWidth + hgap);
+ lpanel->addChild(item);
+ row_stack->addChild(lpanel);
+ mItemPanels.push_back(lpanel);
+ return lpanel;
+}
+
+void LLOutfitGallery::addToGallery(LLOutfitGalleryItem* item)
+{
+ if(item->isHidden())
+ {
+ mHiddenItems.push_back(item);
+ return;
+ }
+ mItemsAddedCount++;
+ mItemIndexMap[item] = mItemsAddedCount - 1;
+ int n = mItemsAddedCount;
+ int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1;
+ int n_prev = n - 1;
+ int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1;
+
+ bool add_row = row_count != row_count_prev;
+ int pos = 0;
+ if (add_row)
+ {
+ for (int i = 0; i < row_count_prev; i++)
+ {
+ moveRowUp(i);
+ }
+ mLastRowPanel = addLastRow();
+ mRowPanels.push_back(mLastRowPanel);
+ }
+ pos = (n - 1) % mItemsInRow;
+ mItems.push_back(item);
+ addToRow(mLastRowPanel, item, pos, mHorizontalGap * pos);
+ reshapeGalleryPanel(row_count);
+}
+
+
+void LLOutfitGallery::removeFromGalleryLast(LLOutfitGalleryItem* item)
+{
+ if(item->isHidden())
+ {
+ mHiddenItems.pop_back();
+ return;
+ }
+ int n_prev = mItemsAddedCount;
+ int n = mItemsAddedCount - 1;
+ int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1;
+ int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1;
+ mItemsAddedCount--;
+
+ bool remove_row = row_count != row_count_prev;
+ removeFromLastRow(mItems[mItemsAddedCount]);
+ mItems.pop_back();
+ if (remove_row)
+ {
+ for (int i = 0; i < row_count_prev - 1; i++)
+ {
+ moveRowDown(i);
+ }
+ removeLastRow();
+ }
+ reshapeGalleryPanel(row_count);
+}
+
+
+void LLOutfitGallery::removeFromGalleryMiddle(LLOutfitGalleryItem* item)
+{
+ if(item->isHidden())
+ {
+ mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end());
+ return;
+ }
+ int n = mItemIndexMap[item];
+ mItemIndexMap.erase(item);
+ std::vector<LLOutfitGalleryItem*> saved;
+ for (int i = mItemsAddedCount - 1; i > n; i--)
+ {
+ saved.push_back(mItems[i]);
+ removeFromGalleryLast(mItems[i]);
+ }
+ removeFromGalleryLast(mItems[n]);
+ int saved_count = saved.size();
+ for (int i = 0; i < saved_count; i++)
+ {
+ addToGallery(saved.back());
+ saved.pop_back();
+ }
+}
+
+void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item)
+{
+ mItemPanels.back()->removeChild(item);
+ mLastRowPanel->removeChild(mItemPanels.back());
+ mItemPanels.pop_back();
+}
+
+LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name)
+{
+ LLOutfitGalleryItem::Params giparams;
+ LLOutfitGalleryItem* gitem = LLUICtrlFactory::create<LLOutfitGalleryItem>(giparams);
+ gitem->reshape(mItemWidth, mItemHeight);
+ gitem->setVisible(true);
+ gitem->setFollowsLeft();
+ gitem->setFollowsTop();
+ gitem->setOutfitName(name);
+ return gitem;
+}
+
+void LLOutfitGallery::buildGalleryPanel(int row_count)
+{
+ LLPanel::Params params;
+ mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params);
+ reshapeGalleryPanel(row_count);
+}
+
+void LLOutfitGallery::reshapeGalleryPanel(int row_count)
+{
+ int bottom = 0;
+ int left = 0;
+ int height = row_count * (mRowPanelHeight + mVerticalGap);
+ LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom);
+ mGalleryPanel->setRect(rect);
+ mGalleryPanel->reshape(mGalleryWidth, height);
+ mGalleryPanel->setVisible(true);
+ mGalleryPanel->setFollowsLeft();
+ mGalleryPanel->setFollowsTop();
+}
+
+LLPanel* LLOutfitGallery::buildItemPanel(int left)
+{
+ LLPanel::Params lpparams;
+ int top = 0;
+ LLPanel* lpanel = LLUICtrlFactory::create<LLPanel>(lpparams);
+ LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top);
+ lpanel->setRect(rect);
+ lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight);
+ lpanel->setVisible(true);
+ lpanel->setFollowsLeft();
+ lpanel->setFollowsTop();
+ return lpanel;
+}
+
+LLPanel* LLOutfitGallery::buildRowPanel(int left, int bottom)
+{
+ LLPanel::Params sparams;
+ LLPanel* stack = LLUICtrlFactory::create<LLPanel>(sparams);
+ moveRowPanel(stack, left, bottom);
+ return stack;
+}
+
+void LLOutfitGallery::moveRowPanel(LLPanel* stack, int left, int bottom)
+{
+ LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom);
+ stack->setRect(rect);
+ stack->reshape(mRowPanelWidth, mRowPanelHeight);
+ stack->setVisible(true);
+ stack->setFollowsLeft();
+ stack->setFollowsTop();
+}
+
+LLOutfitGallery::~LLOutfitGallery()
+{
+ delete mOutfitGalleryMenu;
+
+ if (gInventory.containsObserver(mTexturesObserver))
+ {
+ gInventory.removeObserver(mTexturesObserver);
+ }
+ delete mTexturesObserver;
+
+ if (gInventory.containsObserver(mOutfitsObserver))
+ {
+ gInventory.removeObserver(mOutfitsObserver);
+ }
+ delete mOutfitsObserver;
+}
+
+void LLOutfitGallery::setFilterSubString(const std::string& string)
+{
+ sFilterSubString = string;
+ reArrangeRows();
+}
+
+void LLOutfitGallery::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id)
+{
+ if (mOutfitMap[base_id])
+ {
+ mOutfitMap[base_id]->setOutfitWorn(true);
+ }
+ if (mOutfitMap[prev_id])
+ {
+ mOutfitMap[prev_id]->setOutfitWorn(false);
+ }
+}
+
+void LLOutfitGallery::applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring)
+{
+ if (!item) return;
+
+ std::string outfit_name = item->getItemName();
+ LLStringUtil::toUpper(outfit_name);
+
+ std::string cur_filter = filter_substring;
+ LLStringUtil::toUpper(cur_filter);
+
+ bool hidden = (std::string::npos == outfit_name.find(cur_filter));
+ item->setHidden(hidden);
+}
+
+void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
+{
+}
+
+void LLOutfitGallery::getCurrentCategories(uuid_vec_t& vcur)
+{
+ for (outfit_map_t::const_iterator iter = mOutfitMap.begin();
+ iter != mOutfitMap.end();
+ iter++)
+ {
+ if ((*iter).second != NULL)
+ {
+ vcur.push_back((*iter).first);
+ }
+ }
+}
+
+void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
+{
+ LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+ if (!cat) return;
+
+ std::string name = cat->getName();
+ LLOutfitGalleryItem* item = buildGalleryItem(name);
+ mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item));
+ item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this,
+ _1, _2, _3, cat_id));
+ LLWearableItemsList* list = NULL;
+ item->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id));
+ if (mGalleryCreated)
+ {
+ addToGallery(item);
+ }
+
+ LLViewerInventoryCategory* outfit_category = gInventory.getCategory(cat_id);
+ if (!outfit_category)
+ return;
+
+ if (mOutfitsObserver == NULL)
+ {
+ mOutfitsObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mOutfitsObserver);
+ }
+
+ // Start observing changes in "My Outfits" category.
+ mOutfitsObserver->addCategory(cat_id,
+ boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id));
+
+ outfit_category->fetch();
+ refreshOutfit(cat_id);
+}
+
+void LLOutfitGallery::updateRemovedCategory(LLUUID cat_id)
+{
+ outfit_map_t::iterator outfits_iter = mOutfitMap.find(cat_id);
+ if (outfits_iter != mOutfitMap.end())
+ {
+ // 0. Remove category from observer.
+ mOutfitsObserver->removeCategory(cat_id);
+
+ //const LLUUID& outfit_id = outfits_iter->first;
+ LLOutfitGalleryItem* item = outfits_iter->second;
+
+ // An outfit is removed from the list. Do the following:
+ // 2. Remove the outfit from selection.
+ deselectOutfit(cat_id);
+
+ // 3. Remove category UUID to accordion tab mapping.
+ mOutfitMap.erase(outfits_iter);
+
+ // 4. Remove outfit from gallery.
+ removeFromGalleryMiddle(item);
+
+ // kill removed item
+ if (item != NULL)
+ {
+ item->die();
+ }
+ }
+
+}
+
+void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name)
+{
+ outfit_map_t::iterator outfit_iter = mOutfitMap.find(cat->getUUID());
+ if (outfit_iter != mOutfitMap.end())
+ {
+ // Update name of outfit in gallery
+ LLOutfitGalleryItem* item = outfit_iter->second;
+ if (item)
+ {
+ item->setOutfitName(name);
+ }
+ }
+}
+
+void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
+{
+ if (mOutfitMenu && cat_id.notNull())
+ {
+ uuid_vec_t selected_uuids;
+ selected_uuids.push_back(cat_id);
+ mOutfitGalleryMenu->show(ctrl, selected_uuids, x, y);
+ }
+}
+
+void LLOutfitGallery::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+{
+ if (mSelectedOutfitUUID == category_id)
+ return;
+ if (mOutfitMap[mSelectedOutfitUUID])
+ {
+ mOutfitMap[mSelectedOutfitUUID]->setSelected(FALSE);
+ }
+ if (mOutfitMap[category_id])
+ {
+ mOutfitMap[category_id]->setSelected(TRUE);
+ }
+}
+
+void LLOutfitGallery::wearSelectedOutfit()
+{
+ LLAppearanceMgr::instance().replaceCurrentOutfit(getSelectedOutfitUUID());
+}
+
+bool LLOutfitGallery::hasItemSelected()
+{
+ return false;
+}
+
+bool LLOutfitGallery::canWearSelected()
+{
+ return false;
+}
+
+bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id)
+{
+ if (mOutfitMap[outfit_cat_id])
+ {
+ return mOutfitMap[outfit_cat_id]->isDefaultImage();
+ }
+ return false;
+}
+
+void LLOutfitGallery::updateMessageVisibility()
+{
+ if(mItems.empty())
+ {
+ mMessageTextBox->setVisible(TRUE);
+ mScrollPanel->setVisible(FALSE);
+ std::string message = sFilterSubString.empty()? getString("no_outfits_msg") : getString("no_matched_outfits_msg");
+ mMessageTextBox->setValue(message);
+ }
+ else
+ {
+ mScrollPanel->setVisible(TRUE);
+ mMessageTextBox->setVisible(FALSE);
+ }
+}
+
+LLOutfitListGearMenuBase* LLOutfitGallery::createGearMenu()
+{
+ return new LLOutfitGalleryGearMenu(this);
+}
+
+static LLDefaultChildRegistry::Register<LLOutfitGalleryItem> r("outfit_gallery_item");
+
+LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p)
+ : LLPanel(p),
+ mTexturep(NULL),
+ mSelected(false),
+ mWorn(false),
+ mDefaultImage(true),
+ mOutfitName("")
+{
+ buildFromFile("panel_outfit_gallery_item.xml");
+}
+
+LLOutfitGalleryItem::~LLOutfitGalleryItem()
+{
+
+}
+
+BOOL LLOutfitGalleryItem::postBuild()
+{
+ setDefaultImage();
+
+ mOutfitNameText = getChild<LLTextBox>("outfit_name");
+ mOutfitWornText = getChild<LLTextBox>("outfit_worn_text");
+ mFotoBgPanel = getChild<LLPanel>("foto_bg_panel");
+ mTextBgPanel = getChild<LLPanel>("text_bg_panel");
+ setOutfitWorn(false);
+ mHidden = false;
+ return TRUE;
+}
+
+void LLOutfitGalleryItem::draw()
+{
+ LLPanel::draw();
+
+ // Draw border
+ LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "OutfitGalleryItemSelected" : "OutfitGalleryItemUnselected", LLColor4::white);
+ LLRect border = getChildView("preview_outfit")->getRect();
+ border.mRight = border.mRight + 1;
+ gl_rect_2d(border, border_color.get(), FALSE);
+
+ // If the floater is focused, don't apply its alpha to the texture (STORM-677).
+ const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+ if (mTexturep)
+ {
+ LLRect interior = border;
+ interior.stretch(-1);
+
+ gl_draw_scaled_image(interior.mLeft - 1, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
+
+ // Pump the priority
+ mTexturep->addTextureStats((F32)(interior.getWidth() * interior.getHeight()));
+ }
+
+}
+
+void LLOutfitGalleryItem::setOutfitName(std::string name)
+{
+ mOutfitNameText->setText(name);
+ mOutfitNameText->setToolTip(name);
+ mOutfitName = name;
+}
+
+void LLOutfitGalleryItem::setOutfitWorn(bool value)
+{
+ mWorn = value;
+ LLStringUtil::format_map_t worn_string_args;
+ std::string worn_string = getString("worn_string", worn_string_args);
+ LLUIColor text_color = LLUIColorTable::instance().getColor(mSelected ? "White" : (mWorn ? "OutfitGalleryItemWorn" : "White"), LLColor4::white);
+ mOutfitWornText->setReadOnlyColor(text_color.get());
+ mOutfitNameText->setReadOnlyColor(text_color.get());
+ mOutfitWornText->setValue(value ? worn_string : "");
+}
+
+void LLOutfitGalleryItem::setSelected(bool value)
+{
+ mSelected = value;
+ mTextBgPanel->setBackgroundVisible(value);
+ setOutfitWorn(mWorn);
+}
+
+BOOL LLOutfitGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ setFocus(TRUE);
+ return LLUICtrl::handleMouseDown(x, y, mask);
+}
+
+BOOL LLOutfitGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ setFocus(TRUE);
+ return LLUICtrl::handleRightMouseDown(x, y, mask);
+}
+
+void LLOutfitGalleryItem::setImageAssetId(LLUUID image_asset_id)
+{
+ mImageAssetId = image_asset_id;
+ mTexturep = LLViewerTextureManager::getFetchedTexture(image_asset_id, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ getChildView("preview_outfit")->setVisible(FALSE);
+ mDefaultImage = false;
+}
+
+LLUUID LLOutfitGalleryItem::getImageAssetId()
+{
+ return mImageAssetId;
+}
+
+void LLOutfitGalleryItem::setDefaultImage()
+{
+ mTexturep = NULL;
+ mImageAssetId.setNull();
+ getChildView("preview_outfit")->setVisible(TRUE);
+ mDefaultImage = true;
+}
+
+LLContextMenu* LLOutfitGalleryContextMenu::createMenu()
+{
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ LLUUID selected_id = mUUIDs.front();
+
+ registrar.add("Outfit.WearReplace",
+ boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.WearAdd",
+ boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.TakeOff",
+ boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.Edit", boost::bind(editOutfit));
+ registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
+ registrar.add("Outfit.Delete", boost::bind(&LLOutfitGalleryContextMenu::onRemoveOutfit, this, selected_id));
+ registrar.add("Outfit.Create", boost::bind(&LLOutfitGalleryContextMenu::onCreate, this, _2));
+ registrar.add("Outfit.UploadPhoto", boost::bind(&LLOutfitGalleryContextMenu::onUploadPhoto, this, selected_id));
+ registrar.add("Outfit.SelectPhoto", boost::bind(&LLOutfitGalleryContextMenu::onSelectPhoto, this, selected_id));
+ registrar.add("Outfit.TakeSnapshot", boost::bind(&LLOutfitGalleryContextMenu::onTakeSnapshot, this, selected_id));
+ registrar.add("Outfit.RemovePhoto", boost::bind(&LLOutfitGalleryContextMenu::onRemovePhoto, this, selected_id));
+ enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitGalleryContextMenu::onEnable, this, _2));
+ enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitGalleryContextMenu::onVisible, this, _2));
+
+ return createFromFile("menu_gallery_outfit_tab.xml");
+}
+
+void LLOutfitGalleryContextMenu::onUploadPhoto(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->uploadPhoto(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onSelectPhoto(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->onSelectPhoto(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onRemovePhoto(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->checkRemovePhoto(outfit_cat_id);
+ gallery->refreshOutfit(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onTakeSnapshot(const LLUUID& outfit_cat_id)
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && outfit_cat_id.notNull())
+ {
+ gallery->onTakeSnapshot(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onRemoveOutfit(const LLUUID& outfit_cat_id)
+{
+ LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation, this, _1, _2, outfit_cat_id));
+}
+
+void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return; // canceled
+
+ if (outfit_cat_id.notNull())
+ {
+ gInventory.removeCategory(outfit_cat_id);
+ }
+}
+
+void LLOutfitGalleryContextMenu::onCreate(const LLSD& data)
+{
+ LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
+ if (type == LLWearableType::WT_NONE)
+ {
+ LL_WARNS() << "Invalid wearable type" << LL_ENDL;
+ return;
+ }
+
+ LLAgentWearables::createWearable(type, true);
+}
+
+bool LLOutfitGalleryContextMenu::onEnable(LLSD::String param)
+{
+ return LLOutfitContextMenu::onEnable(param);
+}
+
+bool LLOutfitGalleryContextMenu::onVisible(LLSD::String param)
+{
+ if ("remove_photo" == param)
+ {
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_id = mUUIDs.front();
+ if (gallery && selected_id.notNull())
+ {
+ return !gallery->hasDefaultImage(selected_id);
+ }
+ }
+ return LLOutfitContextMenu::onVisible(param);
+}
+
+LLOutfitGalleryGearMenu::LLOutfitGalleryGearMenu(LLOutfitListBase* olist)
+ : LLOutfitListGearMenuBase(olist)
+{
+}
+
+void LLOutfitGalleryGearMenu::onUpdateItemsVisibility()
+{
+ if (!mMenu) return;
+ bool have_selection = getSelectedOutfitID().notNull();
+ mMenu->setItemVisible("expand", FALSE);
+ mMenu->setItemVisible("collapse", FALSE);
+ mMenu->setItemVisible("upload_photo", have_selection);
+ mMenu->setItemVisible("select_photo", have_selection);
+ mMenu->setItemVisible("take_snapshot", have_selection);
+ mMenu->setItemVisible("remove_photo", !hasDefaultImage());
+ mMenu->setItemVisible("sepatator3", TRUE);
+ mMenu->setItemVisible("sort_folders_by_name", TRUE);
+ LLOutfitListGearMenuBase::onUpdateItemsVisibility();
+}
+
+void LLOutfitGalleryGearMenu::onUploadFoto()
+{
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery && selected_outfit_id.notNull())
+ {
+ gallery->uploadPhoto(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onSelectPhoto()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && !selected_outfit_id.isNull())
+ {
+ gallery->onSelectPhoto(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onRemovePhoto()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && !selected_outfit_id.isNull())
+ {
+ gallery->checkRemovePhoto(selected_outfit_id);
+ gallery->refreshOutfit(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onTakeSnapshot()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && !selected_outfit_id.isNull())
+ {
+ gallery->onTakeSnapshot(selected_outfit_id);
+ }
+}
+
+void LLOutfitGalleryGearMenu::onChangeSortOrder()
+{
+ bool sort_by_name = !gSavedSettings.getBOOL("OutfitGallerySortByName");
+ gSavedSettings.setBOOL("OutfitGallerySortByName", sort_by_name);
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ if (gallery)
+ {
+ gallery->reArrangeRows();
+ }
+}
+
+bool LLOutfitGalleryGearMenu::hasDefaultImage()
+{
+ LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
+ LLUUID selected_outfit_id = getSelectedOutfitID();
+ if (gallery && selected_outfit_id.notNull())
+ {
+ return gallery->hasDefaultImage(selected_outfit_id);
+ }
+ return true;
+}
+
+void LLOutfitGallery::onTextureSelectionChanged(LLInventoryItem* itemp)
+{
+}
+
+void LLOutfitGallery::loadPhotos()
+{
+ //Iterate over inventory
+ LLUUID textures = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);
+ LLViewerInventoryCategory* textures_category = gInventory.getCategory(textures);
+ if (!textures_category)
+ return;
+ if (mTexturesObserver == NULL)
+ {
+ mTexturesObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mTexturesObserver);
+ }
+
+ // Start observing changes in "Textures" category.
+ mTexturesObserver->addCategory(textures,
+ boost::bind(&LLOutfitGallery::refreshTextures, this, textures));
+
+ textures_category->fetch();
+}
+
+void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
+{
+ LLViewerInventoryCategory* category = gInventory.getCategory(category_id);
+ {
+ bool photo_loaded = false;
+ LLInventoryModel::cat_array_t sub_cat_array;
+ LLInventoryModel::item_array_t outfit_item_array;
+ // Collect all sub-categories of a given category.
+ gInventory.collectDescendents(
+ category->getUUID(),
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ BOOST_FOREACH(LLViewerInventoryItem* outfit_item, outfit_item_array)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ LLUUID asset_id = linked_item->getAssetUUID();
+ mOutfitMap[category_id]->setImageAssetId(asset_id);
+ photo_loaded = true;
+ std::string linked_item_name = linked_item->getName();
+ if (!mOutfitRenamePending.isNull() && mOutfitRenamePending.asString() == linked_item_name)
+ {
+ LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(mOutfitRenamePending);
+ LLStringUtil::format_map_t photo_string_args;
+ photo_string_args["OUTFIT_NAME"] = outfit_cat->getName();
+ std::string new_name = getString("outfit_photo_string", photo_string_args);
+ LLSD updates;
+ updates["name"] = new_name;
+ update_inventory_item(linked_item->getUUID(), updates, NULL);
+ mOutfitRenamePending.setNull();
+ LLFloater* inv_floater = LLFloaterReg::getInstance("inventory");
+ if (inv_floater)
+ {
+ inv_floater->closeFloater();
+ }
+ LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance");
+ if (appearance_floater)
+ {
+ appearance_floater->setFocus(TRUE);
+ }
+ }
+ break;
+ }
+ if (!photo_loaded)
+ {
+ mOutfitMap[category_id]->setDefaultImage();
+ }
+ }
+ }
+
+ if (mGalleryCreated && !LLApp::isQuitting())
+ {
+ reArrangeRows();
+ }
+}
+
+void LLOutfitGallery::refreshTextures(const LLUUID& category_id)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+
+ // Collect all sub-categories of a given category.
+ LLIsType is_texture(LLAssetType::AT_TEXTURE);
+ gInventory.collectDescendentsIf(
+ category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_texture);
+
+ //Find texture which contain pending outfit ID string in name
+ LLViewerInventoryItem* photo_upload_item = NULL;
+ BOOST_FOREACH(LLViewerInventoryItem* item, item_array)
+ {
+ std::string name = item->getName();
+ if (!mOutfitLinkPending.isNull() && name == mOutfitLinkPending.asString())
+ {
+ photo_upload_item = item;
+ break;
+ }
+ }
+
+ if (photo_upload_item != NULL)
+ {
+ LLUUID photo_item_id = photo_upload_item->getUUID();
+ LLInventoryObject* upload_object = gInventory.getObject(photo_item_id);
+ if (!upload_object)
+ {
+ LL_WARNS() << "LLOutfitGallery::refreshTextures added_object is null!" << LL_ENDL;
+ }
+ else
+ {
+ linkPhotoToOutfit(photo_item_id, mOutfitLinkPending);
+ mOutfitRenamePending = mOutfitLinkPending;
+ mOutfitLinkPending.setNull();
+ }
+ }
+}
+
+void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)
+{
+ outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id);
+ if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull())
+ {
+ return;
+ }
+
+ LLFilePicker& picker = LLFilePicker::instance();
+ if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE))
+ {
+ std::string filename = picker.getFirstFile();
+ LLLocalBitmap* unit = new LLLocalBitmap(filename);
+ if (unit->getValid())
+ {
+ std::string exten = gDirUtilp->getExtension(filename);
+ U32 codec = LLImageBase::getCodecFromExtension(exten);
+
+ LLImageDimensionsInfo image_info;
+ std::string image_load_error;
+ if (!image_info.load(filename, codec))
+ {
+ image_load_error = image_info.getLastError();
+ }
+
+ S32 max_width = MAX_OUTFIT_PHOTO_WIDTH;
+ S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT;
+
+ if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height))
+ {
+ LLStringUtil::format_map_t args;
+ args["WIDTH"] = llformat("%d", max_width);
+ args["HEIGHT"] = llformat("%d", max_height);
+
+ image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args);
+ }
+
+ if (!image_load_error.empty())
+ {
+ LLSD subst;
+ subst["REASON"] = image_load_error;
+ LLNotificationsUtil::add("OutfitPhotoLoadError", subst);
+ return;
+ }
+
+ S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).
+ void *nruserdata = NULL;
+ nruserdata = (void *)&outfit_id;
+
+ LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id);
+ if (!outfit_cat) return;
+
+ checkRemovePhoto(outfit_id);
+ std::string upload_pending_name = outfit_id.asString();
+ std::string upload_pending_desc = "";
+ LLAssetStorage::LLStoreAssetCallback callback = NULL;
+ LLUUID photo_id = upload_new_resource(filename, // file
+ upload_pending_name,
+ upload_pending_desc,
+ 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
+ upload_pending_name, callback, expected_upload_cost, nruserdata);
+ mOutfitLinkPending = outfit_id;
+ }
+ }
+}
+
+void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id)
+{
+ LLPointer<LLInventoryCallback> cb = new LLUpdateGalleryOnPhotoLinked();
+ link_inventory_object(outfit_id, photo_id, cb);
+}
+
+bool LLOutfitGallery::checkRemovePhoto(LLUUID outfit_id)
+{
+ LLAppearanceMgr::instance().removeOutfitPhoto(outfit_id);
+ return true;
+}
+
+void LLUpdateGalleryOnPhotoLinked::fire(const LLUUID& inv_item_id)
+{
+}
+
+LLUUID LLOutfitGallery::getPhotoAssetId(const LLUUID& outfit_id)
+{
+ outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id);
+ if (outfit_it != mOutfitMap.end())
+ {
+ return outfit_it->second->getImageAssetId();
+ }
+ return LLUUID();
+}
+
+LLUUID LLOutfitGallery::getDefaultPhoto()
+{
+ return LLUUID();
+}
+
+void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id)
+{
+ LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
+
+ if (floaterp && op == LLTextureCtrl::TEXTURE_SELECT)
+ {
+ LLUUID image_item_id;
+ if (id.notNull())
+ {
+ image_item_id = id;
+ }
+ else
+ {
+ image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE);
+ if (image_item_id.isNull())
+ {
+ LL_WARNS() << "id or image_item_id is NULL!" << LL_ENDL;
+ return;
+ }
+ }
+
+ std::string image_load_error;
+ S32 max_width = MAX_OUTFIT_PHOTO_WIDTH;
+ S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT;
+ if (mTextureSelected.isNull() ||
+ mTextureSelected->getFullWidth() == 0 ||
+ mTextureSelected->getFullHeight() == 0)
+ {
+ image_load_error = LLTrans::getString("outfit_photo_verify_dimensions_error");
+ LL_WARNS() << "Cannot verify selected texture dimensions" << LL_ENDL;
+ return;
+ }
+ S32 width = mTextureSelected->getFullWidth();
+ S32 height = mTextureSelected->getFullHeight();
+ if ((width > max_width) || (height > max_height))
+ {
+ LLStringUtil::format_map_t args;
+ args["WIDTH"] = llformat("%d", max_width);
+ args["HEIGHT"] = llformat("%d", max_height);
+
+ image_load_error = LLTrans::getString("outfit_photo_select_dimensions_error", args);
+ }
+
+ if (!image_load_error.empty())
+ {
+ LLSD subst;
+ subst["REASON"] = image_load_error;
+ LLNotificationsUtil::add("OutfitPhotoLoadError", subst);
+ return;
+ }
+
+ checkRemovePhoto(getSelectedOutfitUUID());
+ linkPhotoToOutfit(image_item_id, getSelectedOutfitUUID());
+ }
+}
+
+void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)
+{
+ if (selected_outfit_id.notNull())
+ {
+
+ // show hourglass cursor when loading inventory window
+ // because inventory construction is slooow
+ getWindow()->setCursor(UI_CURSOR_WAIT);
+ LLFloater* floaterp = mFloaterHandle.get();
+
+ // Show the dialog
+ if (floaterp)
+ {
+ floaterp->openFloater();
+ }
+ else
+ {
+ floaterp = new LLFloaterTexturePicker(
+ this,
+ getPhotoAssetId(selected_outfit_id),
+ getPhotoAssetId(selected_outfit_id),
+ getPhotoAssetId(selected_outfit_id),
+ FALSE,
+ TRUE,
+ "SELECT PHOTO",
+ PERM_NONE,
+ PERM_NONE,
+ PERM_NONE,
+ FALSE,
+ NULL);
+
+ mFloaterHandle = floaterp->getHandle();
+ mTextureSelected = NULL;
+
+ LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
+ if (texture_floaterp)
+ {
+ texture_floaterp->setTextureSelectedCallback(boost::bind(&LLOutfitGallery::onTextureSelectionChanged, this, _1));
+ texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2));
+ texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1));
+ texture_floaterp->setLocalTextureEnabled(FALSE);
+ }
+
+ floaterp->openFloater();
+ }
+ floaterp->setFocus(TRUE);
+ }
+}
+
+void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id)
+{
+ LLFloaterReg::toggleInstanceOrBringToFront("outfit_snapshot");
+ LLFloaterOutfitSnapshot* snapshot_floater = LLFloaterOutfitSnapshot::getInstance();
+ if (snapshot_floater)
+ {
+ snapshot_floater->setOutfitID(selected_outfit_id);
+ snapshot_floater->getInstance()->setGallery(this);
+ }
+}
+
+void LLOutfitGallery::onBeforeOutfitSnapshotSave()
+{
+ LLUUID selected_outfit_id = getSelectedOutfitUUID();
+ if (!selected_outfit_id.isNull())
+ {
+ checkRemovePhoto(selected_outfit_id);
+ }
+}
+
+void LLOutfitGallery::onAfterOutfitSnapshotSave()
+{
+ LLUUID selected_outfit_id = getSelectedOutfitUUID();
+ if (!selected_outfit_id.isNull())
+ {
+ mOutfitLinkPending = selected_outfit_id;
+ }
+}
+
+void LLOutfitGallery::onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture)
+{
+ mTextureSelected = texture;
+}
diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h
new file mode 100644
index 0000000000..6b13f264a4
--- /dev/null
+++ b/indra/newview/lloutfitgallery.h
@@ -0,0 +1,284 @@
+/**
+ * @file lloutfitgallery.h
+ * @author Pavlo Kryvych
+ * @brief Visual gallery of agent's outfits for My Appearance side panel
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLOUTFITGALLERYCTRL_H
+#define LL_LLOUTFITGALLERYCTRL_H
+
+#include "llextendedstatus.h"
+#include "lliconctrl.h"
+#include "lllayoutstack.h"
+#include "lloutfitslist.h"
+#include "llpanelappearancetab.h"
+#include "lltexturectrl.h"
+#include "llviewertexture.h"
+
+#include <vector>
+
+class LLVFS;
+class LLOutfitGallery;
+class LLOutfitGalleryItem;
+class LLOutfitListGearMenuBase;
+class LLOutfitGalleryGearMenu;
+class LLOutfitGalleryContextMenu;
+
+class LLUpdateGalleryOnPhotoLinked : public LLInventoryCallback
+{
+public:
+ LLUpdateGalleryOnPhotoLinked(){}
+ virtual ~LLUpdateGalleryOnPhotoLinked(){}
+ /* virtual */ void fire(const LLUUID& inv_item_id);
+private:
+};
+
+class LLOutfitGallery : public LLOutfitListBase
+{
+public:
+ friend class LLOutfitGalleryGearMenu;
+ friend class LLOutfitGalleryContextMenu;
+ friend class LLUpdateGalleryOnPhotoLinked;
+
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<S32> row_panel_height;
+ Optional<S32> row_panel_width_factor;
+ Optional<S32> gallery_width_factor;
+ Optional<S32> vertical_gap;
+ Optional<S32> horizontal_gap;
+ Optional<S32> item_width;
+ Optional<S32> item_height;
+ Optional<S32> item_horizontal_gap;
+ Optional<S32> items_in_row;
+
+ Params();
+ };
+
+ static const LLOutfitGallery::Params& getDefaultParams();
+
+ LLOutfitGallery(const LLOutfitGallery::Params& params = getDefaultParams());
+ virtual ~LLOutfitGallery();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& info);
+ /*virtual*/ void draw();
+
+ void onSelectPhoto(LLUUID selected_outfit_id);
+ void onTakeSnapshot(LLUUID selected_outfit_id);
+
+ void wearSelectedOutfit();
+
+
+ /*virtual*/ void setFilterSubString(const std::string& string);
+
+ /*virtual*/ void getCurrentCategories(uuid_vec_t& vcur);
+ /*virtual*/ void updateAddedCategory(LLUUID cat_id);
+ /*virtual*/ void updateRemovedCategory(LLUUID cat_id);
+ /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name);
+
+ /*virtual*/ bool hasItemSelected();
+ /*virtual*/ bool canWearSelected();
+
+ /*virtual*/ bool getHasExpandableFolders() { return FALSE; }
+
+ void updateMessageVisibility();
+ bool hasDefaultImage(const LLUUID& outfit_cat_id);
+
+ void refreshTextures(const LLUUID& category_id);
+ void refreshOutfit(const LLUUID& category_id);
+
+ void onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LLUUID id);
+ void onTexturePickerUpdateImageStats(LLPointer<LLViewerTexture> texture);
+ void onBeforeOutfitSnapshotSave();
+ void onAfterOutfitSnapshotSave();
+protected:
+ /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
+ /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+ /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
+ /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
+
+ /*virtual*/ void onCollapseAllFolders() {}
+ /*virtual*/ void onExpandAllFolders() {}
+ /*virtual*/ LLOutfitListGearMenuBase* createGearMenu();
+
+ void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring);
+
+private:
+ void loadPhotos();
+ void uploadPhoto(LLUUID outfit_id);
+ LLUUID getPhotoAssetId(const LLUUID& outfit_id);
+ LLUUID getDefaultPhoto();
+ void linkPhotoToOutfit(LLUUID outfit_id, LLUUID photo_id);
+ bool checkRemovePhoto(LLUUID outfit_id);
+ void addToGallery(LLOutfitGalleryItem* item);
+ void removeFromGalleryLast(LLOutfitGalleryItem* item);
+ void removeFromGalleryMiddle(LLOutfitGalleryItem* item);
+ LLPanel* addLastRow();
+ void removeLastRow();
+ void moveRowUp(int row);
+ void moveRowDown(int row);
+ void moveRow(int row, int pos);
+ LLPanel* addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap);
+ void removeFromLastRow(LLOutfitGalleryItem* item);
+ void reArrangeRows(S32 row_diff = 0);
+ void updateRowsIfNeeded();
+ void updateGalleryWidth();
+
+ LLOutfitGalleryItem* buildGalleryItem(std::string name);
+
+ void onTextureSelectionChanged(LLInventoryItem* itemp);
+
+ void buildGalleryPanel(int row_count);
+ void reshapeGalleryPanel(int row_count);
+ LLPanel* buildItemPanel(int left);
+ LLPanel* buildRowPanel(int left, int bottom);
+ void moveRowPanel(LLPanel* stack, int left, int bottom);
+ std::vector<LLPanel*> mRowPanels;
+ std::vector<LLPanel*> mItemPanels;
+ std::vector<LLOutfitGalleryItem*> mItems;
+ std::vector<LLOutfitGalleryItem*> mHiddenItems;
+ LLScrollContainer* mScrollPanel;
+ LLPanel* mGalleryPanel;
+ LLPanel* mLastRowPanel;
+ LLUUID mOutfitLinkPending;
+ LLUUID mOutfitRenamePending;
+ LLTextBox* mMessageTextBox;
+ bool mGalleryCreated;
+ int mRowCount;
+ int mItemsAddedCount;
+ LLPointer<LLViewerTexture> mTextureSelected;
+ /* Params */
+ int mRowPanelHeight;
+ int mVerticalGap;
+ int mHorizontalGap;
+ int mItemWidth;
+ int mItemHeight;
+ int mItemHorizontalGap;
+ int mItemsInRow;
+ int mRowPanelWidth;
+ int mGalleryWidth;
+ int mRowPanWidthFactor;
+ int mGalleryWidthFactor;
+
+ LLListContextMenu* mOutfitGalleryMenu;
+
+ LLHandle<LLFloater> mFloaterHandle;
+
+ typedef std::map<LLUUID, LLOutfitGalleryItem*> outfit_map_t;
+ typedef outfit_map_t::value_type outfit_map_value_t;
+ outfit_map_t mOutfitMap;
+ typedef std::map<LLOutfitGalleryItem*, int> item_num_map_t;
+ typedef item_num_map_t::value_type item_numb_map_value_t;
+ item_num_map_t mItemIndexMap;
+
+
+ LLInventoryCategoriesObserver* mTexturesObserver;
+ LLInventoryCategoriesObserver* mOutfitsObserver;
+};
+class LLOutfitGalleryContextMenu : public LLOutfitContextMenu
+{
+public:
+
+ friend class LLOutfitGallery;
+ LLOutfitGalleryContextMenu(LLOutfitListBase* outfit_list)
+ : LLOutfitContextMenu(outfit_list),
+ mOutfitList(outfit_list){}
+protected:
+ /* virtual */ LLContextMenu* createMenu();
+ bool onEnable(LLSD::String param);
+ bool onVisible(LLSD::String param);
+ void onUploadPhoto(const LLUUID& outfit_cat_id);
+ void onSelectPhoto(const LLUUID& outfit_cat_id);
+ void onRemovePhoto(const LLUUID& outfit_cat_id);
+ void onTakeSnapshot(const LLUUID& outfit_cat_id);
+ void onCreate(const LLSD& data);
+ void onRemoveOutfit(const LLUUID& outfit_cat_id);
+ void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response, const LLUUID& outfit_cat_id);
+private:
+ LLOutfitListBase* mOutfitList;
+};
+
+
+class LLOutfitGalleryGearMenu : public LLOutfitListGearMenuBase
+{
+public:
+ friend class LLOutfitGallery;
+ LLOutfitGalleryGearMenu(LLOutfitListBase* olist);
+
+protected:
+ /*virtual*/ void onUpdateItemsVisibility();
+private:
+ /*virtual*/ void onUploadFoto();
+ /*virtual*/ void onSelectPhoto();
+ /*virtual*/ void onTakeSnapshot();
+ /*virtual*/ void onRemovePhoto();
+ /*virtual*/ void onChangeSortOrder();
+
+ bool hasDefaultImage();
+};
+
+class LLOutfitGalleryItem : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {};
+
+ LLOutfitGalleryItem(const Params& p);
+ virtual ~LLOutfitGalleryItem();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ void setDefaultImage();
+ void setImageAssetId(LLUUID asset_id);
+ LLUUID getImageAssetId();
+ void setOutfitName(std::string name);
+ void setOutfitWorn(bool value);
+ void setSelected(bool value);
+
+ std::string getItemName() {return mOutfitName;}
+ bool isDefaultImage() {return mDefaultImage;}
+
+ bool isHidden() {return mHidden;}
+ void setHidden(bool hidden) {mHidden = hidden;}
+
+private:
+ LLPointer<LLViewerFetchedTexture> mTexturep;
+ LLUUID mImageAssetId;
+ LLTextBox* mOutfitNameText;
+ LLTextBox* mOutfitWornText;
+ LLPanel* mTextBgPanel;
+ LLPanel* mFotoBgPanel;
+ bool mSelected;
+ bool mWorn;
+ bool mDefaultImage;
+ bool mHidden;
+ std::string mOutfitName;
+};
+
+#endif // LL_LLOUTFITGALLERYCTRL_H
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 883221382c..87c3c5042b 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -38,7 +38,6 @@
#include "llfloatersidepanelcontainer.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
-#include "lllistcontextmenu.h"
#include "llmenubutton.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
@@ -98,276 +97,18 @@ const outfit_accordion_tab_params& get_accordion_tab_params()
}
-//////////////////////////////////////////////////////////////////////////
-
-class LLOutfitListGearMenu
-{
-public:
- LLOutfitListGearMenu(LLOutfitsList* olist)
- : mOutfitList(olist),
- mMenu(NULL)
- {
- llassert_always(mOutfitList);
-
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
-
- registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this));
- registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this));
- registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this));
- registrar.add("Gear.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList));
- registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2));
- registrar.add("Gear.Collapse", boost::bind(&LLOutfitsList::collapse_all_folders, mOutfitList));
- registrar.add("Gear.Expand", boost::bind(&LLOutfitsList::expand_all_folders, mOutfitList));
-
- registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this));
-
- enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2));
- enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2));
-
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
- "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- llassert(mMenu);
- }
-
- void updateItemsVisibility()
- {
- if (!mMenu) return;
-
- bool have_selection = getSelectedOutfitID().notNull();
- mMenu->setItemVisible("sepatator1", have_selection);
- mMenu->setItemVisible("sepatator2", have_selection);
- mMenu->arrangeAndClear(); // update menu height
- }
-
- LLToggleableMenu* getMenu() { return mMenu; }
-
-private:
- const LLUUID& getSelectedOutfitID()
- {
- return mOutfitList->getSelectedOutfitUUID();
- }
-
- LLViewerInventoryCategory* getSelectedOutfit()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull())
- {
- return NULL;
- }
-
- LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
- return cat;
- }
-
- void onWear()
- {
- LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
- if (selected_outfit)
- {
- LLAppearanceMgr::instance().wearInventoryCategory(
- selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
- }
- }
-
- void onAdd()
- {
- const LLUUID& selected_id = getSelectedOutfitID();
-
- if (selected_id.notNull())
- {
- LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id);
- }
- }
-
- void onTakeOff()
- {
- // Take off selected outfit.
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
- }
- }
-
- void onRename()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
- }
- }
-
- void onCreate(const LLSD& data)
- {
- LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
- if (type == LLWearableType::WT_NONE)
- {
- LL_WARNS() << "Invalid wearable type" << LL_ENDL;
- return;
- }
-
- LLAgentWearables::createWearable(type, true);
- }
-
- bool onEnable(LLSD::String param)
- {
- // Handle the "Wear - Replace Current Outfit" menu option specially
- // because LLOutfitList::isActionEnabled() checks whether it's allowed
- // to wear selected outfit OR selected items, while we're only
- // interested in the outfit (STORM-183).
- if ("wear" == param)
- {
- return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID());
- }
-
- return mOutfitList->isActionEnabled(param);
- }
-
- bool onVisible(LLSD::String param)
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
- {
- return false;
- }
-
- // *TODO This condition leads to menu item behavior inconsistent with
- // "Wear" button behavior and should be modified or removed.
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
-
- if ("wear" == param)
- {
- return !is_worn;
- }
-
- return true;
- }
-
- LLOutfitsList* mOutfitList;
- LLToggleableMenu* mMenu;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
-class LLOutfitContextMenu : public LLListContextMenu
-{
-public:
-
- LLOutfitContextMenu(LLOutfitsList* outfit_list)
- : LLListContextMenu(),
- mOutfitList(outfit_list)
- {}
-protected:
- /* virtual */ LLContextMenu* createMenu()
- {
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
- LLUUID selected_id = mUUIDs.front();
-
- registrar.add("Outfit.WearReplace",
- boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
- registrar.add("Outfit.WearAdd",
- boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
- registrar.add("Outfit.TakeOff",
- boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
- registrar.add("Outfit.Edit", boost::bind(editOutfit));
- registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
- registrar.add("Outfit.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList));
-
- enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
- enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
-
- return createFromFile("menu_outfit_tab.xml");
- }
-
- bool onEnable(LLSD::String param)
- {
- LLUUID outfit_cat_id = mUUIDs.back();
-
- if ("rename" == param)
- {
- return get_is_category_renameable(&gInventory, outfit_cat_id);
- }
- else if ("wear_replace" == param)
- {
- return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id);
- }
- else if ("wear_add" == param)
- {
- return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
- }
- else if ("take_off" == param)
- {
- return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id);
- }
-
- return true;
- }
-
- bool onVisible(LLSD::String param)
- {
- LLUUID outfit_cat_id = mUUIDs.back();
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
-
- if ("edit" == param)
- {
- return is_worn;
- }
- else if ("wear_replace" == param)
- {
- return !is_worn;
- }
- else if ("delete" == param)
- {
- return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
- }
-
- return true;
- }
-
- static void editOutfit()
- {
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
- }
-
- static void renameOutfit(const LLUUID& outfit_cat_id)
- {
- LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
- }
-
-private:
- LLOutfitsList* mOutfitList;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
static LLPanelInjector<LLOutfitsList> t_outfits_list("outfits_list");
LLOutfitsList::LLOutfitsList()
- : LLPanelAppearanceTab()
- , mAccordion(NULL)
+ : LLOutfitListBase()
+ , mAccordion(NULL)
, mListCommands(NULL)
- , mIsInitialized(false)
, mItemSelected(false)
{
- mCategoriesObserver = new LLInventoryCategoriesObserver();
-
- mGearMenu = new LLOutfitListGearMenu(this);
- mOutfitMenu = new LLOutfitContextMenu(this);
}
LLOutfitsList::~LLOutfitsList()
{
- delete mGearMenu;
- delete mOutfitMenu;
-
- if (gInventory.containsObserver(mCategoriesObserver))
- {
- gInventory.removeObserver(mCategoriesObserver);
- }
- delete mCategoriesObserver;
}
BOOL LLOutfitsList::postBuild()
@@ -375,54 +116,20 @@ BOOL LLOutfitsList::postBuild()
mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");
mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
- LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
-
- menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenu::updateItemsVisibility, mGearMenu));
- menu_gear_btn->setMenu(mGearMenu->getMenu());
-
- return TRUE;
+ return LLOutfitListBase::postBuild();
}
//virtual
-void LLOutfitsList::onOpen(const LLSD& /*info*/)
+void LLOutfitsList::onOpen(const LLSD& info)
{
- if (!mIsInitialized)
- {
- // *TODO: I'm not sure is this check necessary but it never match while developing.
- if (!gInventory.isInventoryUsable())
- return;
+ if (!mIsInitialized)
+ {
+ const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ // Start observing changes in Current Outfit category.
+ mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
+ }
- const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-
- // *TODO: I'm not sure is this check necessary but it never match while developing.
- LLViewerInventoryCategory* category = gInventory.getCategory(outfits);
- if (!category)
- return;
-
- gInventory.addObserver(mCategoriesObserver);
-
- // Start observing changes in "My Outfits" category.
- mCategoriesObserver->addCategory(outfits,
- boost::bind(&LLOutfitsList::refreshList, this, outfits));
-
- const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-
- // Start observing changes in Current Outfit category.
- mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
-
- LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this));
- LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this));
-
- // Fetch "My Outfits" contents and refresh the list to display
- // initially fetched items. If not all items are fetched now
- // the observer will refresh the list as soon as the new items
- // arrive.
- category->fetch();
- refreshList(outfits);
- highlightBaseOutfit();
-
- mIsInitialized = true;
- }
+ LLOutfitListBase::onOpen(info);
LLAccordionCtrlTab* selected_tab = mAccordion->getSelectedTab();
if (!selected_tab) return;
@@ -431,174 +138,131 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/)
selected_tab->showAndFocusHeader();
}
-void LLOutfitsList::refreshList(const LLUUID& category_id)
-{
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
-
- // Collect all sub-categories of a given category.
- LLIsType is_category(LLAssetType::AT_CATEGORY);
- gInventory.collectDescendentsIf(
- category_id,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_category);
-
- uuid_vec_t vadded;
- uuid_vec_t vremoved;
-
- // Create added and removed items vectors.
- computeDifference(cat_array, vadded, vremoved);
-
- // Handle added tabs.
- for (uuid_vec_t::const_iterator iter = vadded.begin();
- iter != vadded.end();
- ++iter)
- {
- const LLUUID cat_id = (*iter);
- LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
- if (!cat) continue;
-
- std::string name = cat->getName();
-
- outfit_accordion_tab_params tab_params(get_accordion_tab_params());
- LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params);
- if (!tab) continue;
- LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list);
- wearable_list->setShape(tab->getLocalRect());
- tab->addChild(wearable_list);
- tab->setName(name);
- tab->setTitle(name);
-
- // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
- tab->setDisplayChildren(false);
- mAccordion->addCollapsibleCtrl(tab);
-
- // Start observing the new outfit category.
- LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
- if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)))
- {
- // Remove accordion tab if category could not be added to observer.
- mAccordion->removeCollapsibleCtrl(tab);
-
- // kill removed tab
- tab->die();
- continue;
- }
-
- // Map the new tab with outfit category UUID.
- mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
-
- tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this,
- _1, _2, _3, cat_id));
+void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
+{
+ LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+ if (!cat) return;
- // Setting tab focus callback to monitor currently selected outfit.
- tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id));
+ std::string name = cat->getName();
- // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875)
- tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id));
+ outfit_accordion_tab_params tab_params(get_accordion_tab_params());
+ LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(tab_params);
+ if (!tab) return;
+ LLWearableItemsList* wearable_list = LLUICtrlFactory::create<LLWearableItemsList>(tab_params.wearable_list);
+ wearable_list->setShape(tab->getLocalRect());
+ tab->addChild(wearable_list);
- // force showing list items that don't match current filter(EXT-7158)
- list->setForceShowingUnmatchedItems(true);
+ tab->setName(name);
+ tab->setTitle(name);
- // Setting list commit callback to monitor currently selected wearable item.
- list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1));
+ // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
+ tab->setDisplayChildren(false);
+ mAccordion->addCollapsibleCtrl(tab);
- // Setting list refresh callback to apply filter on list change.
- list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1));
+ // Start observing the new outfit category.
+ LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
+ if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)))
+ {
+ // Remove accordion tab if category could not be added to observer.
+ mAccordion->removeCollapsibleCtrl(tab);
- list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3));
+ // kill removed tab
+ tab->die();
+ return;
+ }
- // Fetch the new outfit contents.
- cat->fetch();
+ // Map the new tab with outfit category UUID.
+ mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
- // Refresh the list of outfit items after fetch().
- // Further list updates will be triggered by the category observer.
- list->updateList(cat_id);
+ tab->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this,
+ _1, _2, _3, cat_id));
- // If filter is currently applied we store the initial tab state and
- // open it to show matched items if any.
- if (!sFilterSubString.empty())
- {
- tab->notifyChildren(LLSD().with("action","store_state"));
- tab->setDisplayChildren(true);
+ // Setting tab focus callback to monitor currently selected outfit.
+ tab->setFocusReceivedCallback(boost::bind(&LLOutfitListBase::ChangeOutfitSelection, this, list, cat_id));
- // Setting mForceRefresh flag will make the list refresh its contents
- // even if it is not currently visible. This is required to apply the
- // filter to the newly added list.
- list->setForceRefresh(true);
+ // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875)
+ tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id));
- list->setFilterSubString(sFilterSubString);
- }
- }
+ // force showing list items that don't match current filter(EXT-7158)
+ list->setForceShowingUnmatchedItems(true);
- // Handle removed tabs.
- for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter)
- {
- outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter));
- if (outfits_iter != mOutfitsMap.end())
- {
- const LLUUID& outfit_id = outfits_iter->first;
- LLAccordionCtrlTab* tab = outfits_iter->second;
+ // Setting list commit callback to monitor currently selected wearable item.
+ list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1));
- // An outfit is removed from the list. Do the following:
- // 1. Remove outfit category from observer to stop monitoring its changes.
- mCategoriesObserver->removeCategory(outfit_id);
+ // Setting list refresh callback to apply filter on list change.
+ list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1));
- // 2. Remove the outfit from selection.
- deselectOutfit(outfit_id);
+ list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3));
- // 3. Remove category UUID to accordion tab mapping.
- mOutfitsMap.erase(outfits_iter);
+ // Fetch the new outfit contents.
+ cat->fetch();
- // 4. Remove outfit tab from accordion.
- mAccordion->removeCollapsibleCtrl(tab);
+ // Refresh the list of outfit items after fetch().
+ // Further list updates will be triggered by the category observer.
+ list->updateList(cat_id);
- // kill removed tab
- if (tab != NULL)
- {
- tab->die();
- }
- }
- }
+ // If filter is currently applied we store the initial tab state and
+ // open it to show matched items if any.
+ if (!sFilterSubString.empty())
+ {
+ tab->notifyChildren(LLSD().with("action", "store_state"));
+ tab->setDisplayChildren(true);
- // Get changed items from inventory model and update outfit tabs
- // which might have been renamed.
- const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
- for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
- items_iter != changed_items.end();
- ++items_iter)
- {
- updateOutfitTab(*items_iter);
- }
+ // Setting mForceRefresh flag will make the list refresh its contents
+ // even if it is not currently visible. This is required to apply the
+ // filter to the newly added list.
+ list->setForceRefresh(true);
- mAccordion->sort();
+ list->setFilterSubString(sFilterSubString);
+ }
}
-void LLOutfitsList::highlightBaseOutfit()
+void LLOutfitsList::updateRemovedCategory(LLUUID cat_id)
{
- // id of base outfit
- LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
- if (base_id != mHighlightedOutfitUUID)
- {
- if (mOutfitsMap[mHighlightedOutfitUUID])
- {
- mOutfitsMap[mHighlightedOutfitUUID]->setTitleFontStyle("NORMAL");
- mOutfitsMap[mHighlightedOutfitUUID]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
- }
+ outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat_id);
+ if (outfits_iter != mOutfitsMap.end())
+ {
+ const LLUUID& outfit_id = outfits_iter->first;
+ LLAccordionCtrlTab* tab = outfits_iter->second;
+
+ // An outfit is removed from the list. Do the following:
+ // 1. Remove outfit category from observer to stop monitoring its changes.
+ mCategoriesObserver->removeCategory(outfit_id);
+
+ // 2. Remove the outfit from selection.
+ deselectOutfit(outfit_id);
+
+ // 3. Remove category UUID to accordion tab mapping.
+ mOutfitsMap.erase(outfits_iter);
+
+ // 4. Remove outfit tab from accordion.
+ mAccordion->removeCollapsibleCtrl(tab);
+
+ // kill removed tab
+ if (tab != NULL)
+ {
+ tab->die();
+ }
+ }
+}
- mHighlightedOutfitUUID = base_id;
- }
- if (mOutfitsMap[base_id])
+//virtual
+void LLOutfitsList::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id)
+{
+ if (mOutfitsMap[prev_id])
+ {
+ mOutfitsMap[prev_id]->setTitleFontStyle("NORMAL");
+ mOutfitsMap[prev_id]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
+ }
+ if (mOutfitsMap[base_id])
{
mOutfitsMap[base_id]->setTitleFontStyle("BOLD");
mOutfitsMap[base_id]->setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));
}
}
-void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
+void LLOutfitsList::onListSelectionChange(LLUICtrl* ctrl)
{
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);
if (!list) return;
@@ -606,10 +270,10 @@ void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
LLViewerInventoryItem *item = gInventory.getItem(list->getSelectedUUID());
if (!item) return;
- changeOutfitSelection(list, item->getParentUUID());
+ ChangeOutfitSelection(list, item->getParentUUID());
}
-void LLOutfitsList::performAction(std::string action)
+void LLOutfitListBase::performAction(std::string action)
{
if (mSelectedOutfitUUID.isNull()) return;
@@ -630,23 +294,7 @@ void LLOutfitsList::performAction(std::string action)
}
}
-void LLOutfitsList::removeSelected()
-{
- LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitsList::onOutfitsRemovalConfirmation, this, _1, _2));
-}
-
-void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option != 0) return; // canceled
-
- if (mSelectedOutfitUUID.notNull())
- {
- gInventory.removeCategory(mSelectedOutfitUUID);
- }
-}
-
-void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
+void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
@@ -661,7 +309,7 @@ void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
if (!list) continue;
tab->setFocus(TRUE);
- changeOutfitSelection(list, outfit_uuid);
+ ChangeOutfitSelection(list, outfit_uuid);
tab->setDisplayChildren(true);
}
@@ -677,14 +325,14 @@ void LLOutfitsList::setFilterSubString(const std::string& string)
}
// virtual
-bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
+bool LLOutfitListBase::isActionEnabled(const LLSD& userdata)
{
if (mSelectedOutfitUUID.isNull()) return false;
const std::string command_name = userdata.asString();
if (command_name == "delete")
{
- return !mItemSelected && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID);
+ return !hasItemSelected() && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID);
}
if (command_name == "rename")
{
@@ -745,7 +393,7 @@ void LLOutfitsList::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
}
}
-void LLOutfitsList::collapse_all_folders()
+void LLOutfitsList::onCollapseAllFolders()
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
@@ -759,7 +407,7 @@ void LLOutfitsList::collapse_all_folders()
}
}
-void LLOutfitsList::expand_all_folders()
+void LLOutfitsList::onExpandAllFolders()
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
@@ -773,11 +421,6 @@ void LLOutfitsList::expand_all_folders()
}
}
-boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb)
-{
- return mSelectionChangeSignal.connect(cb);
-}
-
bool LLOutfitsList::hasItemSelected()
{
return mItemSelected;
@@ -786,42 +429,12 @@ bool LLOutfitsList::hasItemSelected()
//////////////////////////////////////////////////////////////////////////
// Private methods
//////////////////////////////////////////////////////////////////////////
-void LLOutfitsList::computeDifference(
- const LLInventoryModel::cat_array_t& vcats,
- uuid_vec_t& vadded,
- uuid_vec_t& vremoved)
-{
- uuid_vec_t vnew;
- // Creating a vector of newly collected sub-categories UUIDs.
- for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin();
- iter != vcats.end();
- iter++)
- {
- vnew.push_back((*iter)->getUUID());
- }
-
- uuid_vec_t vcur;
- // Creating a vector of currently displayed sub-categories UUIDs.
- for (outfits_map_t::const_iterator iter = mOutfitsMap.begin();
- iter != mOutfitsMap.end();
- iter++)
- {
- vcur.push_back((*iter).first);
- }
- LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
-}
-
-void LLOutfitsList::updateOutfitTab(const LLUUID& category_id)
+void LLOutfitsList::updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name)
{
- outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id);
+ outfits_map_t::iterator outfits_iter = mOutfitsMap.find(cat->getUUID());
if (outfits_iter != mOutfitsMap.end())
{
- LLViewerInventoryCategory *cat = gInventory.getCategory(category_id);
- if (!cat) return;
-
- std::string name = cat->getName();
-
// Update tab name with the new category name.
LLAccordionCtrlTab* tab = outfits_iter->second;
if (tab)
@@ -836,10 +449,10 @@ void LLOutfitsList::resetItemSelection(LLWearableItemsList* list, const LLUUID&
{
list->resetSelection();
mItemSelected = false;
- setSelectedOutfitUUID(category_id);
+ signalSelectionOutfitUUID(category_id);
}
-void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+void LLOutfitsList::onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
{
MASK mask = gKeyboard->currentMask(TRUE);
@@ -865,24 +478,14 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI
mItemSelected = list && (list->getSelectedItem() != NULL);
mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list));
- setSelectedOutfitUUID(category_id);
-}
-
-void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id)
-{
- mSelectionChangeSignal(mSelectedOutfitUUID = category_id);
}
void LLOutfitsList::deselectOutfit(const LLUUID& category_id)
{
// Remove selected lists map entry.
mSelectedListsMap.erase(category_id);
-
- // Reset selection if the outfit is selected.
- if (category_id == mSelectedOutfitUUID)
- {
- setSelectedOutfitUUID(LLUUID::null);
- }
+
+ LLOutfitListBase::deselectOutfit(category_id);
}
void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID& category_id)
@@ -890,7 +493,7 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID
// Try restoring outfit selection after filtering.
if (mAccordion->getSelectedTab() == tab)
{
- setSelectedOutfitUUID(category_id);
+ signalSelectionOutfitUUID(category_id);
}
}
@@ -1036,24 +639,6 @@ bool LLOutfitsList::canWearSelected()
return true;
}
-void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
-{
- LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
- if(mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull())
- {
- // Focus tab header to trigger tab selection change.
- LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
- if (header)
- {
- header->setFocus(TRUE);
- }
-
- uuid_vec_t selected_uuids;
- selected_uuids.push_back(cat_id);
- mOutfitMenu->show(ctrl, selected_uuids, x, y);
- }
-}
-
void LLOutfitsList::wearSelectedItems()
{
uuid_vec_t selected_uuids;
@@ -1132,6 +717,47 @@ void LLOutfitsList::onCOFChanged()
}
}
+void LLOutfitsList::getCurrentCategories(uuid_vec_t& vcur)
+{
+ // Creating a vector of currently displayed sub-categories UUIDs.
+ for (outfits_map_t::const_iterator iter = mOutfitsMap.begin();
+ iter != mOutfitsMap.end();
+ iter++)
+ {
+ vcur.push_back((*iter).first);
+ }
+}
+
+
+void LLOutfitsList::sortOutfits()
+{
+ mAccordion->sort();
+}
+
+void LLOutfitsList::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
+{
+ LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
+ if (mOutfitMenu && is_tab_header_clicked(tab, y) && cat_id.notNull())
+ {
+ // Focus tab header to trigger tab selection change.
+ LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
+ if (header)
+ {
+ header->setFocus(TRUE);
+ }
+
+ uuid_vec_t selected_uuids;
+ selected_uuids.push_back(cat_id);
+ mOutfitMenu->show(ctrl, selected_uuids, x, y);
+ }
+}
+
+LLOutfitListGearMenuBase* LLOutfitsList::createGearMenu()
+{
+ return new LLOutfitListGearMenu(this);
+}
+
+
bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
{
if(!tab || !tab->getHeaderVisible()) return false;
@@ -1140,4 +766,512 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
return y >= header_bottom;
}
+LLOutfitListBase::LLOutfitListBase()
+ : LLPanelAppearanceTab()
+ , mIsInitialized(false)
+{
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+ mOutfitMenu = new LLOutfitContextMenu(this);
+ //mGearMenu = createGearMenu();
+}
+
+LLOutfitListBase::~LLOutfitListBase()
+{
+ delete mOutfitMenu;
+ delete mGearMenu;
+
+ if (gInventory.containsObserver(mCategoriesObserver))
+ {
+ gInventory.removeObserver(mCategoriesObserver);
+ }
+ delete mCategoriesObserver;
+}
+
+void LLOutfitListBase::onOpen(const LLSD& info)
+{
+ if (!mIsInitialized)
+ {
+ // *TODO: I'm not sure is this check necessary but it never match while developing.
+ if (!gInventory.isInventoryUsable())
+ return;
+
+ const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+
+ // *TODO: I'm not sure is this check necessary but it never match while developing.
+ LLViewerInventoryCategory* category = gInventory.getCategory(outfits);
+ if (!category)
+ return;
+
+ gInventory.addObserver(mCategoriesObserver);
+
+ // Start observing changes in "My Outfits" category.
+ mCategoriesObserver->addCategory(outfits,
+ boost::bind(&LLOutfitListBase::refreshList, this, outfits));
+
+ const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+
+ // Start observing changes in Current Outfit category.
+ //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
+
+ LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this));
+ LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitListBase::highlightBaseOutfit, this));
+
+ // Fetch "My Outfits" contents and refresh the list to display
+ // initially fetched items. If not all items are fetched now
+ // the observer will refresh the list as soon as the new items
+ // arrive.
+ category->fetch();
+ refreshList(outfits);
+ highlightBaseOutfit();
+
+ mIsInitialized = true;
+ }
+}
+
+void LLOutfitListBase::refreshList(const LLUUID& category_id)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+
+ // Collect all sub-categories of a given category.
+ LLIsType is_category(LLAssetType::AT_CATEGORY);
+ gInventory.collectDescendentsIf(
+ category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_category);
+
+ uuid_vec_t vadded;
+ uuid_vec_t vremoved;
+
+ // Create added and removed items vectors.
+ computeDifference(cat_array, vadded, vremoved);
+
+ // Handle added tabs.
+ for (uuid_vec_t::const_iterator iter = vadded.begin();
+ iter != vadded.end();
+ ++iter)
+ {
+ const LLUUID cat_id = (*iter);
+ updateAddedCategory(cat_id);
+ }
+
+ // Handle removed tabs.
+ for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter)
+ {
+ const LLUUID cat_id = (*iter);
+ updateRemovedCategory(cat_id);
+ }
+
+ // Get changed items from inventory model and update outfit tabs
+ // which might have been renamed.
+ const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
+ for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
+ items_iter != changed_items.end();
+ ++items_iter)
+ {
+ LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter);
+ if (!cat) return;
+
+ std::string name = cat->getName();
+
+ updateChangedCategoryName(cat, name);
+ }
+
+ sortOutfits();
+}
+
+void LLOutfitListBase::computeDifference(
+ const LLInventoryModel::cat_array_t& vcats,
+ uuid_vec_t& vadded,
+ uuid_vec_t& vremoved)
+{
+ uuid_vec_t vnew;
+ // Creating a vector of newly collected sub-categories UUIDs.
+ for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin();
+ iter != vcats.end();
+ iter++)
+ {
+ vnew.push_back((*iter)->getUUID());
+ }
+
+ uuid_vec_t vcur;
+ getCurrentCategories(vcur);
+
+ LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
+}
+
+void LLOutfitListBase::sortOutfits()
+{
+}
+
+void LLOutfitListBase::highlightBaseOutfit()
+{
+ // id of base outfit
+ LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
+ if (base_id != mHighlightedOutfitUUID)
+ {
+ LLUUID prev_id = mHighlightedOutfitUUID;
+ mHighlightedOutfitUUID = base_id;
+ onHighlightBaseOutfit(base_id, prev_id);
+ }
+
+}
+
+void LLOutfitListBase::removeSelected()
+{
+ LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitListBase::onOutfitsRemovalConfirmation, this, _1, _2));
+}
+
+void LLOutfitListBase::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return; // canceled
+
+ if (mSelectedOutfitUUID.notNull())
+ {
+ gInventory.removeCategory(mSelectedOutfitUUID);
+ }
+}
+
+void LLOutfitListBase::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
+{
+ onSetSelectedOutfitByUUID(outfit_uuid);
+}
+
+boost::signals2::connection LLOutfitListBase::setSelectionChangeCallback(selection_change_callback_t cb)
+{
+ return mSelectionChangeSignal.connect(cb);
+}
+
+void LLOutfitListBase::signalSelectionOutfitUUID(const LLUUID& category_id)
+{
+ mSelectionChangeSignal(category_id);
+}
+
+void LLOutfitListBase::outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
+{
+ onOutfitRightClick(ctrl, x, y, cat_id);
+}
+
+void LLOutfitListBase::ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+{
+ onChangeOutfitSelection(list, category_id);
+ mSelectedOutfitUUID = category_id;
+ signalSelectionOutfitUUID(category_id);
+}
+
+BOOL LLOutfitListBase::postBuild()
+{
+ mGearMenu = createGearMenu();
+
+ LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
+
+ menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenuBase::updateItemsVisibility, mGearMenu));
+ menu_gear_btn->setMenu(mGearMenu->getMenu());
+ return TRUE;
+}
+
+void LLOutfitListBase::collapseAllFolders()
+{
+ onCollapseAllFolders();
+}
+
+void LLOutfitListBase::expandAllFolders()
+{
+ onExpandAllFolders();
+}
+
+void LLOutfitListBase::deselectOutfit(const LLUUID& category_id)
+{
+ // Reset selection if the outfit is selected.
+ if (category_id == mSelectedOutfitUUID)
+ {
+ signalSelectionOutfitUUID(LLUUID::null);
+ }
+}
+
+LLContextMenu* LLOutfitContextMenu::createMenu()
+{
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ LLUUID selected_id = mUUIDs.front();
+
+ registrar.add("Outfit.WearReplace",
+ boost::bind(&LLAppearanceMgr::replaceCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.WearAdd",
+ boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.TakeOff",
+ boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
+ registrar.add("Outfit.Edit", boost::bind(editOutfit));
+ registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
+ registrar.add("Outfit.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList));
+
+ enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
+ enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
+
+ return createFromFile("menu_outfit_tab.xml");
+
+}
+
+bool LLOutfitContextMenu::onEnable(LLSD::String param)
+{
+ LLUUID outfit_cat_id = mUUIDs.back();
+
+ if ("rename" == param)
+ {
+ return get_is_category_renameable(&gInventory, outfit_cat_id);
+ }
+ else if ("wear_replace" == param)
+ {
+ return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id);
+ }
+ else if ("wear_add" == param)
+ {
+ return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
+ }
+ else if ("take_off" == param)
+ {
+ return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id);
+ }
+
+ return true;
+}
+
+bool LLOutfitContextMenu::onVisible(LLSD::String param)
+{
+ LLUUID outfit_cat_id = mUUIDs.back();
+ bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
+
+ if ("edit" == param)
+ {
+ return is_worn;
+ }
+ else if ("wear_replace" == param)
+ {
+ return !is_worn;
+ }
+ else if ("delete" == param)
+ {
+ return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
+ }
+
+ return true;
+}
+
+//static
+void LLOutfitContextMenu::editOutfit()
+{
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
+}
+
+void LLOutfitContextMenu::renameOutfit(const LLUUID& outfit_cat_id)
+{
+ LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
+}
+
+LLOutfitListGearMenuBase::LLOutfitListGearMenuBase(LLOutfitListBase* olist)
+ : mOutfitList(olist),
+ mMenu(NULL)
+{
+ llassert_always(mOutfitList);
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenuBase::onWear, this));
+ registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenuBase::onTakeOff, this));
+ registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenuBase::onRename, this));
+ registrar.add("Gear.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList));
+ registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenuBase::onCreate, this, _2));
+ registrar.add("Gear.Collapse", boost::bind(&LLOutfitListBase::onCollapseAllFolders, mOutfitList));
+ registrar.add("Gear.Expand", boost::bind(&LLOutfitListBase::onExpandAllFolders, mOutfitList));
+
+ registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenuBase::onAdd, this));
+
+ registrar.add("Gear.UploadPhoto", boost::bind(&LLOutfitListGearMenuBase::onUploadFoto, this));
+ registrar.add("Gear.SelectPhoto", boost::bind(&LLOutfitListGearMenuBase::onSelectPhoto, this));
+ registrar.add("Gear.TakeSnapshot", boost::bind(&LLOutfitListGearMenuBase::onTakeSnapshot, this));
+ registrar.add("Gear.RemovePhoto", boost::bind(&LLOutfitListGearMenuBase::onRemovePhoto, this));
+ registrar.add("Gear.SortByName", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this));
+
+ enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenuBase::onEnable, this, _2));
+ enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenuBase::onVisible, this, _2));
+
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
+ "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ llassert(mMenu);
+}
+
+LLOutfitListGearMenuBase::~LLOutfitListGearMenuBase()
+{}
+
+void LLOutfitListGearMenuBase::updateItemsVisibility()
+{
+ onUpdateItemsVisibility();
+}
+
+void LLOutfitListGearMenuBase::onUpdateItemsVisibility()
+{
+ if (!mMenu) return;
+
+ bool have_selection = getSelectedOutfitID().notNull();
+ mMenu->setItemVisible("sepatator1", have_selection);
+ mMenu->setItemVisible("sepatator2", have_selection);
+ mMenu->arrangeAndClear(); // update menu height
+}
+
+LLToggleableMenu* LLOutfitListGearMenuBase::getMenu()
+{
+ return mMenu;
+}
+const LLUUID& LLOutfitListGearMenuBase::getSelectedOutfitID()
+{
+ return mOutfitList->getSelectedOutfitUUID();
+}
+
+LLViewerInventoryCategory* LLOutfitListGearMenuBase::getSelectedOutfit()
+{
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.isNull())
+ {
+ return NULL;
+ }
+
+ LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
+ return cat;
+}
+
+void LLOutfitListGearMenuBase::onWear()
+{
+ LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
+ if (selected_outfit)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(
+ selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
+ }
+}
+
+void LLOutfitListGearMenuBase::onAdd()
+{
+ const LLUUID& selected_id = getSelectedOutfitID();
+
+ if (selected_id.notNull())
+ {
+ LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id);
+ }
+}
+
+void LLOutfitListGearMenuBase::onTakeOff()
+{
+ // Take off selected outfit.
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
+ }
+}
+
+void LLOutfitListGearMenuBase::onRename()
+{
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
+ }
+}
+
+void LLOutfitListGearMenuBase::onCreate(const LLSD& data)
+{
+ LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
+ if (type == LLWearableType::WT_NONE)
+ {
+ LL_WARNS() << "Invalid wearable type" << LL_ENDL;
+ return;
+ }
+
+ LLAgentWearables::createWearable(type, true);
+}
+
+bool LLOutfitListGearMenuBase::onEnable(LLSD::String param)
+{
+ // Handle the "Wear - Replace Current Outfit" menu option specially
+ // because LLOutfitList::isActionEnabled() checks whether it's allowed
+ // to wear selected outfit OR selected items, while we're only
+ // interested in the outfit (STORM-183).
+ if ("wear" == param)
+ {
+ return LLAppearanceMgr::instance().getCanReplaceCOF(mOutfitList->getSelectedOutfitUUID());
+ }
+
+ return mOutfitList->isActionEnabled(param);
+}
+
+bool LLOutfitListGearMenuBase::onVisible(LLSD::String param)
+{
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
+ {
+ return false;
+ }
+
+ // *TODO This condition leads to menu item behavior inconsistent with
+ // "Wear" button behavior and should be modified or removed.
+ bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
+
+ if ("wear" == param)
+ {
+ return !is_worn;
+ }
+
+ return true;
+}
+
+void LLOutfitListGearMenuBase::onUploadFoto()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onSelectPhoto()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onTakeSnapshot()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onRemovePhoto()
+{
+
+}
+
+void LLOutfitListGearMenuBase::onChangeSortOrder()
+{
+
+}
+
+LLOutfitListGearMenu::LLOutfitListGearMenu(LLOutfitListBase* olist)
+ : LLOutfitListGearMenuBase(olist)
+{}
+
+LLOutfitListGearMenu::~LLOutfitListGearMenu()
+{}
+
+void LLOutfitListGearMenu::onUpdateItemsVisibility()
+{
+ if (!mMenu) return;
+ mMenu->setItemVisible("expand", TRUE);
+ mMenu->setItemVisible("collapse", TRUE);
+ mMenu->setItemVisible("upload_photo", FALSE);
+ mMenu->setItemVisible("select_photo", FALSE);
+ mMenu->setItemVisible("take_snapshot", FALSE);
+ mMenu->setItemVisible("remove_photo", FALSE);
+ mMenu->setItemVisible("sepatator3", FALSE);
+ mMenu->setItemVisible("sort_folders_by_name", FALSE);
+ LLOutfitListGearMenuBase::onUpdateItemsVisibility();
+}
+
// EOF
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index 2e3fb3f488..81be8de94f 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -32,11 +32,14 @@
// newview
#include "llinventorymodel.h"
+#include "lllistcontextmenu.h"
#include "llpanelappearancetab.h"
+#include "lltoggleablemenu.h"
+#include "llviewermenu.h"
class LLAccordionCtrlTab;
class LLInventoryCategoriesObserver;
-class LLOutfitListGearMenu;
+class LLOutfitListGearMenuBase;
class LLWearableItemsList;
class LLListContextMenu;
@@ -57,6 +60,142 @@ public:
/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const;
};
+class LLOutfitListBase : public LLPanelAppearanceTab
+{
+public:
+ typedef boost::function<void(const LLUUID&)> selection_change_callback_t;
+ typedef boost::signals2::signal<void(const LLUUID&)> selection_change_signal_t;
+
+ LLOutfitListBase();
+ virtual ~LLOutfitListBase();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& info);
+
+ void refreshList(const LLUUID& category_id);
+ void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+ // highlights currently worn outfit in list and unhighlights previously worn
+ void highlightBaseOutfit();
+ void ChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
+
+
+ virtual void getCurrentCategories(uuid_vec_t& vcur) = 0;
+ virtual void updateAddedCategory(LLUUID cat_id) = 0;
+ virtual void updateRemovedCategory(LLUUID cat_id) = 0;
+ virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0;
+ virtual void sortOutfits();
+
+ void removeSelected();
+ void setSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+ const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
+ boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
+ void outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
+
+ virtual bool isActionEnabled(const LLSD& userdata);
+ virtual void performAction(std::string action);
+ virtual bool hasItemSelected() = 0;
+ virtual bool canWearSelected() = 0;
+
+ virtual void deselectOutfit(const LLUUID& category_id);
+
+ void signalSelectionOutfitUUID(const LLUUID& category_id);
+
+ void collapseAllFolders();
+ virtual void onCollapseAllFolders() = 0;
+
+ void expandAllFolders();
+ virtual void onExpandAllFolders() = 0;
+
+ virtual bool getHasExpandableFolders() = 0;
+
+protected:
+ virtual LLOutfitListGearMenuBase* createGearMenu() = 0;
+ virtual void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) = 0;
+ virtual void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) = 0;
+ virtual void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) = 0;
+ void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
+ virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0;
+
+ bool mIsInitialized;
+ LLInventoryCategoriesObserver* mCategoriesObserver;
+ LLUUID mSelectedOutfitUUID;
+ // id of currently highlited outfit
+ LLUUID mHighlightedOutfitUUID;
+ selection_change_signal_t mSelectionChangeSignal;
+ LLListContextMenu* mOutfitMenu;
+ LLOutfitListGearMenuBase* mGearMenu;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+class LLOutfitContextMenu : public LLListContextMenu
+{
+public:
+
+ LLOutfitContextMenu(LLOutfitListBase* outfit_list)
+ : LLListContextMenu(),
+ mOutfitList(outfit_list)
+ {}
+protected:
+ /* virtual */ LLContextMenu* createMenu();
+
+ bool onEnable(LLSD::String param);
+
+ bool onVisible(LLSD::String param);
+
+ static void editOutfit();
+
+ static void renameOutfit(const LLUUID& outfit_cat_id);
+
+private:
+ LLOutfitListBase* mOutfitList;
+};
+
+class LLOutfitListGearMenuBase
+{
+public:
+ LLOutfitListGearMenuBase(LLOutfitListBase* olist);
+ virtual ~LLOutfitListGearMenuBase();
+
+ void updateItemsVisibility();
+
+ LLToggleableMenu* getMenu();
+
+protected:
+ virtual void onUpdateItemsVisibility();
+ virtual void onUploadFoto();
+ virtual void onSelectPhoto();
+ virtual void onTakeSnapshot();
+ virtual void onRemovePhoto();
+ virtual void onChangeSortOrder();
+
+ const LLUUID& getSelectedOutfitID();
+
+ LLOutfitListBase* mOutfitList;
+ LLToggleableMenu* mMenu;
+private:
+
+ LLViewerInventoryCategory* getSelectedOutfit();
+
+ void onWear();
+ void onAdd();
+ void onTakeOff();
+ void onRename();
+ void onCreate(const LLSD& data);
+ bool onEnable(LLSD::String param);
+ bool onVisible(LLSD::String param);
+};
+
+class LLOutfitListGearMenu : public LLOutfitListGearMenuBase
+{
+public:
+ LLOutfitListGearMenu(LLOutfitListBase* olist);
+ virtual ~LLOutfitListGearMenu();
+
+protected:
+ /*virtual*/ void onUpdateItemsVisibility();
+};
+
/**
* @class LLOutfitsList
*
@@ -66,11 +205,9 @@ public:
*
* Starts fetching necessary inventory content on first opening.
*/
-class LLOutfitsList : public LLPanelAppearanceTab
+class LLOutfitsList : public LLOutfitListBase
{
public:
- typedef boost::function<void (const LLUUID&)> selection_change_callback_t;
- typedef boost::signals2::signal<void (const LLUUID&)> selection_change_signal_t;
LLOutfitsList();
virtual ~LLOutfitsList();
@@ -79,63 +216,66 @@ public:
/*virtual*/ void onOpen(const LLSD& info);
- void refreshList(const LLUUID& category_id);
-
- // highlits currently worn outfit tab text and unhighlights previously worn
- void highlightBaseOutfit();
- void performAction(std::string action);
+ //virtual void refreshList(const LLUUID& category_id);
- void removeSelected();
+ /*virtual*/ void updateAddedCategory(LLUUID cat_id);
+ /*virtual*/ void updateRemovedCategory(LLUUID cat_id);
- void setSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+ // highlits currently worn outfit tab text and unhighlights previously worn
+ /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
- /*virtual*/ void setFilterSubString(const std::string& string);
+ //void performAction(std::string action);
- /*virtual*/ bool isActionEnabled(const LLSD& userdata);
- const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
+ /*virtual*/ void setFilterSubString(const std::string& string);
/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const;
- boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
-
- // Collects selected items from all selected lists and wears them(if possible- adds, else replaces)
+ // Collects selected items from all selected lists and wears them(if possible- adds, else replaces)
void wearSelectedItems();
/**
* Returns true if there is a selection inside currently selected outfit
*/
- bool hasItemSelected();
+ /*virtual*/ bool hasItemSelected();
/**
Collapses all outfit accordions.
*/
- void collapse_all_folders();
+ /*virtual*/ void onCollapseAllFolders();
/**
Expands all outfit accordions.
*/
- void expand_all_folders();
+ void onExpandAllFolders();
+ /*virtual*/ bool getHasExpandableFolders() { return TRUE; }
-private:
+protected:
+ LLOutfitListGearMenuBase* createGearMenu();
- void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
+private:
/**
* Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference
*/
- void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+ //void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+
+ void getCurrentCategories(uuid_vec_t& vcur);
/**
* Updates tab displaying outfit identified by category_id.
*/
- void updateOutfitTab(const LLUUID& category_id);
+ /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name);
+
+ /*virtual*/ void sortOutfits();
+
+ /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid);
/**
* Resets previous selection and stores newly selected list and outfit id.
*/
- void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
+ /*virtual*/ void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
/**
*Resets items selection inside outfit
@@ -143,14 +283,9 @@ private:
void resetItemSelection(LLWearableItemsList* list, const LLUUID& category_id);
/**
- * Saves newly selected outfit ID.
- */
- void setSelectedOutfitUUID(const LLUUID& category_id);
-
- /**
* Removes the outfit from selection.
*/
- void deselectOutfit(const LLUUID& category_id);
+ /*virtual*/ void deselectOutfit(const LLUUID& category_id);
/**
* Try restoring selection for a temporary hidden tab.
@@ -182,15 +317,16 @@ private:
*/
bool canWearSelected();
- void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
void onCOFChanged();
- void onSelectionChange(LLUICtrl* ctrl);
+ void onListSelectionChange(LLUICtrl* ctrl);
+
+ /*virtual*/ void onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
static void onOutfitRename(const LLSD& notification, const LLSD& response);
- LLInventoryCategoriesObserver* mCategoriesObserver;
+ //LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
LLPanel* mListCommands;
@@ -199,11 +335,6 @@ private:
typedef wearables_lists_map_t::value_type wearables_lists_map_value_t;
wearables_lists_map_t mSelectedListsMap;
- LLUUID mSelectedOutfitUUID;
- // id of currently highlited outfit
- LLUUID mHighlightedOutfitUUID;
- selection_change_signal_t mSelectionChangeSignal;
-
typedef std::map<LLUUID, LLAccordionCtrlTab*> outfits_map_t;
typedef outfits_map_t::value_type outfits_map_value_t;
outfits_map_t mOutfitsMap;
@@ -212,10 +343,9 @@ private:
// Used to monitor COF changes for updating items worn state. See EXT-8636.
uuid_vec_t mCOFLinkedItems;
- LLOutfitListGearMenu* mGearMenu;
- LLListContextMenu* mOutfitMenu;
+ //LLOutfitListGearMenu* mGearMenu;
- bool mIsInitialized;
+ //bool mIsInitialized;
/**
* True if there is a selection inside currently selected outfit
*/
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index b2164c1f21..d17f5494a0 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -199,7 +199,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor");
- mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCII );
+ mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCIINoLeadingSpace );
}
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index c779ba5cdd..eb40616a9c 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -106,7 +106,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
mSavedFolderState(NULL),
mFilterText(""),
mMenuGearDefault(NULL),
- mMenuAdd(NULL),
+ mMenuAddHandle(),
mNeedUploadCost(true)
{
// Menu Callbacks (non contex menus)
@@ -200,10 +200,15 @@ BOOL LLPanelMainInventory::postBuild()
// *TODO:Get the cost info from the server
const std::string upload_cost("10");
- mMenuAdd->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost);
- mMenuAdd->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost);
- mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
- mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if (menu)
+ {
+ menu->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+ }
// Trigger callback for focus received so we can deselect items in inbox/outbox
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
@@ -983,7 +988,8 @@ void LLPanelMainInventory::initListCommandsHandlers()
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearMenuButton->setMenu(mMenuGearDefault);
- mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAddHandle = menu->getHandle();
// Update the trash button when selected item(s) get worn or taken off.
LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
@@ -1001,11 +1007,15 @@ void LLPanelMainInventory::onAddButtonClick()
// Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed
// unless "Always show folders" is checked in the filter options.
bool recent_active = ("Recent Items" == mActivePanel->getName());
- mMenuAdd->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if (menu)
+ {
+ menu->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
- setUploadCostIfNeeded();
+ setUploadCostIfNeeded();
- showActionMenu(mMenuAdd,"add_btn");
+ showActionMenu(menu,"add_btn");
+ }
}
void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
@@ -1156,7 +1166,11 @@ void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
{
if(!new_visibility)
{
- mMenuAdd->setVisible(FALSE);
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if (menu)
+ {
+ menu->setVisible(FALSE);
+ }
getActivePanel()->getRootFolder()->finishRenamingItem();
}
}
@@ -1289,9 +1303,10 @@ void LLPanelMainInventory::setUploadCostIfNeeded()
// have two instances of Inventory panel at the moment(and two instances of context menu),
// call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances.
- if(mNeedUploadCost && mMenuAdd)
+ LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
+ if(mNeedUploadCost && menu)
{
- LLMenuItemBranchGL* upload_menu = mMenuAdd->findChild<LLMenuItemBranchGL>("upload");
+ LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload");
if(upload_menu)
{
S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 290e2e5f47..efa18b42c1 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -156,8 +156,8 @@ protected:
private:
LLDragAndDropButton* mTrashButton;
LLToggleableMenu* mMenuGearDefault;
- LLMenuGL* mMenuAdd;
LLMenuButton* mGearMenuButton;
+ LLHandle<LLView> mMenuAddHandle;
bool mNeedUploadCost;
// List Commands //
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 8331c152e2..8b9941c0ca 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -1059,9 +1059,6 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void)
case LLAssetType::AT_BODYPART:
applyListViewFilter(LVIT_BODYPART);
break;
- case LLAssetType::AT_GESTURE:
- applyListViewFilter(LVIT_GESTURES);
- break;
case LLAssetType::AT_CLOTHING:
default:
applyListViewFilter(LVIT_CLOTHING);
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 841bb4337a..30870daf40 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -80,7 +80,6 @@ public:
{
LVIT_ALL = 0,
LVIT_CLOTHING,
- LVIT_GESTURES,
LVIT_BODYPART,
LVIT_ATTACHMENT,
LVIT_SHAPE,
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 1e1f59055f..3f700496a9 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -37,6 +37,7 @@
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "lloutfitobserver.h"
+#include "lloutfitgallery.h"
#include "lloutfitslist.h"
#include "llpanelwearing.h"
#include "llsaveoutfitcombobtn.h"
@@ -44,6 +45,7 @@
#include "llviewerfoldertype.h"
static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
+static const std::string OUTFIT_GALLERY_TAB_NAME = "outfit_gallery_tab";
static const std::string COF_TAB_NAME = "cof_tab";
static LLPanelInjector<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
@@ -165,14 +167,22 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
void LLPanelOutfitsInventory::onWearButtonClick()
{
- if (mMyOutfitsPanel->hasItemSelected())
+ if(isOutfitsListPanelActive())
{
- mMyOutfitsPanel->wearSelectedItems();
+ if (mMyOutfitsPanel->hasItemSelected())
+ {
+ mMyOutfitsPanel->wearSelectedItems();
+ }
+ else
+ {
+ mMyOutfitsPanel->performAction("replaceoutfit");
+ }
}
- else
+ else if(isOutfitsGalleryPanelActive())
{
- mMyOutfitsPanel->performAction("replaceoutfit");
+ mOutfitGalleryPanel->wearSelectedOutfit();
}
+
}
bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD& response)
@@ -234,6 +244,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
mListCommands = getChild<LLPanel>("bottom_panel");
mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
mMyOutfitsPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
+ mOutfitGalleryPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
}
void LLPanelOutfitsInventory::updateListCommands()
@@ -245,15 +256,23 @@ void LLPanelOutfitsInventory::updateListCommands()
LLButton* wear_btn = mListCommands->getChild<LLButton>("wear_btn");
mMyOutfitsPanel->childSetEnabled("trash_btn", trash_enabled);
+ mOutfitGalleryPanel->childSetEnabled("trash_btn", trash_enabled);
wear_btn->setEnabled(wear_enabled);
wear_btn->setVisible(wear_visible);
mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled);
- wear_btn->setToolTip(getString(mMyOutfitsPanel->hasItemSelected() ? "wear_items_tooltip" : "wear_outfit_tooltip"));
+ wear_btn->setToolTip(getString((!isOutfitsGalleryPanelActive() && mMyOutfitsPanel->hasItemSelected()) ? "wear_items_tooltip" : "wear_outfit_tooltip"));
}
void LLPanelOutfitsInventory::onTrashButtonClick()
{
- mMyOutfitsPanel->removeSelected();
+ if(isOutfitsListPanelActive())
+ {
+ mMyOutfitsPanel->removeSelected();
+ }
+ else if(isOutfitsGalleryPanelActive())
+ {
+ mOutfitGalleryPanel->removeSelected();
+ }
}
bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
@@ -268,12 +287,16 @@ bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
void LLPanelOutfitsInventory::initTabPanels()
{
+ //TODO: Add LLOutfitGallery change callback
mCurrentOutfitPanel = findChild<LLPanelWearing>(COF_TAB_NAME);
mCurrentOutfitPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
mMyOutfitsPanel = findChild<LLOutfitsList>(OUTFITS_TAB_NAME);
mMyOutfitsPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
+ mOutfitGalleryPanel = findChild<LLOutfitGallery>(OUTFIT_GALLERY_TAB_NAME);
+ mOutfitGalleryPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
+
mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs");
mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this));
}
@@ -296,6 +319,22 @@ bool LLPanelOutfitsInventory::isCOFPanelActive() const
return mActivePanel->getName() == COF_TAB_NAME;
}
+bool LLPanelOutfitsInventory::isOutfitsListPanelActive() const
+{
+ if (!mActivePanel) return false;
+
+ return mActivePanel->getName() == OUTFITS_TAB_NAME;
+}
+
+bool LLPanelOutfitsInventory::isOutfitsGalleryPanelActive() const
+{
+ if (!mActivePanel) return false;
+
+ return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME;
+}
+
+
+
void LLPanelOutfitsInventory::setWearablesLoading(bool val)
{
updateVerbs();
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index a7917b457c..6a0ea04fa6 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -30,8 +30,9 @@
#include "llpanel.h"
+class LLOutfitGallery;
class LLOutfitsList;
-class LLOutfitListGearMenu;
+class LLOutfitListGearMenuBase;
class LLPanelAppearanceTab;
class LLPanelWearing;
class LLMenuGL;
@@ -72,10 +73,13 @@ protected:
void initTabPanels();
void onTabChange();
bool isCOFPanelActive() const;
+ bool isOutfitsListPanelActive() const;
+ bool isOutfitsGalleryPanelActive() const;
private:
LLPanelAppearanceTab* mActivePanel;
LLOutfitsList* mMyOutfitsPanel;
+ LLOutfitGallery* mOutfitGalleryPanel;
LLPanelWearing* mCurrentOutfitPanel;
// tab panels //
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 763657ebad..0bcd8a9e63 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -95,7 +95,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mVolumeSliderVisible(0),
mWindowShade(NULL),
mHideImmediately(false),
- mSecureURL(false)
+ mSecureURL(false),
+ mMediaPlaySliderCtrlMouseDownValue(0.0)
{
mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
@@ -109,7 +110,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
- mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MouseDown", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MouseUp", boost::bind(&LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this));
@@ -1246,26 +1248,38 @@ void LLPanelPrimMediaControls::setCurrentURL()
#endif // USE_COMBO_BOX_FOR_MEDIA_URL
}
-void LLPanelPrimMediaControls::onCommitSlider()
+
+void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseDown()
{
- focusOnTarget();
+ mMediaPlaySliderCtrlMouseDownValue = mMediaPlaySliderCtrl->getValue().asReal();
- LLViewerMediaImpl* media_impl = getTargetMediaImpl();
- if (media_impl)
+ mUpdateSlider = false;
+}
+
+void LLPanelPrimMediaControls::onMediaPlaySliderCtrlMouseUp()
+{
+ F64 cur_value = mMediaPlaySliderCtrl->getValue().asReal();
+
+ if (mMediaPlaySliderCtrlMouseDownValue != cur_value)
{
- // get slider value
- F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal();
- if(slider_value <= 0.0)
- {
- media_impl->stop();
- }
- else
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
{
- media_impl->seek(slider_value*mMovieDuration);
- //mUpdateSlider= false;
+ if (cur_value <= 0.0)
+ {
+ media_impl->stop();
+ }
+ else
+ {
+ media_impl->seek(cur_value * mMovieDuration);
+ }
}
+
+ mUpdateSlider = true;
}
-}
+}
void LLPanelPrimMediaControls::onCommitVolumeUp()
{
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 6d2eb3430e..21d5236074 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -107,8 +107,10 @@ private:
void updateZoom();
void setCurrentURL();
- void onCommitSlider();
-
+
+ void onMediaPlaySliderCtrlMouseDown();
+ void onMediaPlaySliderCtrlMouseUp();
+
void onCommitVolumeUp();
void onCommitVolumeDown();
void onCommitVolumeSlider();
@@ -219,6 +221,8 @@ private:
S32 mVolumeSliderVisible;
LLNotificationPtr mActiveNotification;
+
+ F64 mMediaPlaySliderCtrlMouseDownValue;
};
#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 184238c40c..8afa35efa0 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -44,19 +44,11 @@ static const std::string PANEL_PICKS = "panel_picks";
std::string getProfileURL(const std::string& agent_name)
{
- std::string url;
-
- if (LLGridManager::getInstance()->isInProductionGrid())
- {
- url = gSavedSettings.getString("WebProfileURL");
- }
- else
- {
- url = gSavedSettings.getString("WebProfileNonProductionURL");
- }
+ std::string url = "[WEB_PROFILE_URL][AGENT_NAME]";
LLSD subs;
+ subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL();
subs["AGENT_NAME"] = agent_name;
- url = LLWeb::expandURLSubstitutions(url,subs);
+ url = LLWeb::expandURLSubstitutions(url, subs);
LLStringUtil::toLower(url);
return url;
}
diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp
index 106fb4997e..a17e3f9e78 100644
--- a/indra/newview/llpanelsnapshot.cpp
+++ b/indra/newview/llpanelsnapshot.cpp
@@ -29,6 +29,8 @@
// libs
#include "llcombobox.h"
+#include "llfloater.h"
+#include "llfloatersnapshot.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "lltrans.h"
@@ -50,15 +52,29 @@ S32 power_of_two(S32 sz, S32 upper)
return res;
}
+LLPanelSnapshot::LLPanelSnapshot()
+ : mSnapshotFloater(NULL)
+{}
+
// virtual
BOOL LLPanelSnapshot::postBuild()
{
getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onResolutionComboCommit, this, _1));
- getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
- getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
- getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1));
-
+ if (!getWidthSpinnerName().empty())
+ {
+ getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
+ }
+ if (!getHeightSpinnerName().empty())
+ {
+ getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onCustomResolutionCommit, this));
+ }
+ if (!getAspectRatioCBName().empty())
+ {
+ getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onKeepAspectRatioCommit, this, _1));
+ }
updateControls(LLSD());
+
+ mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>();
return TRUE;
}
@@ -76,13 +92,13 @@ void LLPanelSnapshot::onOpen(const LLSD& key)
// e.g. attempt to send a large BMP image by email.
if (old_format != new_format)
{
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true));
+ getParentByType<LLFloater>()->notify(LLSD().with("image-format-change", true));
}
}
-LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const
+LLSnapshotModel::ESnapshotFormat LLPanelSnapshot::getImageFormat() const
{
- return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
+ return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG;
}
void LLPanelSnapshot::enableControls(BOOL enable)
@@ -92,27 +108,32 @@ void LLPanelSnapshot::enableControls(BOOL enable)
LLSpinCtrl* LLPanelSnapshot::getWidthSpinner()
{
+ llassert(!getWidthSpinnerName().empty());
return getChild<LLSpinCtrl>(getWidthSpinnerName());
}
LLSpinCtrl* LLPanelSnapshot::getHeightSpinner()
{
+ llassert(!getHeightSpinnerName().empty());
return getChild<LLSpinCtrl>(getHeightSpinnerName());
}
S32 LLPanelSnapshot::getTypedPreviewWidth() const
{
+ llassert(!getWidthSpinnerName().empty());
return getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger();
}
S32 LLPanelSnapshot::getTypedPreviewHeight() const
{
- return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger();
+ llassert(!getHeightSpinnerName().empty());
+ return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger();
}
void LLPanelSnapshot::enableAspectRatioCheckbox(BOOL enable)
{
- getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable);
+ llassert(!getAspectRatioCBName().empty());
+ getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable);
}
LLSideTrayPanelContainer* LLPanelSnapshot::getParentContainer()
@@ -171,14 +192,17 @@ void LLPanelSnapshot::goBack()
void LLPanelSnapshot::cancel()
{
goBack();
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-ready", true));
+ getParentByType<LLFloater>()->notify(LLSD().with("set-ready", true));
}
void LLPanelSnapshot::onCustomResolutionCommit()
{
LLSD info;
- LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(getWidthSpinnerName());
- LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(getHeightSpinnerName());
+ std::string widthSpinnerName = getWidthSpinnerName();
+ std::string heightSpinnerName = getHeightSpinnerName();
+ llassert(!widthSpinnerName.empty() && !heightSpinnerName.empty());
+ LLSpinCtrl *widthSpinner = getChild<LLSpinCtrl>(widthSpinnerName);
+ LLSpinCtrl *heightSpinner = getChild<LLSpinCtrl>(heightSpinnerName);
if (getName() == "panel_snapshot_inventory")
{
S32 width = widthSpinner->getValue().asInteger();
@@ -197,17 +221,22 @@ void LLPanelSnapshot::onCustomResolutionCommit()
info["w"] = widthSpinner->getValue().asInteger();
info["h"] = heightSpinner->getValue().asInteger();
}
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info));
+ getParentByType<LLFloater>()->notify(LLSD().with("custom-res-change", info));
}
void LLPanelSnapshot::onResolutionComboCommit(LLUICtrl* ctrl)
{
LLSD info;
info["combo-res-change"]["control-name"] = ctrl->getName();
- LLFloaterSnapshot::getInstance()->notify(info);
+ getParentByType<LLFloater>()->notify(info);
}
void LLPanelSnapshot::onKeepAspectRatioCommit(LLUICtrl* ctrl)
{
- LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean()));
+ getParentByType<LLFloater>()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean()));
+}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshot::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_WEB;
}
diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h
index 42ad798d60..55273797cc 100644
--- a/indra/newview/llpanelsnapshot.h
+++ b/indra/newview/llpanelsnapshot.h
@@ -27,9 +27,13 @@
#ifndef LL_LLPANELSNAPSHOT_H
#define LL_LLPANELSNAPSHOT_H
-#include "llfloatersnapshot.h"
+//#include "llfloatersnapshot.h"
+#include "llpanel.h"
+#include "llsnapshotmodel.h"
+class LLSpinCtrl;
class LLSideTrayPanelContainer;
+class LLFloaterSnapshotBase;
/**
* Snapshot panel base class.
@@ -37,6 +41,8 @@ class LLSideTrayPanelContainer;
class LLPanelSnapshot: public LLPanel
{
public:
+ LLPanelSnapshot();
+
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
@@ -51,7 +57,8 @@ public:
virtual LLSpinCtrl* getWidthSpinner();
virtual LLSpinCtrl* getHeightSpinner();
virtual void enableAspectRatioCheckbox(BOOL enable);
- virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const;
+ virtual LLSnapshotModel::ESnapshotFormat getImageFormat() const;
+ virtual LLSnapshotModel::ESnapshotType getSnapshotType();
virtual void updateControls(const LLSD& info) = 0; ///< Update controls from saved settings
void enableControls(BOOL enable);
@@ -59,12 +66,14 @@ protected:
LLSideTrayPanelContainer* getParentContainer();
void updateImageQualityLevel();
void goBack(); ///< Switch to the default (Snapshot Options) panel
- void cancel();
+ virtual void cancel();
// common UI callbacks
void onCustomResolutionCommit();
void onResolutionComboCommit(LLUICtrl* ctrl);
void onKeepAspectRatioCommit(LLUICtrl* ctrl);
+
+ LLFloaterSnapshotBase* mSnapshotFloater;
};
#endif // LL_LLPANELSNAPSHOT_H
diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index a2d1752c6a..b2952834fb 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -33,6 +33,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llstatusbar.h" // can_afford_transaction()
#include "llnotificationsutil.h"
@@ -40,8 +41,22 @@
/**
* The panel provides UI for saving snapshot as an inventory texture.
*/
+class LLPanelSnapshotInventoryBase
+ : public LLPanelSnapshot
+{
+ LOG_CLASS(LLPanelSnapshotInventoryBase);
+
+public:
+ LLPanelSnapshotInventoryBase();
+
+ /*virtual*/ BOOL postBuild();
+protected:
+ void onSend();
+ /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
+};
+
class LLPanelSnapshotInventory
-: public LLPanelSnapshot
+ : public LLPanelSnapshotInventoryBase
{
LOG_CLASS(LLPanelSnapshotInventory);
@@ -60,10 +75,46 @@ private:
/*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; }
/*virtual*/ void updateControls(const LLSD& info);
- void onSend();
};
-static LLPanelInjector<LLPanelSnapshotInventory> panel_class("llpanelsnapshotinventory");
+class LLPanelOutfitSnapshotInventory
+ : public LLPanelSnapshotInventoryBase
+{
+ LOG_CLASS(LLPanelOutfitSnapshotInventory);
+
+public:
+ LLPanelOutfitSnapshotInventory();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+private:
+ /*virtual*/ std::string getWidthSpinnerName() const { return ""; }
+ /*virtual*/ std::string getHeightSpinnerName() const { return ""; }
+ /*virtual*/ std::string getAspectRatioCBName() const { return ""; }
+ /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; }
+ /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; }
+ /*virtual*/ void updateControls(const LLSD& info);
+
+ /*virtual*/ void cancel();
+};
+
+static LLPanelInjector<LLPanelSnapshotInventory> panel_class1("llpanelsnapshotinventory");
+
+static LLPanelInjector<LLPanelOutfitSnapshotInventory> panel_class2("llpaneloutfitsnapshotinventory");
+
+LLPanelSnapshotInventoryBase::LLPanelSnapshotInventoryBase()
+{
+}
+
+BOOL LLPanelSnapshotInventoryBase::postBuild()
+{
+ return LLPanelSnapshot::postBuild();
+}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshotInventoryBase::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_TEXTURE;
+}
LLPanelSnapshotInventory::LLPanelSnapshotInventory()
{
@@ -78,7 +129,7 @@ BOOL LLPanelSnapshotInventory::postBuild()
getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(FALSE);
getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1));
- return LLPanelSnapshot::postBuild();
+ return LLPanelSnapshotInventoryBase::postBuild();
}
// virtual
@@ -102,19 +153,59 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected);
}
-void LLPanelSnapshotInventory::onSend()
+void LLPanelSnapshotInventoryBase::onSend()
{
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
if (can_afford_transaction(expected_upload_cost))
{
- LLFloaterSnapshot::saveTexture();
- LLFloaterSnapshot::postSave();
+ if (mSnapshotFloater)
+ {
+ mSnapshotFloater->saveTexture();
+ mSnapshotFloater->postSave();
+ }
}
else
{
LLSD args;
args["COST"] = llformat("%d", expected_upload_cost);
LLNotificationsUtil::add("ErrorPhotoCannotAfford", args);
- LLFloaterSnapshot::inventorySaveFailed();
+ if (mSnapshotFloater)
+ {
+ mSnapshotFloater->inventorySaveFailed();
+ }
+ }
+}
+
+LLPanelOutfitSnapshotInventory::LLPanelOutfitSnapshotInventory()
+{
+ mCommitCallbackRegistrar.add("Inventory.SaveOutfitPhoto", boost::bind(&LLPanelOutfitSnapshotInventory::onSend, this));
+ mCommitCallbackRegistrar.add("Inventory.SaveOutfitCancel", boost::bind(&LLPanelOutfitSnapshotInventory::cancel, this));
+}
+
+// virtual
+BOOL LLPanelOutfitSnapshotInventory::postBuild()
+{
+ return LLPanelSnapshotInventoryBase::postBuild();
+}
+
+// virtual
+void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key)
+{
+ getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()));
+ LLPanelSnapshot::onOpen(key);
+}
+
+// virtual
+void LLPanelOutfitSnapshotInventory::updateControls(const LLSD& info)
+{
+ const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true;
+ getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot);
+}
+
+void LLPanelOutfitSnapshotInventory::cancel()
+{
+ if (mSnapshotFloater)
+ {
+ mSnapshotFloater->closeFloater();
}
}
diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp
index 01dfdc4ece..3652c10586 100644
--- a/indra/newview/llpanelsnapshotlocal.cpp
+++ b/indra/newview/llpanelsnapshotlocal.cpp
@@ -33,6 +33,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerwindow.h"
@@ -55,7 +56,8 @@ private:
/*virtual*/ std::string getAspectRatioCBName() const { return "local_keep_aspect_check"; }
/*virtual*/ std::string getImageSizeComboName() const { return "local_size_combo"; }
/*virtual*/ std::string getImageSizePanelName() const { return "local_image_size_lp"; }
- /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const;
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const;
+ /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
/*virtual*/ void updateControls(const LLSD& info);
S32 mLocalFormat;
@@ -94,23 +96,23 @@ void LLPanelSnapshotLocal::onOpen(const LLSD& key)
}
// virtual
-LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const
+LLSnapshotModel::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const
{
- LLFloaterSnapshot::ESnapshotFormat fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
+ LLSnapshotModel::ESnapshotFormat fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
LLComboBox* local_format_combo = getChild<LLComboBox>("local_format_combo");
const std::string id = local_format_combo->getValue().asString();
if (id == "PNG")
{
- fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
+ fmt = LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
else if (id == "JPEG")
{
- fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
+ fmt = LLSnapshotModel::SNAPSHOT_FORMAT_JPEG;
}
else if (id == "BMP")
{
- fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP;
+ fmt = LLSnapshotModel::SNAPSHOT_FORMAT_BMP;
}
return fmt;
@@ -119,11 +121,11 @@ LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const
// virtual
void LLPanelSnapshotLocal::updateControls(const LLSD& info)
{
- LLFloaterSnapshot::ESnapshotFormat fmt =
- (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotFormat fmt =
+ (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
getChild<LLComboBox>("local_format_combo")->selectNthItem((S32) fmt);
- const bool show_quality_ctrls = (fmt == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+ const bool show_quality_ctrls = (fmt == LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
getChild<LLUICtrl>("image_quality_slider")->setVisible(show_quality_ctrls);
getChild<LLUICtrl>("image_quality_level")->setVisible(show_quality_ctrls);
@@ -162,10 +164,10 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)
LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();
floater->notify(LLSD().with("set-working", true));
- BOOL saved = LLFloaterSnapshot::saveLocal();
+ BOOL saved = floater->saveLocal();
if (saved)
{
- LLFloaterSnapshot::postSave();
+ mSnapshotFloater->postSave();
goBack();
floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local")));
}
@@ -174,3 +176,8 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)
cancel();
}
}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_LOCAL;
+}
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 0fc9ceec83..269f16c5e4 100644
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -62,6 +62,8 @@ private:
void onSendToFacebook();
void onSendToTwitter();
void onSendToFlickr();
+
+ LLFloaterSnapshotBase* mSnapshotFloater;
};
static LLPanelInjector<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions");
@@ -86,6 +88,7 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
// virtual
BOOL LLPanelSnapshotOptions::postBuild()
{
+ mSnapshotFloater = getParentByType<LLFloaterSnapshotBase>();
return LLPanel::postBuild();
}
@@ -112,7 +115,7 @@ void LLPanelSnapshotOptions::openPanel(const std::string& panel_name)
parent->openPanel(panel_name);
parent->getCurrentPanel()->onOpen(LLSD());
- LLFloaterSnapshot::postPanelSwitch();
+ mSnapshotFloater->postPanelSwitch();
}
void LLPanelSnapshotOptions::onSaveToProfile()
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index e4f39aac04..be8bde09f8 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -38,6 +38,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
#include "llpostcard.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerwindow.h"
#include "llviewerregion.h"
@@ -64,12 +65,13 @@ private:
/*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; }
/*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; }
/*virtual*/ std::string getImageSizePanelName() const { return "postcard_image_size_lp"; }
- /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; }
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; }
+ /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
/*virtual*/ void updateControls(const LLSD& info);
bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
- static void sendPostcardFinished(LLSD result);
- void sendPostcard();
+ static void sendPostcardFinished(LLSD result);
+ void sendPostcard();
void onMsgFormFocusRecieved();
void onFormatComboCommit(LLUICtrl* ctrl);
@@ -93,13 +95,6 @@ LLPanelSnapshotPostcard::LLPanelSnapshotPostcard()
// virtual
BOOL LLPanelSnapshotPostcard::postBuild()
{
- // pick up the user's up-to-date email address
- gAgent.sendAgentUserInfoRequest();
-
- std::string name_string;
- LLAgentUI::buildFullname(name_string);
- getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string));
-
// For the first time a user focuses to .the msg box, all text will be selected.
getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(&LLPanelSnapshotPostcard::onMsgFormFocusRecieved, this));
@@ -113,6 +108,16 @@ BOOL LLPanelSnapshotPostcard::postBuild()
// virtual
void LLPanelSnapshotPostcard::onOpen(const LLSD& key)
{
+ // pick up the user's up-to-date email address
+ if (mAgentEmail.empty())
+ {
+ gAgent.sendAgentUserInfoRequest();
+
+ std::string name_string;
+ LLAgentUI::buildFullname(name_string);
+ getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string));
+ }
+
LLPanelSnapshot::onOpen(key);
}
@@ -190,8 +195,8 @@ void LLPanelSnapshotPostcard::sendPostcard()
getChild<LLUICtrl>("to_form")->getValue().asString(),
getChild<LLUICtrl>("subject_form")->getValue().asString(),
getChild<LLUICtrl>("msg_form")->getValue().asString(),
- LLFloaterSnapshot::getPosTakenGlobal(),
- LLFloaterSnapshot::getImageData(),
+ mSnapshotFloater->getPosTakenGlobal(),
+ mSnapshotFloater->getImageData(),
boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
@@ -205,7 +210,7 @@ void LLPanelSnapshotPostcard::sendPostcard()
// Give user feedback of the event.
gViewerWindow->playSnapshotAnimAndSound();
- LLFloaterSnapshot::postSave();
+ mSnapshotFloater->postSave();
}
void LLPanelSnapshotPostcard::onMsgFormFocusRecieved()
@@ -264,3 +269,8 @@ void LLPanelSnapshotPostcard::onSend()
// Send postcard.
sendPostcard();
}
+
+LLSnapshotModel::ESnapshotType LLPanelSnapshotPostcard::getSnapshotType()
+{
+ return LLSnapshotModel::SNAPSHOT_POSTCARD;
+}
diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp
index 8949eb73eb..38dec78030 100644
--- a/indra/newview/llpanelsnapshotprofile.cpp
+++ b/indra/newview/llpanelsnapshotprofile.cpp
@@ -58,7 +58,7 @@ private:
/*virtual*/ std::string getAspectRatioCBName() const { return "profile_keep_aspect_check"; }
/*virtual*/ std::string getImageSizeComboName() const { return "profile_size_combo"; }
/*virtual*/ std::string getImageSizePanelName() const { return "profile_image_size_lp"; }
- /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const { return LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; }
+ /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; }
/*virtual*/ void updateControls(const LLSD& info);
void onSend();
@@ -96,6 +96,6 @@ void LLPanelSnapshotProfile::onSend()
std::string caption = getChild<LLUICtrl>("caption")->getValue().asString();
bool add_location = getChild<LLUICtrl>("add_location_cb")->getValue().asBoolean();
- LLWebProfile::uploadImage(LLFloaterSnapshot::getImageData(), caption, add_location);
- LLFloaterSnapshot::postSave();
+ LLWebProfile::uploadImage(mSnapshotFloater->getImageData(), caption, add_location);
+ mSnapshotFloater->postSave();
}
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index d0353259a5..796372ba04 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -30,13 +30,19 @@
#include "lltoggleablemenu.h"
+#include "llagent.h"
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
#include "llappearancemgr.h"
#include "llfloatersidepanelcontainer.h"
#include "llinventoryfunctions.h"
+#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llmenubutton.h"
+#include "llscrolllistctrl.h"
#include "llviewermenu.h"
+#include "llviewerregion.h"
#include "llwearableitemslist.h"
#include "llsdserialize.h"
#include "llclipboard.h"
@@ -146,11 +152,47 @@ protected:
menu->setItemVisible("detach", allow_detach);
menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach);
menu->setItemVisible("show_original", mUUIDs.size() == 1);
+ menu->setItemVisible("edit_item", FALSE);
}
};
//////////////////////////////////////////////////////////////////////////
+class LLTempAttachmentsContextMenu : public LLListContextMenu
+{
+public:
+ LLTempAttachmentsContextMenu(LLPanelWearing* panel_wearing)
+ : mPanelWearing(panel_wearing)
+ {}
+protected:
+ /* virtual */ LLContextMenu* createMenu()
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("Wearing.EditItem", boost::bind(&LLPanelWearing::onEditAttachment, mPanelWearing));
+ registrar.add("Wearing.Detach", boost::bind(&LLPanelWearing::onRemoveAttachment, mPanelWearing));
+ LLContextMenu* menu = createFromFile("menu_wearing_tab.xml");
+
+ updateMenuItemsVisibility(menu);
+
+ return menu;
+ }
+
+ void updateMenuItemsVisibility(LLContextMenu* menu)
+ {
+ menu->setItemVisible("take_off", FALSE);
+ menu->setItemVisible("detach", TRUE);
+ menu->setItemVisible("edit_outfit_separator", TRUE);
+ menu->setItemVisible("show_original", FALSE);
+ menu->setItemVisible("edit_item", TRUE);
+ menu->setItemVisible("edit", FALSE);
+ }
+
+ LLPanelWearing* mPanelWearing;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null;
static LLPanelInjector<LLPanelWearing> t_panel_wearing("panel_wearing");
@@ -159,30 +201,47 @@ LLPanelWearing::LLPanelWearing()
: LLPanelAppearanceTab()
, mCOFItemsList(NULL)
, mIsInitialized(false)
+ , mAttachmentsChangedConnection()
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
mGearMenu = new LLWearingGearMenu(this);
mContextMenu = new LLWearingContextMenu();
+ mAttachmentsMenu = new LLTempAttachmentsContextMenu(this);
}
LLPanelWearing::~LLPanelWearing()
{
delete mGearMenu;
delete mContextMenu;
+ delete mAttachmentsMenu;
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
}
delete mCategoriesObserver;
+
+ if (mAttachmentsChangedConnection.connected())
+ {
+ mAttachmentsChangedConnection.disconnect();
+ }
}
BOOL LLPanelWearing::postBuild()
{
+ mAccordionCtrl = getChild<LLAccordionCtrl>("wearables_accordion");
+ mWearablesTab = getChild<LLAccordionCtrlTab>("tab_wearables");
+ mAttachmentsTab = getChild<LLAccordionCtrlTab>("tab_temp_attachments");
+ mAttachmentsTab->setDropDownStateChangedCallback(boost::bind(&LLPanelWearing::onAccordionTabStateChanged, this));
+
mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list");
mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3));
+ mTempItemsList = getChild<LLScrollListCtrl>("temp_attachments_list");
+ mTempItemsList->setFgUnselectedColor(LLColor4::white);
+ mTempItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onTempAttachmentsListRightClick, this, _1, _2, _3));
+
LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
menu_gear_btn->setMenu(mGearMenu->getMenu());
@@ -223,6 +282,44 @@ void LLPanelWearing::onOpen(const LLSD& /*info*/)
}
}
+void LLPanelWearing::draw()
+{
+ if (mUpdateTimer.getStarted() && (mUpdateTimer.getElapsedTimeF32() > 0.1))
+ {
+ mUpdateTimer.stop();
+ updateAttachmentsList();
+ }
+ LLPanel::draw();
+}
+
+void LLPanelWearing::onAccordionTabStateChanged()
+{
+ if(mAttachmentsTab->isExpanded())
+ {
+ startUpdateTimer();
+ mAttachmentsChangedConnection = LLAppearanceMgr::instance().setAttachmentsChangedCallback(boost::bind(&LLPanelWearing::startUpdateTimer, this));
+ }
+ else
+ {
+ if (mAttachmentsChangedConnection.connected())
+ {
+ mAttachmentsChangedConnection.disconnect();
+ }
+ }
+}
+
+void LLPanelWearing::startUpdateTimer()
+{
+ if (!mUpdateTimer.getStarted())
+ {
+ mUpdateTimer.start();
+ }
+ else
+ {
+ mUpdateTimer.reset();
+ }
+}
+
// virtual
void LLPanelWearing::setFilterSubString(const std::string& string)
{
@@ -251,6 +348,124 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
return false;
}
+void LLPanelWearing::updateAttachmentsList()
+{
+ std::vector<LLViewerObject*> attachs = LLAgentWearables::getTempAttachments();
+ mTempItemsList->deleteAllItems();
+ mAttachmentsMap.clear();
+ if(!attachs.empty())
+ {
+ if(!populateAttachmentsList())
+ {
+ requestAttachmentDetails();
+ }
+ }
+ else
+ {
+ std::string no_attachments = getString("no_attachments");
+ LLSD row;
+ row["columns"][0]["column"] = "text";
+ row["columns"][0]["value"] = no_attachments;
+ row["columns"][0]["font"] = "SansSerifBold";
+ mTempItemsList->addElement(row);
+ }
+}
+
+bool LLPanelWearing::populateAttachmentsList(bool update)
+{
+ bool populated = true;
+ if(mTempItemsList)
+ {
+ mTempItemsList->deleteAllItems();
+ mAttachmentsMap.clear();
+ std::vector<LLViewerObject*> attachs = LLAgentWearables::getTempAttachments();
+
+ std::string icon_name = LLInventoryIcon::getIconName(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT);
+ for (std::vector<LLViewerObject*>::iterator iter = attachs.begin();
+ iter != attachs.end(); ++iter)
+ {
+ LLViewerObject *attachment = *iter;
+ LLSD row;
+ row["id"] = attachment->getID();
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = icon_name;
+ row["columns"][1]["column"] = "text";
+ if(mObjectNames.count(attachment->getID()) && !mObjectNames[attachment->getID()].empty())
+ {
+ row["columns"][1]["value"] = mObjectNames[attachment->getID()];
+ }
+ else if(update)
+ {
+ row["columns"][1]["value"] = attachment->getID();
+ populated = false;
+ }
+ else
+ {
+ row["columns"][1]["value"] = "Loading...";
+ populated = false;
+ }
+ mTempItemsList->addElement(row);
+ mAttachmentsMap[attachment->getID()] = attachment;
+ }
+ }
+ return populated;
+}
+
+void LLPanelWearing::requestAttachmentDetails()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
+ if (!url.empty())
+ {
+ LLCoros::instance().launch("LLPanelWearing::getAttachmentLimitsCoro",
+ boost::bind(&LLPanelWearing::getAttachmentLimitsCoro, this, url));
+ }
+}
+
+void LLPanelWearing::getAttachmentLimitsCoro(std::string url)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL;
+ return;
+ }
+
+ result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+ setAttachmentDetails(result);
+}
+
+
+void LLPanelWearing::setAttachmentDetails(LLSD content)
+{
+ mObjectNames.clear();
+ S32 number_attachments = content["attachments"].size();
+ for(int i = 0; i < number_attachments; i++)
+ {
+ S32 number_objects = content["attachments"][i]["objects"].size();
+ for(int j = 0; j < number_objects; j++)
+ {
+ LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
+ std::string name = content["attachments"][i]["objects"][j]["name"].asString();
+ mObjectNames[task_id] = name;
+ }
+ }
+ if(!mObjectNames.empty())
+ {
+ populateAttachmentsList(true);
+ }
+}
+
boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb)
{
if (!mCOFItemsList) return boost::signals2::connection();
@@ -270,6 +485,20 @@ void LLPanelWearing::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
mContextMenu->show(ctrl, selected_uuids, x, y);
}
+void LLPanelWearing::onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
+{
+ LLScrollListCtrl* list = dynamic_cast<LLScrollListCtrl*>(ctrl);
+ if (!list) return;
+ list->selectItemAt(x, y, MASK_NONE);
+ uuid_vec_t selected_uuids;
+
+ if(list->getCurrentID().notNull())
+ {
+ selected_uuids.push_back(list->getCurrentID());
+ mAttachmentsMenu->show(ctrl, selected_uuids, x, y);
+ }
+}
+
bool LLPanelWearing::hasItemSelected()
{
return mCOFItemsList->getSelectedItem() != NULL;
@@ -280,6 +509,28 @@ void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
mCOFItemsList->getSelectedUUIDs(selected_uuids);
}
+void LLPanelWearing::onEditAttachment()
+{
+ LLScrollListItem* item = mTempItemsList->getFirstSelected();
+ if (item)
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]);
+ handle_object_edit();
+ }
+}
+
+void LLPanelWearing::onRemoveAttachment()
+{
+ LLScrollListItem* item = mTempItemsList->getFirstSelected();
+ if (item)
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]);
+ LLSelectMgr::getInstance()->sendDropAttachment();
+ }
+}
+
void LLPanelWearing::copyToClipboard()
{
std::string text;
diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h
index 9a212b3cca..c5cb79092a 100644
--- a/indra/newview/llpanelwearing.h
+++ b/indra/newview/llpanelwearing.h
@@ -31,9 +31,14 @@
// newview
#include "llpanelappearancetab.h"
+#include "llselectmgr.h"
+#include "lltimer.h"
+class LLAccordionCtrl;
+class LLAccordionCtrlTab;
class LLInventoryCategoriesObserver;
class LLListContextMenu;
+class LLScrollListCtrl;
class LLWearableItemsList;
class LLWearingGearMenu;
@@ -52,6 +57,8 @@ public:
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+
/*virtual*/ void onOpen(const LLSD& info);
/*virtual*/ void setFilterSubString(const std::string& string);
@@ -62,17 +69,43 @@ public:
/*virtual*/ void copyToClipboard();
+ void startUpdateTimer();
+ void updateAttachmentsList();
+
boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb);
bool hasItemSelected();
+ bool populateAttachmentsList(bool update = false);
+ void onAccordionTabStateChanged();
+ void setAttachmentDetails(LLSD content);
+ void requestAttachmentDetails();
+ void onEditAttachment();
+ void onRemoveAttachment();
+
private:
void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
+ void onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
+
+ void getAttachmentLimitsCoro(std::string url);
LLInventoryCategoriesObserver* mCategoriesObserver;
LLWearableItemsList* mCOFItemsList;
+ LLScrollListCtrl* mTempItemsList;
LLWearingGearMenu* mGearMenu;
LLListContextMenu* mContextMenu;
+ LLListContextMenu* mAttachmentsMenu;
+
+ LLAccordionCtrlTab* mWearablesTab;
+ LLAccordionCtrlTab* mAttachmentsTab;
+ LLAccordionCtrl* mAccordionCtrl;
+
+ std::map<LLUUID, LLViewerObject*> mAttachmentsMap;
+
+ std::map<LLUUID, std::string> mObjectNames;
+
+ boost::signals2::connection mAttachmentsChangedConnection;
+ LLFrameTimer mUpdateTimer;
bool mIsInitialized;
};
diff --git a/indra/newview/llpathfindinglinksetlist.cpp b/indra/newview/llpathfindinglinksetlist.cpp
index b886e46765..eb7b95552e 100644
--- a/indra/newview/llpathfindinglinksetlist.cpp
+++ b/indra/newview/llpathfindinglinksetlist.cpp
@@ -204,7 +204,10 @@ void LLPathfindingLinksetList::parseLinksetListData(const LLSD& pLinksetListData
{
const std::string& uuid(linksetDataIter->first);
const LLSD& linksetData = linksetDataIter->second;
- LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData));
- objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr));
+ if(linksetData.size() != 0)
+ {
+ LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData));
+ objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr));
+ }
}
}
diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp
index 9957039f72..836f63bffa 100644
--- a/indra/newview/llpresetsmanager.cpp
+++ b/indra/newview/llpresetsmanager.cpp
@@ -104,8 +104,7 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam
if (found)
{
std::string path = gDirUtilp->add(dir, file);
- std::string name = gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true);
-
+ std::string name = LLURI::unescape(gDirUtilp->getBaseFileName(path, /*strip_exten = */ true));
LL_DEBUGS() << " Found preset '" << name << "'" << LL_ENDL;
if (PRESETS_DEFAULT != name)
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index ba9845ef04..510d91839d 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -437,6 +437,23 @@ void LLPreviewNotecard::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId,
}
}
+void LLPreviewNotecard::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId)
+{
+
+ LLSD floater_key;
+ floater_key["taskid"] = taskId;
+ floater_key["itemid"] = itemId;
+ LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", floater_key);
+ if (nc)
+ {
+ if (nc->hasEmbeddedInventory())
+ {
+ gVFS->removeFile(newAssetId, LLAssetType::AT_NOTECARD);
+ }
+ nc->setAssetId(newAssetId);
+ nc->refreshFromInventory();
+ }
+}
bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
{
@@ -485,7 +502,7 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
else if (!mObjectUUID.isNull() && !task_url.empty())
{
uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer,
- boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _3, LLUUID::null)));
+ boost::bind(&LLPreviewNotecard::finishTaskUpload, _1, _3, mObjectUUID)));
url = task_url;
}
diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h
index ba571995f6..017c4485ba 100644
--- a/indra/newview/llpreviewnotecard.h
+++ b/indra/newview/llpreviewnotecard.h
@@ -96,6 +96,7 @@ protected:
bool handleConfirmDeleteDialog(const LLSD& notification, const LLSD& response);
static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId);
+ static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId);
protected:
LLViewerTextEditor* mEditor;
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 5b1b356597..f28ffce602 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -375,7 +375,8 @@ LLScriptEdCore::LLScriptEdCore(
mLiveFile(NULL),
mLive(live),
mContainer(container),
- mHasScriptData(FALSE)
+ mHasScriptData(FALSE),
+ mScriptRemoved(FALSE)
{
setFollowsAll();
setBorderVisible(FALSE);
@@ -666,7 +667,7 @@ bool LLScriptEdCore::hasChanged()
void LLScriptEdCore::draw()
{
BOOL script_changed = hasChanged();
- getChildView("Save_btn")->setEnabled(script_changed);
+ getChildView("Save_btn")->setEnabled(script_changed && !mScriptRemoved);
if( mEditor->hasFocus() )
{
@@ -840,7 +841,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string)
BOOL LLScriptEdCore::canClose()
{
- if(mForceClose || !hasChanged())
+ if(mForceClose || !hasChanged() || mScriptRemoved)
{
return TRUE;
}
@@ -1511,6 +1512,17 @@ BOOL LLPreviewLSL::postBuild()
return LLPreview::postBuild();
}
+void LLPreviewLSL::draw()
+{
+ const LLInventoryItem* item = getItem();
+ if(!item)
+ {
+ setTitle(LLTrans::getString("ScriptWasDeleted"));
+ mScriptEd->setItemRemoved(TRUE);
+ }
+
+ LLPreview::draw();
+}
// virtual
void LLPreviewLSL::callbackLSLCompileSucceeded()
{
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index a8c6a6eeeb..6b31125641 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -119,6 +119,8 @@ public:
void setScriptName(const std::string& name){mScriptName = name;};
+ void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;};
+
private:
void onBtnHelp();
void onBtnDynamicHelp();
@@ -163,6 +165,7 @@ private:
BOOL mHasScriptData;
LLLiveLSLFile* mLiveFile;
LLUUID mAssociatedExperience;
+ BOOL mScriptRemoved;
LLScriptEdContainer* mContainer; // parent view
@@ -198,6 +201,7 @@ public:
/*virtual*/ BOOL postBuild();
protected:
+ virtual void draw();
virtual BOOL canClose();
void closeIfNeeded();
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index 4f9f83b6f2..72d7cf1e45 100644
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -29,6 +29,8 @@
#include "llviewerprecompiledheaders.h"
#include "llsecapi.h"
#include "llsechandler_basic.h"
+#include "llexception.h"
+#include "stringize.h"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <map>
@@ -64,12 +66,12 @@ void initializeSecHandler()
}
catch (LLProtectedDataException e)
{
- exception_msg = e.getMessage();
+ exception_msg = e.what();
}
}
if (!exception_msg.empty()) // an exception was thrown.
{
- throw LLProtectedDataException(exception_msg.c_str());
+ LLTHROW(LLProtectedDataException(exception_msg));
}
}
@@ -101,6 +103,7 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred)
LLSD LLCredential::getLoginParams()
{
LLSD result = LLSD::emptyMap();
+ std::string username;
try
{
if (mIdentifier["type"].asString() == "agent")
@@ -109,17 +112,19 @@ LLSD LLCredential::getLoginParams()
result["passwd"] = "$1$" + mAuthenticator["secret"].asString();
result["first"] = mIdentifier["first_name"];
result["last"] = mIdentifier["last_name"];
-
+ username = result["first"].asString() + " " + result["last"].asString();
}
else if (mIdentifier["type"].asString() == "account")
{
result["username"] = mIdentifier["account_name"];
result["passwd"] = mAuthenticator["secret"];
-
+ username = result["username"].asString();
}
}
catch (...)
{
+ // nat 2016-08-18: not clear what exceptions the above COULD throw?!
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("for '" << username << "'"));
// we could have corrupt data, so simply return a null login param if so
LL_WARNS("AppInit") << "Invalid credential" << LL_ENDL;
}
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index 6fe3ee31cf..6af5a28fa5 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -32,6 +32,7 @@
#include <openssl/x509.h>
#include <ostream>
#include "llpointer.h"
+#include "llexception.h"
#ifdef LL_WINDOWS
#pragma warning(disable:4250)
@@ -116,17 +117,13 @@
-class LLProtectedDataException
+struct LLProtectedDataException: public LLException
{
-public:
- LLProtectedDataException(const char *msg)
+ LLProtectedDataException(const std::string& msg):
+ LLException(msg)
{
- LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL;
- mMsg = (std::string)msg;
+ LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL;
}
- std::string getMessage() { return mMsg; }
-protected:
- std::string mMsg;
};
// class LLCertificate
@@ -334,22 +331,21 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
// All error handling is via exceptions.
-class LLCertException
+class LLCertException: public LLException
{
public:
- LLCertException(LLPointer<LLCertificate> cert, const char* msg)
+ LLCertException(LLPointer<LLCertificate> cert, const std::string& msg):
+ LLException(msg)
{
mCert = cert;
- LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL;
- mMsg = (std::string)msg;
+ LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
}
- LLPointer<LLCertificate> getCert() { return mCert; }
- std::string getMessage() { return mMsg; }
+ virtual ~LLCertException() throw() {}
+ LLPointer<LLCertificate> getCert() const { return mCert; }
protected:
LLPointer<LLCertificate> mCert;
- std::string mMsg;
};
class LLInvalidCertificate : public LLCertException
@@ -358,6 +354,7 @@ public:
LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")
{
}
+ virtual ~LLInvalidCertificate() throw() {}
protected:
};
@@ -367,6 +364,7 @@ public:
LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")
{
}
+ virtual ~LLCertValidationTrustException() throw() {}
protected:
};
@@ -378,7 +376,7 @@ public:
{
mHostname = hostname;
}
-
+ virtual ~LLCertValidationHostnameException() throw() {}
std::string getHostname() { return mHostname; }
protected:
std::string mHostname;
@@ -392,6 +390,7 @@ public:
{
mTime = current_time;
}
+ virtual ~LLCertValidationExpirationException() throw() {}
LLDate GetTime() { return mTime; }
protected:
LLDate mTime;
@@ -403,6 +402,7 @@ public:
LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")
{
}
+ virtual ~LLCertKeyUsageValidationException() throw() {}
protected:
};
@@ -412,6 +412,7 @@ public:
LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")
{
}
+ virtual ~LLCertBasicConstraintsValidationException() throw() {}
protected:
};
@@ -421,6 +422,7 @@ public:
LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")
{
}
+ virtual ~LLCertValidationInvalidSignatureException() throw() {}
protected:
};
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 40516f9bbb..d6fb801cc0 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -35,6 +35,8 @@
#include "llfile.h"
#include "lldir.h"
#include "llviewercontrol.h"
+#include "llexception.h"
+#include "stringize.h"
#include <vector>
#include <ios>
#include <openssl/ossl_typ.h>
@@ -72,14 +74,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert)
if(pem_bio == NULL)
{
LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
- throw LLInvalidCertificate(this);
+ LLTHROW(LLInvalidCertificate(this));
}
mCert = NULL;
PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
BIO_free(pem_bio);
if (!mCert)
{
- throw LLInvalidCertificate(this);
+ LLTHROW(LLInvalidCertificate(this));
}
}
@@ -88,7 +90,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert)
{
if (!pCert || !pCert->cert_info)
{
- throw LLInvalidCertificate(this);
+ LLTHROW(LLInvalidCertificate(this));
}
mCert = X509_dup(pCert);
}
@@ -617,7 +619,7 @@ void LLBasicCertificateStore::load_from_file(const std::string& filename)
}
catch (...)
{
- LL_WARNS("SECAPI") << "Failure creating certificate from the certificate store file." << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file");
}
X509_free(cert_x509);
cert_x509 = NULL;
@@ -873,22 +875,22 @@ void _validateCert(int validation_policy,
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))
{
- throw LLCertException(cert, "Cert doesn't have a Subject Name");
+ LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name"));
}
if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))
{
- throw LLCertException(cert, "Cert doesn't have an Issuer Name");
+ LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name"));
}
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))
{
- throw LLCertException(cert, "Cert doesn't have an expiration period");
+ LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period"));
}
if (!current_cert_info.has(CERT_SHA1_DIGEST))
{
- throw LLCertException(cert, "No SHA1 digest");
+ LLTHROW(LLCertException(cert, "No SHA1 digest"));
}
if (validation_policy & VALIDATION_POLICY_TIME)
@@ -903,7 +905,7 @@ void _validateCert(int validation_policy,
if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||
(validation_date > current_cert_info[CERT_VALID_TO].asDate()))
{
- throw LLCertValidationExpirationException(cert, validation_date);
+ LLTHROW(LLCertValidationExpirationException(cert, validation_date));
}
}
if (validation_policy & VALIDATION_POLICY_SSL_KU)
@@ -914,14 +916,14 @@ void _validateCert(int validation_policy,
!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
{
- throw LLCertKeyUsageValidationException(cert);
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
// only validate EKU if the cert has it
if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&
(!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
LLSD((std::string)CERT_EKU_SERVER_AUTH))))
{
- throw LLCertKeyUsageValidationException(cert);
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
}
if (validation_policy & VALIDATION_POLICY_CA_KU)
@@ -930,7 +932,7 @@ void _validateCert(int validation_policy,
(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
(std::string)CERT_KU_CERT_SIGN)))
{
- throw LLCertKeyUsageValidationException(cert);
+ LLTHROW(LLCertKeyUsageValidationException(cert));
}
}
@@ -942,13 +944,13 @@ void _validateCert(int validation_policy,
if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||
!current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])
{
- throw LLCertBasicConstraintsValidationException(cert);
+ LLTHROW(LLCertBasicConstraintsValidationException(cert));
}
if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&
((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&
(depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))
{
- throw LLCertBasicConstraintsValidationException(cert);
+ LLTHROW(LLCertBasicConstraintsValidationException(cert));
}
}
}
@@ -1018,7 +1020,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(cert_chain->size() < 1)
{
- throw LLCertException(NULL, "No certs in chain");
+ LLTHROW(LLCertException(NULL, "No certs in chain"));
}
iterator current_cert = cert_chain->begin();
LLSD current_cert_info;
@@ -1033,11 +1035,11 @@ void LLBasicCertificateStore::validate(int validation_policy,
(*current_cert)->getLLSD(current_cert_info);
if(!validation_params.has(CERT_HOSTNAME))
{
- throw LLCertException((*current_cert), "No hostname passed in for validation");
+ LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation"));
}
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))
{
- throw LLInvalidCertificate((*current_cert));
+ LLTHROW(LLInvalidCertificate((*current_cert)));
}
LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<
@@ -1054,7 +1056,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
X509* cert_x509 = (*current_cert)->getOpenSSLX509();
if(!cert_x509)
{
- throw LLInvalidCertificate((*current_cert));
+ LLTHROW(LLInvalidCertificate((*current_cert)));
}
std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
X509_free( cert_x509 );
@@ -1075,7 +1077,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if((validation_date < cache_entry->second.first) ||
(validation_date > cache_entry->second.second))
{
- throw LLCertValidationExpirationException((*current_cert), validation_date);
+ LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));
}
}
// successfully found in cache
@@ -1107,7 +1109,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*current_cert),
previous_cert))
{
- throw LLCertValidationInvalidSignatureException(previous_cert);
+ LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));
}
}
_validateCert(local_validation_policy,
@@ -1156,7 +1158,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*found_store_cert),
(*current_cert)))
{
- throw LLCertValidationInvalidSignatureException(*current_cert);
+ LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));
}
// successfully validated.
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
@@ -1173,7 +1175,7 @@ void LLBasicCertificateStore::validate(int validation_policy,
if (validation_policy & VALIDATION_POLICY_TRUSTED)
{
// we reached the end without finding a trusted cert.
- throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]);
+ LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));
}
mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
@@ -1261,7 +1263,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
if (protected_data_stream.gcount() < STORE_SALT_SIZE)
{
- throw LLProtectedDataException("Config file too short.");
+ LLTHROW(LLProtectedDataException("Config file too short."));
}
cipher.decrypt(salt, STORE_SALT_SIZE);
@@ -1301,7 +1303,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
if (parser->parse(parse_stream, mProtectedDataMap,
LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
{
- throw LLProtectedDataException("Config file cannot be decrypted.");
+ LLTHROW(LLProtectedDataException("Config file cannot be decrypted."));
}
}
}
@@ -1364,7 +1366,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()
}
catch (...)
{
- LL_WARNS() << "LLProtectedDataException(Error writing Protected Data Store)" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION("LLProtectedDataException(Error writing Protected Data Store)");
// it's good practice to clean up any secure information on error
// (even though this file isn't really secure. Perhaps in the future
// it may be, however.
@@ -1372,39 +1374,39 @@ void LLSecAPIBasicHandler::_writeProtectedData()
// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
// Decided throwing an exception here was overkill until we figure out why this happens
- //throw LLProtectedDataException("Error writing Protected Data Store");
+ //LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));
}
- try
- {
- // move the temporary file to the specified file location.
- if((( (LLFile::isfile(mProtectedDataFilename) != 0)
- && (LLFile::remove(mProtectedDataFilename) != 0)))
- || (LLFile::rename(tmp_filename, mProtectedDataFilename)))
- {
- LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL;
- LLFile::remove(tmp_filename);
+ try
+ {
+ // move the temporary file to the specified file location.
+ if((( (LLFile::isfile(mProtectedDataFilename) != 0)
+ && (LLFile::remove(mProtectedDataFilename) != 0)))
+ || (LLFile::rename(tmp_filename, mProtectedDataFilename)))
+ {
+ LL_WARNS() << "LLProtectedDataException(Could not overwrite protected data store)" << LL_ENDL;
+ LLFile::remove(tmp_filename);
- // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
- // Decided throwing an exception here was overkill until we figure out why this happens
- //throw LLProtectedDataException("Could not overwrite protected data store");
- }
+ // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
+ // Decided throwing an exception here was overkill until we figure out why this happens
+ //LLTHROW(LLProtectedDataException("Could not overwrite protected data store"));
+ }
}
catch (...)
{
- LL_WARNS() << "LLProtectedDataException(Error renaming '" << tmp_filename
- << "' to '" << mProtectedDataFilename << "')" << LL_ENDL;
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("renaming '" << tmp_filename << "' to '"
+ << mProtectedDataFilename << "'"));
// it's good practice to clean up any secure information on error
// (even though this file isn't really secure. Perhaps in the future
- // it may be, however.
+ // it may be, however).
LLFile::remove(tmp_filename);
//crash in LLSecAPIBasicHandler::_writeProtectedData()
// Decided throwing an exception here was overkill until we figure out why this happens
- //throw LLProtectedDataException("Error writing Protected Data Store");
+ //LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));
}
}
-
+
// instantiate a certificate from a pem string
LLPointer<LLCertificate> LLSecAPIBasicHandler::getCertificate(const std::string& pem_cert)
{
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 86135ee6e8..f07f0ed86c 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -383,7 +383,7 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam
void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch)
{
- if (!mEditWearable || mEditWearable->getVisible() == visible)
+ if (!mEditWearable || ((mEditWearable->getWearable() == wearable) && mEditWearable->getVisible() == visible))
{
// visibility isn't changing, hence nothing to do
return;
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 623565817d..049aae1336 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -86,13 +86,13 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
mNeedsFlash(TRUE),
mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
mDataSize(0),
- mSnapshotType(SNAPSHOT_POSTCARD),
- mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
+ mSnapshotType(LLSnapshotModel::SNAPSHOT_POSTCARD),
+ mSnapshotFormat(LLSnapshotModel::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
mSnapshotUpToDate(FALSE),
mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
mSnapshotActive(FALSE),
- mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
+ mSnapshotBufferType(LLSnapshotModel::SNAPSHOT_TYPE_COLOR),
mFilterName(""),
mAllowRenderUI(TRUE),
mAllowFullScreenPreview(TRUE),
@@ -737,7 +737,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->getWidth(),
previewp->getHeight(),
previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
- previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
+ previewp->getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE,
previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
FALSE,
previewp->mSnapshotBufferType,
@@ -813,7 +813,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame()
mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex];
gGL.getTexUnit(0)->bind(curr_preview_image);
- curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
+ curr_preview_image->setFilteringOption(getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -827,7 +827,7 @@ void LLSnapshotLivePreview::prepareFreezeFrame()
S32 LLSnapshotLivePreview::getEncodedImageWidth() const
{
S32 width = getWidth();
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE);
}
@@ -836,7 +836,7 @@ S32 LLSnapshotLivePreview::getEncodedImageWidth() const
S32 LLSnapshotLivePreview::getEncodedImageHeight() const
{
S32 height = getHeight();
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE);
}
@@ -854,7 +854,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
mPreviewImage->getHeight(),
mPreviewImage->getComponents());
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
// We don't store the intermediate formatted image in mFormattedImage in the J2C case
LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL;
@@ -881,7 +881,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
{
// Update mFormattedImage if necessary
getFormattedImage();
- if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
+ if (getSnapshotFormat() == LLSnapshotModel::SNAPSHOT_FORMAT_BMP)
{
// BMP hack : copy instead of decode otherwise decode will crash.
mPreviewImageEncoded->copy(mPreviewImage);
@@ -903,23 +903,23 @@ void LLSnapshotLivePreview::estimateDataSize()
// Compression ratio
F32 ratio = 1.0;
- if (getSnapshotType() == SNAPSHOT_TEXTURE)
+ if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
ratio = 8.0; // This is what we shoot for when compressing to J2C
}
else
{
- LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
+ LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
switch (format)
{
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
ratio = 3.0; // Average observed PNG compression ratio
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
// Observed from JPG compression tests
ratio = (110 - mSnapshotQuality) / 2;
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
ratio = 1.0; // No compression with BMP
break;
}
@@ -947,18 +947,18 @@ LLPointer<LLImageFormatted> LLSnapshotLivePreview::getFormattedImage()
}
// Create the new formatted image of the appropriate format.
- LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
+ LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL;
switch (format)
{
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
mFormattedImage = new LLImagePNG();
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
mFormattedImage = new LLImageJPEG(mSnapshotQuality);
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
mFormattedImage = new LLImageBMP();
break;
}
@@ -978,7 +978,7 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h)
setHeight(h);
}
-void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format)
+void LLSnapshotLivePreview::setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format)
{
if (mSnapshotFormat != format)
{
@@ -993,7 +993,7 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
h = getHeight();
}
-void LLSnapshotLivePreview::saveTexture()
+void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
{
LL_DEBUGS() << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
// gen a new uuid for this asset
@@ -1033,12 +1033,14 @@ void LLSnapshotLivePreview::saveTexture()
std::string who_took_it;
LLAgentUI::buildFullname(who_took_it);
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
- std::string name = "Snapshot: " + pos_string;
- std::string desc = "Taken by " + who_took_it + " at " + pos_string;
+ std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;
+ std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;
+ LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY;
+ LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT;
LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
- tid, LLAssetType::AT_TEXTURE, name, desc, 0,
- LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT,
+ tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0,
+ folder_type, inv_type,
PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost));
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 57e5d83f8e..b689c50320 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -27,7 +27,7 @@
#ifndef LL_LLSNAPSHOTLIVEPREVIEW_H
#define LL_LLSNAPSHOTLIVEPREVIEW_H
-#include "llpanelsnapshot.h"
+#include "llsnapshotmodel.h"
#include "llviewertexture.h"
#include "llviewerwindow.h"
@@ -40,14 +40,6 @@ class LLSnapshotLivePreview : public LLView
{
LOG_CLASS(LLSnapshotLivePreview);
public:
- enum ESnapshotType
- {
- SNAPSHOT_POSTCARD,
- SNAPSHOT_TEXTURE,
- SNAPSHOT_LOCAL,
- SNAPSHOT_WEB
- };
-
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
@@ -80,8 +72,8 @@ public:
void setMaxImageSize(S32 size) ;
S32 getMaxImageSize() {return mMaxImageSize ;}
- ESnapshotType getSnapshotType() const { return mSnapshotType; }
- LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
+ LLSnapshotModel::ESnapshotType getSnapshotType() const { return mSnapshotType; }
+ LLSnapshotModel::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
BOOL isSnapshotActive() { return mSnapshotActive; }
LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
@@ -98,16 +90,16 @@ public:
void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
- void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
- void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format);
+ void setSnapshotType(LLSnapshotModel::ESnapshotType type) { mSnapshotType = type; }
+ void setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format);
bool setSnapshotQuality(S32 quality, bool set_by_user = true);
- void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
+ void setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType type) { mSnapshotBufferType = type; }
void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; }
void setAllowFullScreenPreview(BOOL allow) { mAllowFullScreenPreview = allow; }
void setFilter(std::string filter_name) { mFilterName = filter_name; }
std::string getFilter() const { return mFilterName; }
void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
- void saveTexture();
+ void saveTexture(BOOL outfit_snapshot = FALSE, std::string name = "");
BOOL saveLocal();
LLPointer<LLImageFormatted> getFormattedImage();
@@ -169,14 +161,14 @@ private:
LLVector3d mPosTakenGlobal;
S32 mSnapshotQuality;
S32 mDataSize;
- ESnapshotType mSnapshotType;
- LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat;
+ LLSnapshotModel::ESnapshotType mSnapshotType;
+ LLSnapshotModel::ESnapshotFormat mSnapshotFormat;
BOOL mSnapshotUpToDate;
LLFrameTimer mFallAnimTimer;
LLVector3 mCameraPos;
LLQuaternion mCameraRot;
BOOL mSnapshotActive;
- LLViewerWindow::ESnapshotType mSnapshotBufferType;
+ LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType;
std::string mFilterName;
public:
diff --git a/indra/newview/llsnapshotmodel.h b/indra/newview/llsnapshotmodel.h
new file mode 100644
index 0000000000..71402fb5bc
--- /dev/null
+++ b/indra/newview/llsnapshotmodel.h
@@ -0,0 +1,55 @@
+/**
+* @file llsnapshotmodel.h
+* @brief Snapshot model for storing snapshot data etc.
+*
+* $LicenseInfo:firstyear=2004&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2016, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLSNAPSHOTMODEL_H
+#define LL_LLSNAPSHOTMODEL_H
+
+class LLSnapshotModel
+{
+public:
+ enum ESnapshotType
+ {
+ SNAPSHOT_POSTCARD,
+ SNAPSHOT_TEXTURE,
+ SNAPSHOT_LOCAL,
+ SNAPSHOT_WEB
+ };
+
+ typedef enum e_snapshot_format
+ {
+ SNAPSHOT_FORMAT_PNG,
+ SNAPSHOT_FORMAT_JPEG,
+ SNAPSHOT_FORMAT_BMP
+ } ESnapshotFormat;
+
+ typedef enum
+ {
+ SNAPSHOT_TYPE_COLOR,
+ SNAPSHOT_TYPE_DEPTH
+ } ESnapshotLayerType;
+};
+
+#endif // LL_LLSNAPSHOTMODEL_H
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index a2c8e7772e..4e81d78455 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -771,7 +771,11 @@ bool idle_startup()
LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL;
}
}
-
+ display_startup();
+ if (gViewerWindow->getSystemUIScaleFactorChanged())
+ {
+ LLViewerWindow::showSystemUIScaleFactorChanged();
+ }
LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input
}
else
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 2d06b8599c..d28a7cc048 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -230,8 +230,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f);
F32 vec[3] = {
- fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
- fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
+ (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
+ (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
0.f
};
F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f);
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 37cc908e84..36c4f0d516 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1928,6 +1928,12 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis
{
//make a duplicate to keep the original raw image untouched.
raw = raw->duplicate();
+ if (raw->isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL;
+ return false;
+ }
+
raw->scale(w, h) ;
discardlevel += i ;
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index e5aa740a33..24bc55c998 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -37,8 +37,6 @@
#include "llbutton.h"
#include "lldraghandle.h"
#include "llfocusmgr.h"
-#include "llviewertexture.h"
-#include "llfolderview.h"
#include "llfolderviewmodel.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
@@ -71,6 +69,7 @@
#include "llradiogroup.h"
#include "llfloaterreg.h"
#include "lllocalbitmaps.h"
+#include "llerror.h"
static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
@@ -82,118 +81,13 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
//static const char WHITE_IMAGE_NAME[] = "Blank Texture";
//static const char NO_IMAGE_NAME[] = "None";
-//////////////////////////////////////////////////////////////////////////////////////////
-// LLFloaterTexturePicker
-
-class LLFloaterTexturePicker : public LLFloater
-{
-public:
- LLFloaterTexturePicker(
- LLTextureCtrl* owner,
- const std::string& label,
- PermissionMask immediate_filter_perm_mask,
- PermissionMask dnd_filter_perm_mask,
- PermissionMask non_immediate_filter_perm_mask,
- BOOL can_apply_immediately,
- LLUIImagePtr fallback_image_name);
-
- virtual ~LLFloaterTexturePicker();
-
- // LLView overrides
- /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg);
- /*virtual*/ void draw();
- /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
-
- // LLFloater overrides
- /*virtual*/ BOOL postBuild();
- /*virtual*/ void onClose(bool app_settings);
-
- // New functions
- void setImageID( const LLUUID& image_asset_id, bool set_selection = true);
- void updateImageStats();
- const LLUUID& getAssetID() { return mImageAssetID; }
- const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
- void setCanApplyImmediately(BOOL b);
-
- void setActive( BOOL active );
-
- LLTextureCtrl* getOwner() const { return mOwner; }
- void setOwner(LLTextureCtrl* owner) { mOwner = owner; }
-
- void stopUsingPipette();
- PermissionMask getFilterPermMask();
- void updateFilterPermMask();
- void commitIfImmediateSet();
- void commitCancel();
-
- void onFilterEdit(const std::string& search_string );
-
- void setCanApply(bool can_preview, bool can_apply);
- void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;}
-
- static void onBtnSetToDefault( void* userdata );
- static void onBtnSelect( void* userdata );
- static void onBtnCancel( void* userdata );
- void onBtnPipette( );
- //static void onBtnRevert( void* userdata );
- static void onBtnBlank( void* userdata );
- static void onBtnNone( void* userdata );
- static void onBtnClear( void* userdata );
- void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
- static void onShowFolders(LLUICtrl* ctrl, void* userdata);
- static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
- void onTextureSelect( const LLTextureEntry& te );
-
- static void onModeSelect(LLUICtrl* ctrl, void *userdata);
- static void onBtnAdd(void* userdata);
- static void onBtnRemove(void* userdata);
- static void onBtnUpload(void* userdata);
- static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata);
-
-protected:
- LLPointer<LLViewerTexture> mTexturep;
- LLTextureCtrl* mOwner;
-
- LLUUID mImageAssetID; // Currently selected texture
- LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null.
-
- LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory.
- LLUUID mOriginalImageAssetID;
-
- std::string mLabel;
-
- LLTextBox* mTentativeLabel;
- LLTextBox* mResolutionLabel;
-
- std::string mPendingName;
- BOOL mActive;
-
- LLFilterEditor* mFilterEdit;
- LLInventoryPanel* mInventoryPanel;
- PermissionMask mImmediateFilterPermMask;
- PermissionMask mDnDFilterPermMask;
- PermissionMask mNonImmediateFilterPermMask;
- BOOL mCanApplyImmediately;
- BOOL mNoCopyTextureSelected;
- F32 mContextConeOpacity;
- LLSaveFolderState mSavedFolderState;
- BOOL mSelectedItemPinned;
-
- LLRadioGroup* mModeSelector;
- LLScrollListCtrl* mLocalScrollCtrl;
-
-private:
- bool mCanApply;
- bool mCanPreview;
- bool mPreviewSettingChanged;
- texture_selected_callback mTextureSelectedCallback;
-};
-
LLFloaterTexturePicker::LLFloaterTexturePicker(
- LLTextureCtrl* owner,
+ LLView* owner,
+ LLUUID image_asset_id,
+ LLUUID default_image_asset_id,
+ LLUUID blank_image_asset_id,
+ BOOL tentative,
+ BOOL allow_no_texture,
const std::string& label,
PermissionMask immediate_filter_perm_mask,
PermissionMask dnd_filter_perm_mask,
@@ -202,9 +96,13 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
LLUIImagePtr fallback_image)
: LLFloater(LLSD()),
mOwner( owner ),
- mImageAssetID( owner->getImageAssetID() ),
- mFallbackImage( fallback_image ),
- mOriginalImageAssetID(owner->getImageAssetID()),
+ mImageAssetID( image_asset_id ),
+ mOriginalImageAssetID(image_asset_id),
+ mFallbackImage(fallback_image),
+ mDefaultImageAssetID(default_image_asset_id),
+ mBlankImageAssetID(blank_image_asset_id),
+ mTentative(tentative),
+ mAllowNoTexture(allow_no_texture),
mLabel(label),
mTentativeLabel(NULL),
mResolutionLabel(NULL),
@@ -217,7 +115,11 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mSelectedItemPinned( FALSE ),
mCanApply(true),
mCanPreview(true),
- mPreviewSettingChanged(false)
+ mPreviewSettingChanged(false),
+ mOnFloaterCommitCallback(NULL),
+ mOnFloaterCloseCallback(NULL),
+ mSetImageAssetIDCallback(NULL),
+ mOnUpdateImageStatsCallback(NULL)
{
buildFromFile("floater_texture_ctrl.xml");
mCanApplyImmediately = can_apply_immediately;
@@ -294,6 +196,10 @@ void LLFloaterTexturePicker::updateImageStats()
{
std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight());
mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
+ if (mOnUpdateImageStatsCallback)
+ {
+ mOnUpdateImageStatsCallback(mTexturep);
+ }
}
else
{
@@ -400,9 +306,9 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
void LLFloaterTexturePicker::onClose(bool app_quitting)
{
- if (mOwner)
+ if (mOwner && mOnFloaterCloseCallback)
{
- mOwner->onFloaterClose();
+ mOnFloaterCloseCallback();
}
stopUsingPipette();
}
@@ -582,9 +488,9 @@ void LLFloaterTexturePicker::draw()
mTentativeLabel->setVisible( FALSE );
}
- getChildView("Default")->setEnabled(mImageAssetID != mOwner->getDefaultImageAssetID() || mOwner->getTentative());
- getChildView("Blank")->setEnabled(mImageAssetID != mOwner->getBlankImageAssetID() || mOwner->getTentative());
- getChildView("None")->setEnabled(mOwner->getAllowNoTexture() && (!mImageAssetID.isNull() || mOwner->getTentative()));
+ getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
+ getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative);
+ getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
LLFloater::draw();
@@ -629,7 +535,7 @@ void LLFloaterTexturePicker::draw()
}
// Draw Tentative Label over the image
- if( mOwner->getTentative() && !mViewModel->isDirty() )
+ if( mTentative && !mViewModel->isDirty() )
{
mTentativeLabel->setVisible( TRUE );
drawChild(mTentativeLabel);
@@ -704,17 +610,17 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask()
void LLFloaterTexturePicker::commitIfImmediateSet()
{
- if (!mNoCopyTextureSelected && mOwner && mCanApply)
+ if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
{
- mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE);
+ mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, LLUUID::null);
}
}
void LLFloaterTexturePicker::commitCancel()
{
- if (!mNoCopyTextureSelected && mOwner && mCanApply)
+ if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply)
{
- mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
+ mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null);
}
}
@@ -725,7 +631,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
self->setCanApply(true, true);
if (self->mOwner)
{
- self->setImageID( self->mOwner->getDefaultImageAssetID() );
+ self->setImageID( self->getDefaultImageAssetID() );
}
self->commitIfImmediateSet();
}
@@ -735,7 +641,7 @@ void LLFloaterTexturePicker::onBtnBlank(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
self->setCanApply(true, true);
- self->setImageID( self->mOwner->getBlankImageAssetID() );
+ self->setImageID( self->getBlankImageAssetID() );
self->commitIfImmediateSet();
}
@@ -765,9 +671,9 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
self->setImageID( self->mOriginalImageAssetID );
- if (self->mOwner)
+ if (self->mOnFloaterCommitCallback)
{
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null);
}
self->mViewModel->resetDirty();
self->closeFloater();
@@ -777,17 +683,18 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)
void LLFloaterTexturePicker::onBtnSelect(void* userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ LLUUID local_id = LLUUID::null;
if (self->mOwner)
{
- LLUUID local_id = LLUUID::null;
-
if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty())
{
LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();
local_id = LLLocalBitmapMgr::getWorldID(temp_id);
}
-
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT, local_id);
+ }
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_SELECT, local_id);
}
self->closeFloater();
}
@@ -941,11 +848,17 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
{
LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);
LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id);
- self->mOwner->setImageAssetID(inworld_id);
+ if (self->mSetImageAssetIDCallback)
+ {
+ self->mSetImageAssetIDCallback(inworld_id);
+ }
if (self->childGetValue("apply_immediate_check").asBoolean())
{
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, inworld_id);
+ if (self->mOnFloaterCommitCallback)
+ {
+ self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, inworld_id);
+ }
}
}
}
@@ -1028,6 +941,11 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
mInventoryPanel->setFilterSubString(search_string);
}
+void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled)
+{
+ mModeSelector->setIndexEnabled(1,enabled);
+}
+
void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
{
LLUUID inventory_item_id = findItemID(te.getID(), TRUE);
@@ -1238,13 +1156,17 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
{
floaterp = new LLFloaterTexturePicker(
this,
+ getImageAssetID(),
+ getDefaultImageAssetID(),
+ getBlankImageAssetID(),
+ getTentative(),
+ getAllowNoTexture(),
mLabel,
mImmediateFilterPermMask,
mDnDFilterPermMask,
mNonImmediateFilterPermMask,
mCanApplyImmediately,
mFallbackImage);
-
mFloaterHandle = floaterp->getHandle();
LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
@@ -1252,6 +1174,18 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
{
texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback);
}
+ if (texture_floaterp && mOnCloseCallback)
+ {
+ texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this));
+ }
+ if (texture_floaterp)
+ {
+ texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2));
+ }
+ if (texture_floaterp)
+ {
+ texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1));
+ }
LLFloater* root_floater = gFloaterView->getParentFloater(this);
if (root_floater)
@@ -1393,7 +1327,7 @@ void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb)
void LLTextureCtrl::setImageAssetName(const std::string& name)
{
- LLPointer<LLUIImage> imagep = LLUI::getUIImage(name, LLGLTexture::BOOST_PREVIEW);
+ LLPointer<LLUIImage> imagep = LLUI::getUIImage(name);
if(imagep)
{
LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get());
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 15ca7bed92..61f99de5c0 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -29,12 +29,20 @@
#define LL_LLTEXTURECTRL_H
#include "llcoord.h"
+#include "llfiltereditor.h"
#include "llfloater.h"
+#include "llfolderview.h"
+#include "lllocalbitmaps.h"
#include "llstring.h"
#include "lluictrl.h"
#include "llpermissionsflags.h"
+#include "llradiogroup.h"
#include "lltextbox.h" // for params
+#include "llviewerinventory.h"
#include "llviewborder.h" // for params
+#include "llviewerobject.h"
+#include "llviewertexture.h"
+#include "llwindow.h"
class LLButton;
class LLFloaterTexturePicker;
@@ -166,7 +174,7 @@ public:
void closeDependentFloater();
void onFloaterClose();
- void onFloaterCommit(ETexturePickOp op, LLUUID id = LLUUID::null);
+ void onFloaterCommit(ETexturePickOp op, LLUUID id);
// This call is returned when a drag is detected. Your callback
// should return TRUE if the drag is acceptable.
@@ -227,4 +235,140 @@ private:
S32 mLabelWidth;
};
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLFloaterTexturePicker
+typedef boost::function<void(LLTextureCtrl::ETexturePickOp op, LLUUID id)> floater_commit_callback;
+typedef boost::function<void()> floater_close_callback;
+typedef boost::function<void(const LLUUID& asset_id)> set_image_asset_id_callback;
+typedef boost::function<void(LLPointer<LLViewerTexture> texture)> set_on_update_image_stats_callback;
+
+class LLFloaterTexturePicker : public LLFloater
+{
+public:
+ LLFloaterTexturePicker(
+ LLView* owner,
+ LLUUID image_asset_id,
+ LLUUID default_image_asset_id,
+ LLUUID blank_image_asset_id,
+ BOOL tentative,
+ BOOL allow_no_texture,
+ const std::string& label,
+ PermissionMask immediate_filter_perm_mask,
+ PermissionMask dnd_filter_perm_mask,
+ PermissionMask non_immediate_filter_perm_mask,
+ BOOL can_apply_immediately,
+ LLUIImagePtr fallback_image_name
+ );
+
+ virtual ~LLFloaterTexturePicker();
+
+ // LLView overrides
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
+ EAcceptance *accept,
+ std::string& tooltip_msg);
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+
+ // LLFloater overrides
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_settings);
+
+ // New functions
+ void setImageID(const LLUUID& image_asset_id, bool set_selection = true);
+ void updateImageStats();
+ const LLUUID& getAssetID() { return mImageAssetID; }
+ const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
+ void setCanApplyImmediately(BOOL b);
+
+ void setActive(BOOL active);
+
+ LLView* getOwner() const { return mOwner; }
+ void setOwner(LLView* owner) { mOwner = owner; }
+ void stopUsingPipette();
+ PermissionMask getFilterPermMask();
+
+ void updateFilterPermMask();
+ void commitIfImmediateSet();
+ void commitCancel();
+
+ void onFilterEdit(const std::string& search_string);
+
+ void setCanApply(bool can_preview, bool can_apply);
+ void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; }
+ void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; }
+ void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; }
+ void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; }
+ void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; }
+ const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; }
+ const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; }
+
+ static void onBtnSetToDefault(void* userdata);
+ static void onBtnSelect(void* userdata);
+ static void onBtnCancel(void* userdata);
+ void onBtnPipette();
+ //static void onBtnRevert( void* userdata );
+ static void onBtnBlank(void* userdata);
+ static void onBtnNone(void* userdata);
+ static void onBtnClear(void* userdata);
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ static void onShowFolders(LLUICtrl* ctrl, void* userdata);
+ static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
+ void onTextureSelect(const LLTextureEntry& te);
+
+ static void onModeSelect(LLUICtrl* ctrl, void *userdata);
+ static void onBtnAdd(void* userdata);
+ static void onBtnRemove(void* userdata);
+ static void onBtnUpload(void* userdata);
+ static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata);
+
+ void setLocalTextureEnabled(BOOL enabled);
+
+protected:
+ LLPointer<LLViewerTexture> mTexturep;
+ LLView* mOwner;
+
+ LLUUID mImageAssetID; // Currently selected texture
+ LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null.
+ LLUUID mDefaultImageAssetID;
+ LLUUID mBlankImageAssetID;
+ BOOL mTentative;
+ BOOL mAllowNoTexture;
+ LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory.
+ LLUUID mOriginalImageAssetID;
+
+ std::string mLabel;
+
+ LLTextBox* mTentativeLabel;
+ LLTextBox* mResolutionLabel;
+
+ std::string mPendingName;
+ BOOL mActive;
+
+ LLFilterEditor* mFilterEdit;
+ LLInventoryPanel* mInventoryPanel;
+ PermissionMask mImmediateFilterPermMask;
+ PermissionMask mDnDFilterPermMask;
+ PermissionMask mNonImmediateFilterPermMask;
+ BOOL mCanApplyImmediately;
+ BOOL mNoCopyTextureSelected;
+ F32 mContextConeOpacity;
+ LLSaveFolderState mSavedFolderState;
+ BOOL mSelectedItemPinned;
+
+ LLRadioGroup* mModeSelector;
+ LLScrollListCtrl* mLocalScrollCtrl;
+
+private:
+ bool mCanApply;
+ bool mCanPreview;
+ bool mPreviewSettingChanged;
+
+ texture_selected_callback mTextureSelectedCallback;
+ floater_close_callback mOnFloaterCloseCallback;
+ floater_commit_callback mOnFloaterCommitCallback;
+ set_image_asset_id_callback mSetImageAssetIDCallback;
+ set_on_update_image_stats_callback mOnUpdateImageStatsCallback;
+};
+
#endif // LL_LLTEXTURECTRL_H
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index c4696c3a01..caa055e5e0 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -223,6 +223,7 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info)
}
if (!(pick_info.mKeyMask & MASK_ALT) &&
+ !LLFloaterCamera::inFreeCameraMode() &&
gAgentCamera.cameraThirdPerson() &&
gViewerWindow->getLeftMouseDown() &&
!gSavedSettings.getBOOL("FreezeTime") &&
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index b0e3b5bf89..f6eb290bc3 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -267,7 +267,7 @@ bool LLToolMgr::canEdit()
bool LLToolMgr::buildEnabledOrActive()
{
- return inEdit() || canEdit();
+ return LLFloaterReg::instanceVisible("build") || canEdit();
}
void LLToolMgr::toggleBuildMode(const LLSD& sdname)
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index a0ca91672a..375dce485d 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -99,10 +99,16 @@ const std::string &LLVersionInfo::getShortVersion()
namespace
{
+ // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The
+ // macro expands to the string name of the channel, but without quotes. We
+ // need to turn it into a quoted string. This macro trick does that.
+#define stringize_inner(x) #x
+#define stringize_outer(x) stringize_inner(x)
+
/// Storage of the channel name the viewer is using.
// The channel name is set by hardcoded constant,
// or by calling LLVersionInfo::resetChannel()
- std::string sWorkingChannelName(LL_VIEWER_CHANNEL);
+ std::string sWorkingChannelName(stringize_outer(LL_VIEWER_CHANNEL));
// Storage for the "version and channel" string.
// This will get reset too.
diff --git a/indra/newview/llviewchildren.cpp b/indra/newview/llviewchildren.cpp
index 5c5bbdc8f5..32b2f7e9f5 100644
--- a/indra/newview/llviewchildren.cpp
+++ b/indra/newview/llviewchildren.cpp
@@ -79,8 +79,9 @@ void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible)
default:
case BADGE_OK: child->setValue(std::string("badge_ok.j2c")); break;
case BADGE_NOTE: child->setValue(std::string("badge_note.j2c")); break;
- case BADGE_WARN: child->setValue(std::string("badge_warn.j2c")); break;
- case BADGE_ERROR: child->setValue(std::string("badge_error.j2c")); break;
+ case BADGE_WARN:
+ case BADGE_ERROR:
+ child->setValue(std::string("badge_warn.j2c")); break;
}
}
}
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 497ff4d2bf..94f1b09fa9 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -779,12 +779,17 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
if (uploadInfo->showUploadDialog())
LLUploadDialog::modalUploadFinished();
- // Let the Snapshot floater know we have finished uploading a snapshot to inventory.
+ // Let the Snapshot floater know we have finished uploading a snapshot to inventory
LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
- if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot)
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
{
floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
}
+ LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot");
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown())
+ {
+ floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+ }
}
//=========================================================================
@@ -839,10 +844,14 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res
// Let the Snapshot floater know we have failed uploading.
LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
- if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot)
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot && floater_snapshot->isShown())
{
floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
}
-
+ LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot");
+ if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown())
+ {
+ floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
+ }
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 91e4980e45..6d13d28e18 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -93,6 +93,7 @@
#include "llfloaternotificationstabbed.h"
#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
+#include "llfloateroutfitsnapshot.h"
#include "llfloaterpathfindingcharacters.h"
#include "llfloaterpathfindingconsole.h"
#include "llfloaterpathfindinglinksets.h"
@@ -333,7 +334,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
- LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
+ LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>);
+ LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d0813544f8..0bbe9fa2c2 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1007,6 +1007,22 @@ void activate_gesture_cb(const LLUUID& inv_item)
LLGestureMgr::instance().activateGesture(inv_item);
}
+void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type)
+{
+ llassert(item);
+ LLPermissions perm = item->getPermissions();
+ if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type)
+ || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type))
+ {
+ perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type));
+ perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type));
+
+ item->setPermissions(perm);
+
+ item->updateServer(FALSE);
+ }
+}
+
void create_script_cb(const LLUUID& inv_item)
{
if (!inv_item.isNull())
@@ -1014,13 +1030,9 @@ void create_script_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
- LLPermissions perm = item->getPermissions();
- perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts"));
- perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts"));
-
- item->setPermissions(perm);
+ set_default_permissions(item, "Scripts");
- item->updateServer(FALSE);
+ // item was just created, update even if permissions did not changed
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@@ -1036,13 +1048,8 @@ void create_gesture_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
- LLPermissions perm = item->getPermissions();
- perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures"));
- perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures"));
+ set_default_permissions(item, "Gestures");
- item->setPermissions(perm);
-
- item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
@@ -1061,13 +1068,8 @@ void create_notecard_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
- LLPermissions perm = item->getPermissions();
- perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards"));
- perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards"));
-
- item->setPermissions(perm);
+ set_default_permissions(item, "Notecards");
- item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 6ed063e066..78c4d98d55 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1490,7 +1490,7 @@ void LLViewerMedia::createSpareBrowserMediaSource()
// The null owner will keep the browser plugin from fully initializing
// (specifically, it keeps LLPluginClassMedia from negotiating a size change,
// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
- sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0);
+ sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0, 1.0);
}
}
@@ -1762,7 +1762,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
//////////////////////////////////////////////////////////////////////////////////////////
/*static*/
-LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool clean_browser)
+LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser)
{
std::string plugin_basename = LLMIMETypes::implType(media_type);
LLPluginClassMedia* media_source = NULL;
@@ -1779,6 +1779,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
media_source->setOwner(owner);
media_source->setTarget(target);
media_source->setSize(default_width, default_height);
+ media_source->setZoomFactor(zoom_factor);
return media_source;
}
@@ -1827,6 +1828,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
media_source->setSize(default_width, default_height);
media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies);
media_source->setLanguageCode(LLUI::getLanguage());
+ media_source->setZoomFactor(zoom_factor);
// collect 'cookies enabled' setting from prefs and send to embedded browser
bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
@@ -1883,6 +1885,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
// Save the previous media source's last set size before destroying it.
mMediaWidth = mMediaSource->getSetWidth();
mMediaHeight = mMediaSource->getSetHeight();
+ mZoomFactor = mMediaSource->getZoomFactor();
}
// Always delete the old media impl first.
@@ -1905,7 +1908,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
// Save the MIME type that really caused the plugin to load
mCurrentMimeType = mMimeType;
- LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget, mCleanBrowser);
+ LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser);
if (media_source)
{
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 48f0d9dc4d..1fecf15fc9 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -299,7 +299,7 @@ public:
void setTarget(const std::string& target) { mTarget = target; }
// utility function to create a ready-to-use media instance from a desired media type.
- static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool clean_browser = false);
+ static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false);
// Internally set our desired browser user agent string, including
// the Second Life version and skin name. Used because we can
diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp
index c107e8472c..3ccf3070ab 100644
--- a/indra/newview/llviewermedia_streamingaudio.cpp
+++ b/indra/newview/llviewermedia_streamingaudio.cpp
@@ -154,7 +154,8 @@ LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::st
{
LLPluginClassMediaOwner* owner = NULL;
S32 default_size = 1; // audio-only - be minimal, doesn't matter
- LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size);
+ F64 default_zoom = 1.0;
+ LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size, default_zoom);
if (media_source)
{
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index f5b06fbd19..39059fc01e 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -397,13 +397,15 @@ void set_merchant_SLM_menu()
gToolBarView->enableCommand(command->id(), true);
}
-void check_merchant_status()
+void check_merchant_status(bool force)
{
if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth"))
{
- // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
-
+ if (force)
+ {
+ // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status()
+ LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED);
+ }
// Hide SLM related menu item
gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE);
@@ -7906,7 +7908,7 @@ void handle_web_browser_test(const LLSD& param)
void handle_web_content_test(const LLSD& param)
{
std::string url = param.asString();
- LLWeb::loadURLInternal(url);
+ LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true);
}
void handle_show_url(const LLSD& param)
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index b7bdf00157..a553bb79a2 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -83,7 +83,7 @@ BOOL enable_god_full(void* user_data);
BOOL enable_god_liaison(void* user_data);
BOOL enable_god_basic(void* user_data);
void set_underclothes_menu_options();
-void check_merchant_status();
+void check_merchant_status(bool force = false);
void exchange_callingcard(const LLUUID& dest_id);
@@ -108,6 +108,7 @@ void handle_look_at_selection(const LLSD& param);
void handle_zoom_to_object(LLUUID object_id);
void handle_object_return();
void handle_object_delete();
+void handle_object_edit();
void handle_buy_land();
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 4f24dfafac..b48b45502b 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -37,6 +37,7 @@
#include "llfloatermap.h"
#include "llfloatermodelpreview.h"
#include "llfloatersnapshot.h"
+#include "llfloateroutfitsnapshot.h"
#include "llimage.h"
#include "llimagebmp.h"
#include "llimagepng.h"
@@ -508,8 +509,10 @@ class LLFileEnableCloseAllWindows : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
- bool is_floater_snapshot_opened = floater_snapshot && floater_snapshot->isInVisibleChain();
- bool open_children = gFloaterView->allChildrenClosed() && !is_floater_snapshot_opened;
+ LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance();
+ bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain())
+ || (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain());
+ bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;
return !open_children;
}
};
@@ -520,7 +523,12 @@ class LLFileCloseAllWindows : public view_listener_t
{
bool app_quitting = false;
gFloaterView->closeAllChildren(app_quitting);
- LLFloaterSnapshot::getInstance()->closeFloater(app_quitting);
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
+ if (floater_snapshot)
+ floater_snapshot->closeFloater(app_quitting);
+ LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance();
+ if (floater_outfit_snapshot)
+ floater_outfit_snapshot->closeFloater(app_quitting);
if (gMenuHolder) gMenuHolder->hideMenus();
return true;
}
@@ -551,18 +559,18 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
{
gViewerWindow->playSnapshotAnimAndSound();
LLPointer<LLImageFormatted> formatted;
- LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
+ LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
switch (fmt)
{
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
break;
default:
LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
formatted = new LLImagePNG;
break;
- case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
formatted = new LLImageBMP;
break;
}
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 92df3866f7..f472db080f 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1639,7 +1639,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
discard_agent_offer->startFetch();
- if (catp || (itemp && itemp->isFinished()))
+ if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
{
discard_agent_offer->done();
}
@@ -4719,7 +4719,9 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
{
if (!gAudiop)
{
+#if !LL_LINUX
LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+#endif
return;
}
@@ -4781,7 +4783,9 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data)
{
if (!gAudiop)
{
+#if !LL_LINUX
LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+#endif
return;
}
@@ -6601,6 +6605,11 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
if (("ScriptTakeMoney" == script_perm.question) && has_not_only_debit)
continue;
+ if (script_perm.question == "JoinAnExperience")
+ { // Some experience only permissions do not have an explicit permission bit. Add them here.
+ script_question += " " + LLTrans::getString("ForceSitAvatar") + "\n";
+ }
+
script_question += " " + LLTrans::getString(script_perm.question) + "\n";
}
}
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 6666aecca2..2525886222 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -49,6 +49,8 @@ const std::string GRID_UPDATE_SERVICE_URL = "update_query_url_base";
const std::string GRID_HELPER_URI_VALUE = "helper_uri";
/// the splash page url
const std::string GRID_LOGIN_PAGE_VALUE = "login_page";
+/// url for the web profile site
+const std::string GRID_WEB_PROFILE_VALUE = "web_profile_url";
/// internal data on system grids
const std::string GRID_IS_SYSTEM_GRID_VALUE = "system_grid";
/// whether this is single or double names
@@ -70,6 +72,8 @@ const std::string SL_UPDATE_QUERY_URL = "https://update.secondlife.com/update";
const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/";
const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app";
+const std::string MAIN_GRID_WEB_PROFILE_URL = "https://my.secondlife.com/";
+
const char* SYSTEM_GRID_SLURL_BASE = "secondlife://%s/secondlife/";
const char* DEFAULT_SLURL_BASE = "https://%s/region/";
const char* DEFAULT_APP_SLURL_BASE = "x-grid-location-info://%s/app";
@@ -125,6 +129,7 @@ void LLGridManager::initialize(const std::string& grid_file)
"https://secondlife.com/helpers/",
DEFAULT_LOGIN_PAGE,
SL_UPDATE_QUERY_URL,
+ MAIN_GRID_WEB_PROFILE_URL,
"Agni");
addSystemGrid(LLTrans::getString("AditiGridLabel"),
"util.aditi.lindenlab.com",
@@ -132,6 +137,7 @@ void LLGridManager::initialize(const std::string& grid_file)
"http://aditi-secondlife.webdev.lindenlab.com/helpers/",
DEFAULT_LOGIN_PAGE,
SL_UPDATE_QUERY_URL,
+ "https://my.aditi.lindenlab.com/",
"Aditi");
LLSD other_grids;
@@ -288,6 +294,10 @@ bool LLGridManager::addGrid(LLSD& grid_data)
{
grid_data[GRID_HELPER_URI_VALUE] = std::string("https://") + grid + "/helpers/";
}
+ if (!grid_data.has(GRID_WEB_PROFILE_VALUE))
+ {
+ grid_data[GRID_WEB_PROFILE_VALUE] = std::string("https://") + grid + "/";
+ }
if (!grid_data.has(GRID_LOGIN_IDENTIFIER_TYPES))
{
@@ -302,7 +312,8 @@ bool LLGridManager::addGrid(LLSD& grid_data)
<<" id: "<<grid_data[GRID_ID_VALUE].asString()<<"\n"
<<" label: "<<grid_data[GRID_LABEL_VALUE].asString()<<"\n"
<<" login page: "<<grid_data[GRID_LOGIN_PAGE_VALUE].asString()<<"\n"
- <<" helper page: "<<grid_data[GRID_HELPER_URI_VALUE].asString()<<"\n";
+ <<" helper page: "<<grid_data[GRID_HELPER_URI_VALUE].asString()<<"\n"
+ <<" web profile: "<<grid_data[GRID_WEB_PROFILE_VALUE].asString()<<"\n";
/* still in LL_DEBUGS */
for (LLSD::array_const_iterator login_uris = grid_data[GRID_LOGIN_URI_VALUE].beginArray();
login_uris != grid_data[GRID_LOGIN_URI_VALUE].endArray();
@@ -339,6 +350,7 @@ void LLGridManager::addSystemGrid(const std::string& label,
const std::string& helper,
const std::string& login_page,
const std::string& update_url_base,
+ const std::string& web_profile_url,
const std::string& login_id)
{
LLSD grid = LLSD::emptyMap();
@@ -349,6 +361,7 @@ void LLGridManager::addSystemGrid(const std::string& label,
grid[GRID_LOGIN_URI_VALUE].append(login_uri);
grid[GRID_LOGIN_PAGE_VALUE] = login_page;
grid[GRID_UPDATE_SERVICE_URL] = update_url_base;
+ grid[GRID_WEB_PROFILE_VALUE] = web_profile_url;
grid[GRID_IS_SYSTEM_GRID_VALUE] = true;
grid[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray();
grid[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT);
@@ -535,6 +548,21 @@ std::string LLGridManager::getLoginPage()
return login_page;
}
+std::string LLGridManager::getWebProfileURL(const std::string& grid)
+{
+ std::string web_profile_url;
+ std::string grid_name = getGrid(grid);
+ if (!grid_name.empty())
+ {
+ web_profile_url = mGridList[grid_name][GRID_WEB_PROFILE_VALUE].asString();
+ }
+ else
+ {
+ LL_WARNS("GridManager")<<"invalid grid '"<<grid<<"'"<<LL_ENDL;
+ }
+ return web_profile_url;
+}
+
void LLGridManager::getLoginIdentifierTypes(LLSD& idTypes)
{
idTypes = mGridList[mGrid][GRID_LOGIN_IDENTIFIER_TYPES];
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 8526c0ba7f..228303d8e2 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -166,6 +166,13 @@ class LLGridManager : public LLSingleton<LLGridManager>
/// Return the application URL prefix for the selected grid
std::string getAppSLURLBase() { return getAppSLURLBase(mGrid); }
+ /// Return the url of the resident profile web site for the given grid
+ std::string getWebProfileURL(const std::string& grid);
+
+ /// Return the url of the resident profile web site for the selected grid
+ std::string getWebProfileURL() { return getWebProfileURL(mGrid); }
+
+
//@}
/* ================================================================
@@ -216,6 +223,7 @@ class LLGridManager : public LLSingleton<LLGridManager>
const std::string& helper,
const std::string& login_page,
const std::string& update_url_base,
+ const std::string& web_profile_url,
const std::string& login_id = "");
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 5edc3c9745..7964bf1848 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -244,9 +244,10 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mPixelArea(1024.f),
mInventory(NULL),
mInventorySerialNum(0),
- mRegionp( regionp ),
- mInventoryPending(FALSE),
+ mInvRequestState(INVENTORY_REQUEST_STOPPED),
+ mInvRequestXFerId(0),
mInventoryDirty(FALSE),
+ mRegionp(regionp),
mDead(FALSE),
mOrphaned(FALSE),
mUserSelected(FALSE),
@@ -1434,10 +1435,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
setChanged(MOVED | SILHOUETTE);
}
- else if (mText.notNull())
+ else
{
- mText->markDead();
- mText = NULL;
+ if (mText.notNull())
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+ mHudText.clear();
}
std::string media_url;
@@ -1812,10 +1817,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
setChanged(TEXTURE);
}
- else if(mText.notNull())
+ else
{
- mText->markDead();
- mText = NULL;
+ if (mText.notNull())
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+ mHudText.clear();
}
std::string media_url;
@@ -2832,6 +2841,11 @@ void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener)
}
}
+BOOL LLViewerObject::isInventoryPending()
+{
+ return mInvRequestState != INVENTORY_REQUEST_STOPPED;
+}
+
void LLViewerObject::clearInventoryListeners()
{
for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer());
@@ -2870,7 +2884,7 @@ void LLViewerObject::requestInventory()
void LLViewerObject::fetchInventoryFromServer()
{
- if (!mInventoryPending)
+ if (!isInventoryPending())
{
delete mInventory;
LLMessageSystem* msg = gMessageSystem;
@@ -2883,7 +2897,7 @@ void LLViewerObject::fetchInventoryFromServer()
msg->sendReliable(mRegionp->getHost());
// this will get reset by dirtyInventory or doInventoryCallback
- mInventoryPending = TRUE;
+ mInvRequestState = INVENTORY_REQUEST_PENDING;
}
}
@@ -2944,7 +2958,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
std::string unclean_filename;
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
-
+
if(ft->mFilename.empty())
{
LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
@@ -2966,13 +2980,27 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
delete ft;
return;
}
- gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+ U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
ft->mFilename, LL_PATH_CACHE,
object->mRegionp->getHost(),
TRUE,
&LLViewerObject::processTaskInvFile,
(void**)ft,
LLXferManager::HIGH_PRIORITY);
+ if (object->mInvRequestState == INVENTORY_XFER)
+ {
+ if (new_id > 0 && new_id != object->mInvRequestXFerId)
+ {
+ // we started new download.
+ gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
+ object->mInvRequestXFerId = new_id;
+ }
+ }
+ else
+ {
+ object->mInvRequestState = INVENTORY_XFER;
+ object->mInvRequestXFerId = new_id;
+ }
}
void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -3099,7 +3127,10 @@ void LLViewerObject::doInventoryCallback()
mInventoryCallbacks.erase(curiter);
}
}
- mInventoryPending = FALSE;
+
+ // release inventory loading state
+ mInvRequestXFerId = 0;
+ mInvRequestState = INVENTORY_REQUEST_STOPPED;
}
void LLViewerObject::removeInventory(const LLUUID& item_id)
@@ -4990,8 +5021,26 @@ void LLViewerObject::initHudText()
void LLViewerObject::restoreHudText()
{
- if(mText)
+ if (mHudText.empty())
{
+ if (mText)
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+ }
+ else
+ {
+ if (!mText)
+ {
+ initHudText();
+ }
+ else
+ {
+ // Restore default values
+ mText->setZCompare(TRUE);
+ mText->setDoFade(TRUE);
+ }
mText->setColor(mHudTextColor);
mText->setString(mHudText);
}
@@ -6271,7 +6320,7 @@ const LLUUID &LLViewerObject::extractAttachmentItemID()
return getAttachmentItemID();
}
-const std::string& LLViewerObject::getAttachmentItemName()
+const std::string& LLViewerObject::getAttachmentItemName() const
{
static std::string empty;
LLInventoryItem *item = gInventory.getItem(getAttachmentItemID());
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index cb8acfdcf8..1e8f3f4ec2 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -172,7 +172,7 @@ public:
void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; }
virtual BOOL isAttachment() const { return FALSE; }
- const std::string& getAttachmentItemName();
+ const std::string& getAttachmentItemName() const;
virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
virtual BOOL isHUDAttachment() const { return FALSE; }
@@ -437,7 +437,7 @@ public:
// viewer object has the inventory stored locally.
void registerInventoryListener(LLVOInventoryListener* listener, void* user_data);
void removeInventoryListener(LLVOInventoryListener* listener);
- BOOL isInventoryPending() { return mInventoryPending; }
+ BOOL isInventoryPending();
void clearInventoryListeners();
bool hasInventoryListeners();
void requestInventory();
@@ -720,6 +720,7 @@ private:
void deleteTEImages(); // correctly deletes list of images
protected:
+
typedef std::map<char *, LLNameValue *> name_value_map_t;
name_value_map_t mNameValuePairs; // Any name-value pairs stored by script
@@ -756,9 +757,17 @@ protected:
callback_list_t mInventoryCallbacks;
S16 mInventorySerialNum;
+ enum EInventoryRequestState
+ {
+ INVENTORY_REQUEST_STOPPED,
+ INVENTORY_REQUEST_PENDING,
+ INVENTORY_XFER
+ };
+ EInventoryRequestState mInvRequestState;
+ U64 mInvRequestXFerId;
+ BOOL mInventoryDirty;
+
LLViewerRegion *mRegionp; // Region that this object belongs to.
- BOOL mInventoryPending;
- BOOL mInventoryDirty;
BOOL mDead;
BOOL mOrphaned; // This is an orphaned child
BOOL mUserSelected; // Cached user select information
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index ed719ae418..178aa1e646 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1200,7 +1200,7 @@ void LLViewerFetchedTexture::loadFromFastCache()
{
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
- if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+ if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
{
// scale oversized icon, no need to give more work to gl
mRawImage->scale(expected_width, expected_height);
@@ -1981,7 +1981,7 @@ bool LLViewerFetchedTexture::updateFetch()
{
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
- if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+ if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
{
// scale oversized icon, no need to give more work to gl
mRawImage->scale(expected_width, expected_height);
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index 0f73515b5d..88eb13e7cd 100644
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -451,7 +451,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src)
// Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable
// to be the same as the saved values (which were loaded from src at param->cloneParam(this))
- revertValues();
+ revertValuesWithoutUpdate();
}
void LLViewerWearable::setItemID(const LLUUID& item_id)
@@ -471,6 +471,11 @@ void LLViewerWearable::revertValues()
}
}
+void LLViewerWearable::revertValuesWithoutUpdate()
+{
+ LLWearable::revertValues();
+}
+
void LLViewerWearable::saveValues()
{
LLWearable::saveValues();
diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h
index 62cd5e21ad..cc99f6af2f 100644
--- a/indra/newview/llviewerwearable.h
+++ b/indra/newview/llviewerwearable.h
@@ -85,6 +85,8 @@ public:
/*virtual*/ void revertValues();
/*virtual*/ void saveValues();
+ void revertValuesWithoutUpdate();
+
// Something happened that requires the wearable's label to be updated (e.g. worn/unworn).
/*virtual*/void setUpdated() const;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c17c50fd88..9e68bb78e0 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -251,6 +251,11 @@ BOOL gDisplayBadge = FALSE;
static const U8 NO_FACE = 255;
BOOL gQuietSnapshot = FALSE;
+// Minimum value for UIScaleFactor, also defined in preferences, ui_scale_slider
+static const F32 MIN_UI_SCALE = 0.75f;
+// 4.0 in preferences, but win10 supports larger scaling and value is used more as
+// sanity check, so leaving space for larger values from DPI updates.
+static const F32 MAX_UI_SCALE = 7.0f;
static const F32 MIN_DISPLAY_SCALE = 0.75f;
std::string LLViewerWindow::sSnapshotBaseName;
@@ -1593,6 +1598,20 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
return FALSE;
}
+void LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
+{
+ if (ui_scale_factor >= MIN_UI_SCALE && ui_scale_factor <= MAX_UI_SCALE)
+ {
+ gSavedSettings.setF32("UIScaleFactor", ui_scale_factor);
+ LLViewerWindow::reshape(window_width, window_height);
+ mResDirty = true;
+ }
+ else
+ {
+ LL_WARNS() << "DPI change caused UI scale to go out of bounds: " << ui_scale_factor << LL_ENDL;
+ }
+}
+
void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
{
LLAppViewer::instance()->pingMainloopTimeout(msg);
@@ -1655,7 +1674,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)
mResDirty(false),
mStatesDirty(false),
mCurrResolutionIndex(0),
- mProgressView(NULL)
+ mProgressView(NULL),
+ mSystemUIScaleFactorChanged(false)
{
// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
// pass its value right now. Instead, pass it a nullary function that
@@ -1743,9 +1763,24 @@ LLViewerWindow::LLViewerWindow(const Params& p)
gSavedSettings.setS32("FullScreenHeight",scr.mY);
}
+
+ F32 system_scale_factor = mWindow->getSystemUISize();
+ if (system_scale_factor < MIN_UI_SCALE || system_scale_factor > MAX_UI_SCALE)
+ {
+ // reset to default;
+ system_scale_factor = 1.f;
+ }
+ if (p.first_run || gSavedSettings.getF32("LastSystemUIScaleFactor") != system_scale_factor)
+ {
+ mSystemUIScaleFactorChanged = !p.first_run;
+ gSavedSettings.setF32("LastSystemUIScaleFactor", system_scale_factor);
+ gSavedSettings.setF32("UIScaleFactor", system_scale_factor);
+ }
+
+
// Get the real window rect the window was created with (since there are various OS-dependent reasons why
// the size of a window or fullscreen context may have been adjusted slightly...)
- F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+ F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor"), MIN_UI_SCALE, MAX_UI_SCALE);
mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
mDisplayScale *= ui_scale_factor;
@@ -1838,6 +1873,28 @@ LLViewerWindow::LLViewerWindow(const Params& p)
mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
}
+//static
+void LLViewerWindow::showSystemUIScaleFactorChanged()
+{
+ LLNotificationsUtil::add("SystemUIScaleFactorChanged", LLSD(), LLSD(), onSystemUIScaleFactorChanged);
+}
+
+//static
+bool LLViewerWindow::onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if(option == 0)
+ {
+ LLFloaterReg::toggleInstanceOrBringToFront("preferences");
+ LLFloater* pref_floater = LLFloaterReg::getInstance("preferences");
+ LLTabContainer* tab_container = pref_floater->getChild<LLTabContainer>("pref core");
+ tab_container->selectTabByName("advanced1");
+
+ }
+ return false;
+}
+
+
void LLViewerWindow::initGLDefaults()
{
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -4364,7 +4421,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
}
}
-BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)
{
LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL;
@@ -4403,7 +4460,7 @@ void LLViewerWindow::playSnapshotAnimAndSound()
send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
}
-BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type)
{
return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
}
@@ -4412,7 +4469,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy
// the results over to the final raw image.
BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height,
- BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
+ BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)
{
if (!raw)
{
@@ -4620,7 +4677,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
}
- if (type == SNAPSHOT_TYPE_COLOR)
+ if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR)
{
glReadPixels(
subimage_x_offset, out_y + subimage_y_offset,
@@ -4629,7 +4686,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
raw->getData() + output_buffer_offset
);
}
- else // SNAPSHOT_TYPE_DEPTH
+ else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH
{
LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
glReadPixels(
@@ -5211,7 +5268,7 @@ F32 LLViewerWindow::getWorldViewAspectRatio() const
void LLViewerWindow::calcDisplayScale()
{
- F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+ F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor"), MIN_UI_SCALE, MAX_UI_SCALE);
LLVector2 display_scale;
display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
display_scale *= ui_scale_factor;
@@ -5224,7 +5281,7 @@ void LLViewerWindow::calcDisplayScale()
if (display_scale != mDisplayScale)
{
- LL_INFOS() << "Setting display scale to " << display_scale << LL_ENDL;
+ LL_INFOS() << "Setting display scale to " << display_scale << " for ui scale: " << ui_scale_factor << LL_ENDL;
mDisplayScale = display_scale;
// Init default fonts
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index ad06f00234..72b7370621 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -46,6 +46,7 @@
#include "llhandle.h"
#include "llinitparam.h"
#include "lltrace.h"
+#include "llsnapshotmodel.h"
#include <boost/function.hpp>
#include <boost/signals2.hpp>
@@ -155,7 +156,8 @@ public:
min_width,
min_height;
Optional<bool> fullscreen,
- ignore_pixel_depth;
+ ignore_pixel_depth,
+ first_run;
Params();
};
@@ -209,6 +211,7 @@ public:
/*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data);
/*virtual*/ BOOL handleTimerEvent(LLWindow *window);
/*virtual*/ BOOL handleDeviceChange(LLWindow *window);
+ /*virtual*/ void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
/*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg);
/*virtual*/ void handlePauseWatchdog(LLWindow *window);
@@ -342,15 +345,11 @@ public:
// snapshot functionality.
// perhaps some of this should move to llfloatershapshot? -MG
- typedef enum
- {
- SNAPSHOT_TYPE_COLOR,
- SNAPSHOT_TYPE_DEPTH
- } ESnapshotType;
- BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
+
+ BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR);
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
- BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE );
- BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;
+ BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE);
+ BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }
void resetSnapshotLoc() const { sSnapshotDir.clear(); }
BOOL saveImageNumbered(LLImageFormatted *image, bool force_picker = false);
@@ -418,6 +417,9 @@ public:
void calcDisplayScale();
static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale);
+ bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; }
+ static void showSystemUIScaleFactorChanged();
+
private:
bool shouldShowToolTipFor(LLMouseHandler *mh);
@@ -431,6 +433,7 @@ private:
S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter
LLRect getChatConsoleRect(); // Get optimal cosole rect.
+ static bool onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response);
private:
LLWindow* mWindow; // graphical window object
bool mActive;
@@ -509,6 +512,7 @@ private:
LLPointer<LLViewerObject> mDragHoveredObject;
static LLTrace::SampleStatHandle<> sMouseVelocityStat;
+ bool mSystemUIScaleFactorChanged; // system UI scale factor changed from last run
};
//
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
index 1fe5fc9800..97b405c1d0 100644
--- a/indra/newview/llviewerwindowlistener.cpp
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -65,9 +65,9 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow):
void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
{
- typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap;
+ typedef std::map<LLSD::String, LLSnapshotModel::ESnapshotLayerType> TypeMap;
TypeMap types;
-#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name
+#define tp(name) types[#name] = LLSnapshotModel::SNAPSHOT_TYPE_##name
tp(COLOR);
tp(DEPTH);
#undef tp
@@ -84,7 +84,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
if (event.has("showui"))
showui = event["showui"].asBoolean();
bool rebuild(event["rebuild"]); // defaults to false
- LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR);
+ LLSnapshotModel::ESnapshotLayerType type(LLSnapshotModel::SNAPSHOT_TYPE_COLOR);
if (event.has("type"))
{
TypeMap::const_iterator found = types.find(event["type"]);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index cdc7e20c2c..1425b3d42e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -186,6 +186,7 @@ const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f;
const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f;
const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0;
+const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024;
enum ERenderName
{
@@ -7391,16 +7392,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
// No backsies zone - if we get here, the message should be valid and usable, will be processed.
LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL;
- if (isSelf())
- {
- // Note:
- // locally the COF is maintained via LLInventoryModel::accountForUpdate
- // which is called from various places. This should match the simhost's
- // idea of what the COF version is. AIS however maintains its own version
- // of the COF that should be considered canonical.
- mLastUpdateReceivedCOFVersion = thisAppearanceVersion;
- }
-
+ // Note:
+ // locally the COF is maintained via LLInventoryModel::accountForUpdate
+ // which is called from various places. This should match the simhost's
+ // idea of what the COF version is. AIS however maintains its own version
+ // of the COF that should be considered canonical.
+ mLastUpdateReceivedCOFVersion = thisAppearanceVersion;
+
if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE))
{
updateVisualComplexity();
@@ -8356,6 +8354,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
{
U32 cost = VISUAL_COMPLEXITY_UNKNOWN;
LLVOVolume::texture_cost_t textures;
+ hud_complexity_list_t hud_complexity_list;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
@@ -8432,6 +8431,63 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
}
}
}
+ if (isSelf()
+ && attached_object
+ && attached_object->isHUDAttachment()
+ && !attached_object->isTempAttachment()
+ && attached_object->mDrawable)
+ {
+ textures.clear();
+
+ const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
+ if (volume)
+ {
+ LLHUDComplexity hud_object_complexity;
+ hud_object_complexity.objectName = attached_object->getAttachmentItemName();
+ hud_object_complexity.objectId = attached_object->getAttachmentItemID();
+ std::string joint_name;
+ gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name);
+ hud_object_complexity.jointName = joint_name;
+ // get cost and individual textures
+ hud_object_complexity.objectsCost += volume->getRenderCost(textures);
+ hud_object_complexity.objectsCount++;
+
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
+ if (chld_volume)
+ {
+ // get cost and individual textures
+ hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures);
+ hud_object_complexity.objectsCount++;
+ }
+ }
+
+ hud_object_complexity.texturesCount += textures.size();
+
+ for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
+ volume_texture != textures.end();
+ ++volume_texture)
+ {
+ // add the cost of each individual texture (ignores duplicates)
+ hud_object_complexity.texturesCost += volume_texture->second;
+ LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first);
+ if (tex)
+ {
+ // Note: Texture memory might be incorect since texture might be still loading.
+ hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory();
+ if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE)
+ {
+ hud_object_complexity.largeTexturesCount++;
+ }
+ }
+ }
+ hud_complexity_list.push_back(hud_object_complexity);
+ }
+ }
}
}
@@ -8493,11 +8549,15 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
- if (isSelf() && show_my_complexity_changes)
- {
- LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
- }
- }
+ if (isSelf() && show_my_complexity_changes)
+ {
+ // Avatar complexity
+ LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
+
+ // HUD complexity
+ LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
+ }
+ }
}
void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set)
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 4dab213fa0..6b4a450e6f 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -283,7 +283,7 @@ void LLSkyTex::create(const F32 brightness)
S32 offset = basic_offset * sComponents;
U32* pix = (U32*)(data + offset);
LLColor4U temp = LLColor4U(mSkyData[basic_offset]);
- *pix = temp.mAll;
+ *pix = temp.asRGBA();
}
}
createGLImage(sCurrent);
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index ee8e91fb71..9cfb9773bd 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -171,7 +171,7 @@ protected:
{
S32 offset = (i * sResolution + j) * sComponents;
U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
- *pix = col.mAll;
+ *pix = col.asRGBA();
}
LLColor4U getPixel(const S32 i, const S32 j)
@@ -179,7 +179,7 @@ protected:
LLColor4U col;
S32 offset = (i * sResolution + j) * sComponents;
U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
- col.mAll = *pix;
+ col.fromRGBA( *pix );
return col;
}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e69a8d1d1d..8c026bae21 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4429,7 +4429,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE);
if (type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT))
{
- LL_WARNS("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
+ LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
}
if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects)
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index b37e41fb85..8026dc3ea8 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -104,10 +104,10 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std
// static
// Explicitly open a Web URL using the Web content floater
-void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
+void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode)
{
LLFloaterWebContent::Params p;
- p.url(url).target(target).id(uuid);
+ p.url(url).target(target).id(uuid).dev_mode(dev_mode);
LLFloaterReg::showInstance("web_content", p);
}
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 7c90badbfe..7149ce9baf 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -57,7 +57,7 @@ public:
static void loadURL(const std::string& url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);
// load content using built-in browser
- static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null);
+ static void loadURLInternal(const std::string &url, const std::string& target = LLStringUtil::null, const std::string& uuid = LLStringUtil::null, bool dev_mode = false);
/// Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 11d3706821..cee47a591e 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -957,10 +957,10 @@ void LLWorld::updateWaterObjects()
center_y = min_y + (wy >> 1);
S32 add_boundary[4] = {
- 512 - (max_x - region_x),
- 512 - (max_y - region_y),
- 512 - (region_x - min_x),
- 512 - (region_y - min_y) };
+ (S32)(512 - (max_x - region_x)),
+ (S32)(512 - (max_y - region_y)),
+ (S32)(512 - (region_x - min_x)),
+ (S32)(512 - (region_y - min_y)) };
S32 dir;
for (dir = 0; dir < 8; dir++)
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
index 97a9eb7f5f..cc3645131d 100644
--- a/indra/newview/llxmlrpclistener.cpp
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -322,7 +322,7 @@ public:
mBoundListener =
LLEventPumps::instance().
obtain("mainloop").
- listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1));
+ listen(LLEventPump::ANONYMOUS, boost::bind(&Poller::poll, this, _1));
LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL;
}
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 8533625e50..e0da7f5d9e 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -948,4 +948,13 @@
<color
name="SyntaxLslStringLiteral"
value="1 0.14 0 1" />
+ <color
+ name="OutfitGalleryItemSelected"
+ value="0.22 0.45 0.35 1" />
+ <color
+ name="OutfitGalleryItemWorn"
+ value="0.33 0.58 0.47 1" />
+ <color
+ name="OutfitGalleryItemUnselected"
+ value="0.4 0.4 0.4 1" />
</colors>
diff --git a/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png
new file mode 100644
index 0000000000..bacddcbb68
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Default_Outfit_Photo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Video_URL_Off.png b/indra/newview/skins/default/textures/icons/Video_URL_Off.png
new file mode 100644
index 0000000000..40e5df7d81
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Video_URL_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 72037a84b3..f2da22256c 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -676,7 +676,10 @@ with the same filename but different name
<texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" />
<texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" />
- <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
+
+ <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" />
+
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
<texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
@@ -774,6 +777,9 @@ with the same filename but different name
<texture name="default_land_picture.j2c" />
<texture name="default_profile_picture.j2c" />
<texture name="locked_image.j2c" />
+ <texture name="badge_note.j2c" />
+ <texture name="badge_warn.j2c" />
+ <texture name="badge_ok.j2c" />
<texture name="materials_ui_x_24.png" />
<texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" />
@@ -806,6 +812,7 @@ with the same filename but different name
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+ <texture name="Default_Outfit_Photo" file_name="icons/Default_Outfit_Photo.png" preload="true"/>
<texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/>
<texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/>
<texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/>
diff --git a/indra/newview/skins/default/textures/windows/first_login_image_left.png b/indra/newview/skins/default/textures/windows/first_login_image_left.png
index b405a88245..1fa10fde53 100644
--- a/indra/newview/skins/default/textures/windows/first_login_image_left.png
+++ b/indra/newview/skins/default/textures/windows/first_login_image_left.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/first_login_image_right.png b/indra/newview/skins/default/textures/windows/first_login_image_right.png
index 22a6dd8a53..d764d846b7 100644
--- a/indra/newview/skins/default/textures/windows/first_login_image_right.png
+++ b/indra/newview/skins/default/textures/windows/first_login_image_right.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml
index d3d85de3c3..b0cb1e0592 100644
--- a/indra/newview/skins/default/xui/de/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">[AMT] L$</panel.string>
- <panel left="-415" name="balance_bg" width="205">
+ <panel left="-436" name="balance_bg" width="205">
<text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="L$ ??"/>
<button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/>
<button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/>
diff --git a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml
new file mode 100644
index 0000000000..15c480f144
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ positioning="cascading"
+ legacy_header_height="18"
+ can_minimize="true"
+ can_resize="false"
+ can_close="true"
+ height="455"
+ layout="topleft"
+ name="outfit_snapshot"
+ single_instance="true"
+ help_topic="snapshot"
+ save_rect="true"
+ save_visibility="false"
+ title="OUTFIT SNAPSHOT"
+ width="624"
+ min_height="455">
+ <floater.string
+ name="unknown">
+ unknown
+ </floater.string>
+ <string
+ name="inventory_progress_str">
+ Saving to Inventory
+ </string>
+ <string
+ name="inventory_succeeded_str">
+ Saved to Inventory!
+ </string>
+ <string
+ name="inventory_failed_str">
+ Failed to save to inventory.
+ </string>
+ <button
+ follows="left|top"
+ height="25"
+ image_overlay="Refresh_Off"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ image_overlay_alignment="left"
+ imgoverlay_label_space="5"
+ pad_bottom="0"
+ halign="left"
+ layout="topleft"
+ left="10"
+ label="REFRESH"
+ name="new_snapshot_btn"
+ top_pad="26"
+ width="167" />
+ <button
+ follows="left|top"
+ control_name="AdvanceOutfitSnapshot"
+ invisibility_control="AdvanceOutfitSnapshot"
+ height="25"
+ is_toggle="true"
+ layout="topleft"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_selected="Toolbar_Middle_Off"
+ image_unselected="Toolbar_Middle_Off"
+ image_overlay="Conv_toolbar_expand"
+ name="retract_btn"
+ left_pad="1"
+ top_delta="0"
+ width="31" />
+ <button
+ follows="left|top"
+ control_name="AdvanceOutfitSnapshot"
+ visibility_control="AdvanceOutfitSnapshot"
+ height="25"
+ is_toggle="true"
+ layout="topleft"
+ image_overlay="Conv_toolbar_collapse"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_selected="Toolbar_Middle_Off"
+ image_unselected="Toolbar_Middle_Off"
+ name="extend_btn"
+ left_delta="0"
+ top_delta="0"
+ width="31" />
+ <panel
+ height="154"
+ layout="topleft"
+ follows="top|left"
+ left="0"
+ name="advanced_options_panel"
+ top_pad="-6"
+ width="210">
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="10"
+ layout="topleft"
+ name="advanced_options_hr"
+ right="-1"
+ top_pad="5"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="layer_type_label"
+ top_pad="10"
+ width="100">
+ Capture:
+ </text>
+ <check_box
+ label="Interface"
+ layout="topleft"
+ left="30"
+ height="16"
+ top_pad="8"
+ width="180"
+ name="ui_check" />
+ <check_box
+ label="HUDs"
+ layout="topleft"
+ height="16"
+ left="30"
+ top_pad="1"
+ width="180"
+ name="hud_check" />
+ <check_box
+ label="Freeze frame (fullscreen)"
+ layout="topleft"
+ height="16"
+ left="10"
+ top_pad="1"
+ width="180"
+ name="freeze_frame_check" />
+ <check_box
+ label="Auto-refresh"
+ layout="topleft"
+ height="16"
+ left="10"
+ top_pad="1"
+ width="180"
+ name="auto_snapshot_check" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="filter_list_label"
+ top_pad="10"
+ width="50">
+ Filter:
+ </text>
+ <combo_box
+ control_name="PhotoFilters"
+ follows="left|right|top"
+ name="filters_combobox"
+ tool_tip="Image filters"
+ top_delta="-3"
+ left="50"
+ right="-1"
+ height="21"
+ width="135">
+ <combo_box.item
+ label="No Filter"
+ name="NoFilter"
+ value="NoFilter" />
+ </combo_box>
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="10"
+ layout="topleft"
+ name="advanced_options_hr"
+ right="-1"
+ top_pad="7"
+ />
+ </panel>
+ <panel
+ class="llpaneloutfitsnapshotinventory"
+ follows="left|top"
+ height="230"
+ layout="topleft"
+ left="0"
+ name="panel_outfit_snapshot_inventory"
+ filename="panel_outfit_snapshot_inventory.xml"
+ top_pad="10"
+ width="215"
+ />
+ <view_border
+ bevel_style="in"
+ follows="left|top"
+ height="1"
+ left="10"
+ layout="topleft"
+ name="status_hr"
+ width="199"
+ top_pad="-16"/>
+ <panel
+ background_visible="false"
+ follows="left|top"
+ font="SansSerifLarge"
+ halign="center"
+ height="20"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="succeeded_panel"
+ width="198"
+ top_pad="1"
+ type="string"
+ visible="false">
+ <text
+ follows="all"
+ font="SansSerif"
+ halign="center"
+ height="18"
+ layout="topleft"
+ left="1"
+ length="1"
+ name="succeeded_lbl"
+ right="-1"
+ text_color="0.2 0.85 0.2 1"
+ top="4"
+ translate="false"
+ type="string">
+ Succeeded
+ </text>
+ </panel>
+ <panel
+ background_visible="false"
+ follows="left|top"
+ font="SansSerifLarge"
+ halign="center"
+ height="20"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="failed_panel"
+ width="198"
+ top_delta="0"
+ type="string"
+ visible="false">
+ <text
+ follows="all"
+ font="SansSerif"
+ halign="center"
+ height="18"
+ layout="topleft"
+ left="1"
+ length="1"
+ name="failed_lbl"
+ right="-1"
+ text_color="0.95 0.4 0.4 1"
+ top="4"
+ translate="false"
+ type="string">
+ Failed
+ </text>
+ </panel>
+ <loading_indicator
+ follows="left|top"
+ height="24"
+ layout="topleft"
+ name="working_indicator"
+ left="10"
+ top_delta="0"
+ visible="false"
+ width="24" />
+ <text
+ follows="left|top"
+ font="SansSerifBold"
+ height="14"
+ layout="topleft"
+ left_pad="3"
+ length="1"
+ halign="left"
+ name="working_lbl"
+ top_delta="5"
+ translate="false"
+ type="string"
+ visible="false"
+ width="162">
+ Working
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifBold"
+ halign="left"
+ height="18"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="refresh_lbl"
+ text_color="0.95 0.4 0.4 1"
+ top_delta="0"
+ translate="false"
+ type="string"
+ visible="false"
+ width="130">
+ Refresh to save.
+ </text>
+ <ui_ctrl
+ layout="topleft"
+ name="thumbnail_placeholder"
+ top="23"
+ left="215"
+ width="400"
+ height="400"
+ follows="top|left"/>
+ <view_border
+ bevel_style="in"
+ height="21"
+ layout="topleft"
+ name="img_info_border"
+ top_pad="0"
+ right="-10"
+ follows="left|top|right"
+ left_delta="0"/>
+ <text
+ type="string"
+ font="SansSerifSmall"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="220"
+ right="-20"
+ halign="left"
+ name="image_res_text"
+ top_delta="5"
+ width="200">
+ [WIDTH]px (width) x [HEIGHT]px (height)
+ </text>
+ <text
+ follows="right|top"
+ font="SansSerifSmall"
+ height="14"
+ layout="topleft"
+ left="-65"
+ length="1"
+ halign="right"
+ name="file_size_label"
+ top_delta="0"
+ type="string"
+ width="50">
+ [SIZE] KB
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 2bd3aa8bcc..c6b91a8b2f 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -117,7 +117,7 @@
<slider
control_name="IndirectMaxComplexity"
- tool_tip="Controls at what point a visually complex avatar is drawn as a jelly doll"
+ tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
follows="left|top"
height="16"
initial_value="101"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index af62c7a9bc..225266af86 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -21,14 +21,6 @@
name="screenshot"
top="15"
width="220" />
- <check_box
- height="15"
- label="Use this screenshot"
- layout="topleft"
- left="8"
- name="screen_check"
- top_pad="-12"
- width="116" />
<text
type="string"
length="1"
@@ -39,7 +31,7 @@
layout="topleft"
left="10"
name="reporter_title"
- top_pad="0"
+ top_pad="-2"
width="100">
Reporter:
</text>
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
index a80440e844..4473ce0cda 100644
--- a/indra/newview/skins/default/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -154,6 +154,136 @@
</button>
</layout_panel>
<layout_panel
+ height="22"
+ layout="topleft"
+ left_delta="0"
+ name="debug_controls"
+ top_delta="0"
+ auto_resize="false"
+ width="585">
+ <button
+ image_overlay="Home_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Web tests home page"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="1"
+ name="web_test_home_page"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ </button>
+
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MPEG4 Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="27"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MKV Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="WebM Video Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="75"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="MP3 audio Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="99"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/>
+ </button>
+ <button
+ image_overlay="Video_URL_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="FLV Test"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="123"
+ name="VLC Plugin Test"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.TestURL"
+ parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/>
+ </button>
+ </layout_panel>
+ <layout_panel
height="40"
layout="topleft"
left_delta="0"
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index 5d05ecf127..550af03683 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -10,6 +10,7 @@
<file>ArialUni.ttf</file>
</os>
<os name="Mac">
+ <file>ヒラギノ角ゴシック W3.ttc</file>
<file>ヒラギノ角ゴ Pro W3.otf</file>
<file>ヒラギノ角ゴ ProN W3.otf</file>
<file>ヒラギノ明朝 ProN W3.ttc</file>
diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml
index 324ff3eabd..a69585074c 100644
--- a/indra/newview/skins/default/xui/en/inspect_group.xml
+++ b/indra/newview/skins/default/xui/en/inspect_group.xml
@@ -66,7 +66,7 @@ Fear the moose! Fear it! And the mongoose too!
width="220">
L$123 to join
</text>
- <icon
+ <group_icon
follows="all"
height="38"
right="-10"
diff --git a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
new file mode 100755
index 0000000000..1b08767edc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Outfit">
+ <menu_item_call
+ label="Wear - Replace Current Outfit"
+ layout="topleft"
+ name="wear_replace">
+ <on_click
+ function="Outfit.WearReplace" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="wear_replace" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="wear_replace" />
+ </menu_item_call>
+ <menu_item_call
+ label="Wear - Add to Current Outfit"
+ layout="topleft"
+ name="wear_add">
+ <on_click
+ function="Outfit.WearAdd" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="wear_add" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="wear_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take Off - Remove from Current Outfit"
+ layout="topleft"
+ name="take_off">
+ <on_click
+ function="Outfit.TakeOff" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="take_off" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="take_off" />
+ </menu_item_call>
+ <menu_item_call
+ label="Upload Photo (L$10)"
+ layout="topleft"
+ name="upload_photo">
+ <on_click
+ function="Outfit.UploadPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select Photo"
+ layout="topleft"
+ name="select_photo">
+ <on_click
+ function="Outfit.SelectPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take a Snapshot"
+ layout="topleft"
+ name="take_snapshot">
+ <on_click
+ function="Outfit.TakeSnapshot" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Photo"
+ layout="topleft"
+ name="remove_photo">
+ <on_click
+ function="Outfit.RemovePhoto" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="remove_photo" />
+ </menu_item_call>
+ <menu_item_separator name="sepatator1" />
+ <menu
+ height="175"
+ label="New Clothes"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Clothes"
+ top_pad="514"
+ width="125">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha"
+ layout="topleft"
+ name="New Alpha">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="physics" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="85"
+ label="New Body Parts"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Body Parts"
+ top_pad="514"
+ width="118">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Outfit.Create"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator name="sepatator2" />
+ <menu_item_call
+ label="Edit Outfit"
+ layout="topleft"
+ name="edit">
+ <on_click
+ function="Outfit.Edit" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rename Outfit"
+ layout="topleft"
+ name="rename">
+ <on_click
+ function="Outfit.Rename" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete Outfit"
+ layout="topleft"
+ name="delete">
+ <on_click
+ function="Outfit.Delete" />
+ <on_visible
+ function="Outfit.OnVisible"
+ parameter="delete" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index dcf2da52f1..a39ee5fddd 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -225,11 +225,11 @@
parameter="message_critical" />
</menu_item_call>
<menu_item_call
- label="Web Content Floater Debug Test"
- name="Web Content Floater Debug Test">
+ label="Media Browser"
+ name="Media Browser">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ parameter="http://google.com"/>
</menu_item_call>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 3b8ace6308..7faa4f3d71 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -39,8 +39,35 @@
function="Gear.OnVisible"
parameter="take_off" />
</menu_item_call>
-
- <menu_item_separator name="sepatator1" />
+ <menu_item_call
+ label="Upload Photo (L$10)"
+ layout="topleft"
+ name="upload_photo">
+ <on_click
+ function="Gear.UploadPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select Photo"
+ layout="topleft"
+ name="select_photo">
+ <on_click
+ function="Gear.SelectPhoto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take a Snapshot"
+ layout="topleft"
+ name="take_snapshot">
+ <on_click
+ function="Gear.TakeSnapshot" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Photo"
+ layout="topleft"
+ name="remove_photo">
+ <on_click
+ function="Gear.RemovePhoto" />
+ </menu_item_call>
+ <menu_item_separator name="sepatator1" />
<!-- copied (with minor modifications) from menu_inventory_add.xml -->
<!-- *TODO: generate dynamically? -->
<menu
@@ -234,4 +261,15 @@
function="Gear.OnVisible"
parameter="delete" />
</menu_item_call>
+ <menu_item_separator name="sepatator3" />
+ <menu_item_check
+ label="Sort Folders Always by Name"
+ layout="topleft"
+ name="sort_folders_by_name">
+ <on_click
+ function="Gear.SortByName" />
+ <on_check
+ function="CheckControl"
+ parameter="OutfitGallerySortByName" />
+ </menu_item_check>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b189d1038f..8a649a57d1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3141,30 +3141,13 @@
label="UI"
name="UI"
tear_off="true">
- <!-- <menu_item_check
- label="New Bottom Bar"
- name="New Bottom Bar">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="BottomPanelNew" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="BottomPanelNew" />
- </menu_item_check>-->
- <menu_item_call
- label="Media Browser Test"
- name="Web Browser Test">
- <menu_item_call.on_click
- function="Advanced.WebBrowserTest"
- parameter="http://secondlife.com/app/search/slurls.html"/>
- </menu_item_call>
<menu_item_call
- label="Web Content Browser"
- name="Web Content Browser"
- shortcut="control|shift|Z">
+ label="Media Browser"
+ name="Media Browser"
+ shortcut="control|alt|shift|Z">
<menu_item_call.on_click
function="Advanced.WebContentTest"
- parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/>
+ parameter="http://google.com"/>
</menu_item_call>
<menu_item_call
label="FB Connect Test"
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
index 44b2727671..75c1de24aa 100644
--- a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
@@ -28,6 +28,13 @@
function="Wearing.Edit" />
</menu_item_call>
<menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit_item">
+ <on_click
+ function="Wearing.EditItem" />
+ </menu_item_call>
+ <menu_item_call
label="Show Original"
layout="topleft"
name="show_original">
diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml
index 7cb4a6e53b..8d8d546b24 100644
--- a/indra/newview/skins/default/xui/en/mime_types.xml
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -130,10 +130,21 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</scheme>
- <mimetype name="blank">
+ <scheme name="libvlc">
+ <label name="libvlc_label">
+ LibVLC supported media
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_libvlc
+ </impl>
+ </scheme>
+ <mimetype name="blank">
<label name="blank_label">
- None -
</label>
@@ -163,7 +174,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/*">
@@ -174,7 +185,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="image/*">
@@ -196,7 +207,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/javascript">
@@ -218,7 +229,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="application/pdf">
@@ -295,7 +306,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@@ -306,7 +317,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@@ -317,7 +328,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@@ -328,7 +339,7 @@
audio
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@@ -438,7 +449,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/mp4">
@@ -449,10 +460,21 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
- <mimetype menu="1" name="video/quicktime">
+ <mimetype name="application/octet-stream">
+ <label name="video/octet-stream">
+ Movie
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_libvlc
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/quicktime">
<label name="video/quicktime_label">
Movie (QuickTime)
</label>
@@ -460,7 +482,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@@ -471,7 +493,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@@ -482,7 +504,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +515,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
+ media_plugin_cef
</impl>
</mimetype>
</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml
index 84aeaf3b54..7188b1e699 100644
--- a/indra/newview/skins/default/xui/en/mime_types_linux.xml
+++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml
@@ -130,7 +130,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</scheme>
<mimetype name="blank">
@@ -163,7 +163,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/*">
@@ -174,7 +174,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="image/*">
@@ -196,7 +196,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/javascript">
@@ -218,7 +218,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="application/pdf">
@@ -295,7 +295,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/mpeg">
@@ -306,7 +306,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-aiff">
@@ -317,7 +317,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="audio/x-wav">
@@ -328,7 +328,7 @@
audio
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="image/bmp">
@@ -438,7 +438,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/mp4">
@@ -449,7 +449,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="video/quicktime">
@@ -460,7 +460,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-asf">
@@ -471,7 +471,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
@@ -482,7 +482,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +493,7 @@
movie
</widgettype>
<impl>
- media_plugin_gstreamer
+ media_plugin_libvlc
</impl>
</mimetype>
</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index dfde38bc5f..804235518e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -832,6 +832,13 @@ If you no longer wish to have these abilities granted to this role, disable them
</notification>
<notification
+ icon="notify.tga"
+ name="GroupBanUserOnBanlist"
+ type="notify">
+Some residents have not been sent an invite due to being banned from the group.
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="AttachmentDrop"
type="alertmodal">
@@ -1476,6 +1483,7 @@ Save Changes?
icon="alertmodal.tga"
name="DeleteNotecard"
type="alertmodal">
+ <unique/>
Delete Notecard?
<tag>confirm</tag>
<usetemplate
@@ -1631,52 +1639,14 @@ Visit [_URL] for more information?
<notification
icon="alertmodal.tga"
- name="IntelOldDriver"
+ name="OldGPUDriver"
type="alertmodal">
There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
- Visit [_URL] to check for driver updates?
- <tag>confirm</tag>
- <url option="0" name="url">
- http://www.intel.com/p/en_US/support/detect/graphics
- </url>
- <usetemplate
- ignoretext="My graphics driver is out of date"
- name="okcancelignore"
- notext="No"
- yestext="Yes"/>
- <tag>fail</tag>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="AMDOldDriver"
- type="alertmodal">
- There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
-
- Visit [_URL] to check for driver updates?
- <tag>confirm</tag>
- <url option="0" name="url">
- http://support.amd.com/us/Pages/AMDSupportHub.aspx
- </url>
- <usetemplate
- ignoretext="My graphics driver is out of date"
- name="okcancelignore"
- notext="No"
- yestext="Yes"/>
- <tag>fail</tag>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="NVIDIAOldDriver"
- type="alertmodal">
- There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
-
- Visit [_URL] to check for driver updates?
+ Visit [URL] to check for driver updates?
<tag>confirm</tag>
<url option="0" name="url">
- http://www.nvidia.com/Download/index.aspx?lang=en-us
+ [URL]
</url>
<usetemplate
ignoretext="My graphics driver is out of date"
@@ -1686,7 +1656,6 @@ Visit [_URL] for more information?
<tag>fail</tag>
</notification>
-
<notification
icon="alertmodal.tga"
name="UnknownGPU"
@@ -3349,6 +3318,23 @@ Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Renderin
<context>AgentComplexityNotice</context>
</unique>
Your [https://community.secondlife.com/t5/English-Knowledge-Base/Avatar-Rendering-Complexity/ta-p/2967838 avatar complexity] is [AGENT_COMPLEXITY].
+ <usetemplate
+ ignoretext="Warn me about my avatar complexity changes"
+ name="notifyignore"/>
+ </notification>
+
+ <notification
+ icon = "notifytip.tga"
+ name = "HUDComplexityWarning"
+ type = "notifytip"
+ log_to_chat = "false">
+ <unique combine = "cancel_old">
+ <context>HUDComplexityWarning</context>
+ </unique>
+ [HUD_REASON], it is likely to negatively affect your performance.
+ <usetemplate
+ ignoretext="Warn me when my HUD complexity is too high"
+ name="notifyignore"/>
</notification>
<notification
@@ -3665,6 +3651,13 @@ Can&apos;t add estate owner to estate &apos;Banned Resident&apos; list.
<notification
icon="alertmodal.tga"
+ name="ProblemAddingEstateManagerBanned"
+ type="alertmodal">
+Unable to add banned resident to estate manager list.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CanNotChangeAppearanceUntilLoaded"
type="alertmodal">
Can&apos;t change appearance until clothing and shape are loaded.
@@ -4059,6 +4052,18 @@ Do you want to open your Web browser to view this content?
<notification
icon="alertmodal.tga"
+ name="SystemUIScaleFactorChanged"
+ type="alertmodal">
+System UI size factor has changed since last run. Do you want to open UI size adjustment settings page?
+ <tag>confirm</tag>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="WebLaunchJoinNow"
type="alertmodal">
Go to your [http://secondlife.com/account/ Dashboard] to manage your account?
@@ -4178,6 +4183,14 @@ Leave Group?
</notification>
<notification
+ icon="notify.tga"
+ name="GroupDepart"
+ type="notify">
+You have left the group &apos;[group_name]&apos;.
+ <tag>group</tag>
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="OwnerCannotLeaveGroup"
type="alertmodal">
@@ -4189,6 +4202,17 @@ Leave Group?
</notification>
<notification
+ icon="alertmodal.tga"
+ name="GroupDepartError"
+ type="alertmodal">
+ Unable to leave group.
+ <tag>group</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alert.tga"
name="ConfirmKick"
type="alert">
@@ -5310,6 +5334,17 @@ There are too many prims selected. Please select [MAX_PRIM_COUNT] or fewer prim
</notification>
<notification
+ icon="alertmodal.tga"
+ name="TooManyScriptsSelected"
+ type="alertmodal">
+Too many scripts in the objects selected. Please select fewer objects and try again
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alertmodal.tga"
name="ProblemImportingEstateCovenant"
type="alertmodal">
@@ -5728,6 +5763,17 @@ Warning: The &apos;Pay object&apos; click action has been set, but it will only
<notification
icon="alertmodal.tga"
+ name="PaymentBlockedButtonMismatch"
+ type="alertmodal">
+ Payment stopped: the price paid does not match any of the pay buttons set for this object.
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="OpenObjectCannotCopy"
type="alertmodal">
There are no items in this object that you are allowed to copy.
@@ -5830,7 +5876,20 @@ You cannot undo this action.
notext="Cancel"
yestext="Unlink"/>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseConfirm"
+ type="alertmodal">
+ <unique/>
+Thank you for taking the time to inform us of this issue.
+We will review your report for possible violations and take
+the appropriate action.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="HelpReportAbuseSelectCategory"
@@ -7339,7 +7398,8 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
name="TeleportOffered_MaturityExceeded"
log_to_im="true"
log_to_chat="false"
- type="offer">
+ type="offer"
+ sound="UISndNewIncomingIMSession">
[NAME_SLURL] has offered to teleport you to their location:
“[MESSAGE]”
@@ -7364,7 +7424,8 @@ This region contains [REGION_CONTENT_MATURITY] content, but your current prefere
name="TeleportOffered_MaturityBlocked"
log_to_im="true"
log_to_chat="false"
- type="notifytip">
+ type="notifytip"
+ sound="UISndNewIncomingIMSession">
[NAME_SLURL] has offered to teleport you to their location:
“[MESSAGE]”
@@ -8804,23 +8865,6 @@ Click and drag anywhere on the world to rotate your view
</notification>
<notification
- name="PopupAttempt"
- icon="Popup_Caution"
- type="browser">
- A pop-up was prevented from opening.
- <form name="form">
- <ignore name="ignore"
- control="MediaEnablePopups"
- invert_control="true"
- text="Enable all pop-ups"/>
- <button default="true"
- index="0"
- name="open"
- text="Open pop-up window"/>
- </form>
- </notification>
-
- <notification
icon="alertmodal.tga"
name="SOCKS_NOT_PERMITTED"
type="alertmodal">
@@ -9802,6 +9846,14 @@ Can't move object '[OBJECT_NAME]' to
<notification
icon="alertmodal.tga"
+ name="NoParcelPermsNoObject"
+ type="notify">
+ <tag>fail</tag>
+Copy failed because you lack access to that parcel.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CantMoveObjectRegionVersion"
type="notify">
<tag>fail</tag>
@@ -9837,6 +9889,17 @@ You don't have permission to modify that object
<notification
icon="alertmodal.tga"
+ name="TooMuchObjectInventorySelected"
+ type="alertmodal">
+ <tag>fail</tag>
+ Too many objects with large inventory are selected. Please select fewer objects and try again.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CantEnablePhysObjContributesToNav"
type="notify">
<tag>fail</tag>
@@ -9934,6 +9997,22 @@ Cannot save to object contents: This would modify the attachment permissions.
<notification
icon="alertmodal.tga"
+ name="AttachmentHasTooMuchInventory"
+ type="notify">
+ <tag>fail</tag>
+Your attachments contain too much inventory to add more.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="IllegalAttachment"
+ type="notify">
+ <tag>fail</tag>
+The attachment has requested a nonexistent point on the avatar. It has been attached to the chest instead.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="TooManyScripts"
type="notify">
<tag>fail</tag>
@@ -10183,6 +10262,22 @@ You have been teleported by the object '[OBJECT_NAME]' owned by an unknown user.
<notification
icon="alertmodal.tga"
+ name="StandDeniedByObject"
+ type="notify">
+ <tag>fail</tag>
+'[OBJECT_NAME]' will not allow you to stand at this time.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ResitDeniedByObject"
+ type="notify">
+ <tag>fail</tag>
+'[OBJECT_NAME]' will not allow you to change your seat at this time.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CantCreateObjectRegionFull"
type="notify">
<tag>fail</tag>
@@ -10972,6 +11067,14 @@ Money transfers to objects are currently disabled in this region.
<notification
icon="alertmodal.tga"
+ name="DroppedMoneyTransferRequest"
+ type="notify">
+ <tag>fail</tag>
+Unable to make payment due to system load.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CantPayNoAgent"
type="notify">
<tag>fail</tag>
@@ -11068,4 +11171,16 @@ Cannot create large prims that intersect other players. Please re-try when othe
yestext="OK"/>
</notification>
+
+ <notification
+ icon="alert.tga"
+ name="OutfitPhotoLoadError"
+ type="alertmodal">
+ [REASON]
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
new file mode 100644
index 0000000000..c1272c6bf8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ border="false"
+ follows="all"
+ height="430"
+ name="Outfit Gallery"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="318">
+ <string name="outfit_photo_string">
+ Photo of "[OUTFIT_NAME]" outfit
+ </string>
+ <string name="no_outfits_msg">
+ You don't have any outfits yet. Try [secondlife:///app/search/all/ Search]
+ </string>
+ <string name="no_matched_outfits_msg">
+ Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].
+ </string>
+ <text
+ type="string"
+ clip_partial="false"
+ follows="left|top"
+ layout="topleft"
+ left="13"
+ name="no_outfits_txt"
+ top="0"
+ height="32"
+ valign="center"
+ parse_urls="true"
+ wrap="true">
+ Searching...
+ </text>
+ <scroll_container
+ border="true"
+ bevel_style="none"
+ follows="all"
+ height="400"
+ width="312"
+ min_width="312"
+ layout="topleft"
+ left="4"
+ top="0"
+ name="gallery_scroll_panel"
+ opaque="false"
+ top_pad="0">
+ <!--outfit_gallery_item
+ layout="topleft"
+ left="10"
+ name="preview_outfit1"
+ height="175"
+ width="150"
+ follows="left|top"/-->
+ <!--layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="0" name="top_gallery_stack" orientation="horizontal">
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="190" name="top_gallery_stack" orientation="horizontal">
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack follows="left|right" height="180" width="498" layout="topleft" left="0" animate="false" top="380" name="top_gallery_stack" orientation="horizontal">
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top_gallery_panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit1" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ <layout_panel follows="left|top" height="175" width="166" layout="topleft" left="0" top="0" auto_resize="false" visible="true" name="top panel">
+ <outfit_gallery_item layout="topleft" left="10" name="preview_outfit2" height="175" width="150" follows="left|top"/>
+ </layout_panel>
+ </layout_stack-->
+ <!--</panel>-->
+ </scroll_container>
+ <panel
+ background_visible="true"
+ follows="bottom|left|right"
+ height="28"
+ layout="topleft"
+ left="4"
+ top_pad="0"
+ visible="true"
+ name="bottom_panel"
+ width="312">
+ <menu_button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="25"
+ image_hover_unselected="Toolbar_Left_Over"
+ image_overlay="OptionsMenu_Off"
+ image_selected="Toolbar_Left_Selected"
+ image_unselected="Toolbar_Left_Off"
+ layout="topleft"
+ left="0"
+ name="options_gear_btn"
+ top="1"
+ width="31" />
+ <icon
+ follows="bottom|left|right"
+ height="25"
+ image_name="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_icon"
+ width="243"/>
+ <button
+ follows="bottom|right"
+ height="25"
+ image_hover_unselected="Toolbar_Right_Over"
+ image_overlay="TrashItem_Off"
+ image_selected="Toolbar_Right_Selected"
+ image_unselected="Toolbar_Right_Off"
+ layout="topleft"
+ left_pad="1"
+ name="trash_btn"
+ tool_tip="Delete selected outfit"
+ width="31"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml
new file mode 100644
index 0000000000..e3f0f1128b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery_item.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="false"
+ background_opaque="false"
+ bg_alpha_color="FrogGreen"
+ bg_opaque_color="FrogGreen"
+ border="false"
+ bevel_style="none"
+ follows="left|top"
+ height="169"
+ width="150"
+ name="gallery_item_panel"
+ layout="topleft"
+ left="0"
+ top="0"
+ >
+ <string name="worn_string">
+ (worn)
+ </string>
+ <icon
+ left="1"
+ top="0"
+ layout="topleft"
+ name="preview_outfit"
+ height="149"
+ width="147"
+ follows="left|top"
+ visible="true"
+ image_name="Default_Outfit_Photo"
+ />
+ <panel
+ background_visible="false"
+ background_opaque="true"
+ bg_opaque_color="OutfitGalleryItemSelected"
+ border="false"
+ bevel_style="none"
+ follows="left|top"
+ left="0"
+ top="149"
+ height="25"
+ width="148"
+ name="text_bg_panel"
+ >
+ <text
+ read_only="true"
+ length="1"
+ follows="left|top"
+ left="1"
+ height="10"
+ layout="topleft"
+ name="outfit_name"
+ top="2"
+ width="150"
+ use_ellipses="true">
+ Summer hipster, Pierce Pierce Pierce Pierce
+ </text>
+ <text
+ read_only="true"
+ length="1"
+ follows="left|top"
+ left="1"
+ height="10"
+ layout="topleft"
+ name="outfit_worn_text"
+ top="12"
+ width="150">
+ (worn)
+ </text>
+ </panel>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
new file mode 100644
index 0000000000..800faabc2a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="380"
+ layout="topleft"
+ name="panel_outfit_snapshot_inventory"
+ width="490">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Snapshot_Inventory"
+ layout="topleft"
+ left="12"
+ mouse_opaque="true"
+ name="title_icon"
+ top="6"
+ width="18" />
+ <text
+ follows="top|left|right"
+ font="SansSerifBold"
+ height="14"
+ layout="topleft"
+ left_pad="12"
+ length="1"
+ name="title"
+ right="-10"
+ text_color="white"
+ type="string"
+ top_delta="3">
+ Inventory
+ </text>
+ <view_border
+ bevel_style="in"
+ follows="left|top|right"
+ height="1"
+ left="9"
+ layout="topleft"
+ name="hr"
+ right="-5"
+ top_pad="5"
+ />
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="56"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="hint_lbl"
+ top_pad="6"
+ width="200"
+ type="string"
+ word_wrap="true">
+ Uploading an image to your inventory costs L$[UPLOAD_COST].
+ </text>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-5"
+ top="337"
+ width="97">
+ <button.commit_callback
+ function="Inventory.SaveOutfitCancel" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="UPLOAD L$10"
+ layout="topleft"
+ left="10"
+ name="save_btn"
+ top_delta="0"
+ width="97">
+ <button.commit_callback
+ function="Inventory.SaveOutfitPhoto" />
+ </button>
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index 405d9513db..ff0714adbb 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -33,6 +33,17 @@
top="8"
width="315">
<panel
+ class="outfit_gallery"
+ filename="panel_outfit_gallery.xml"
+ height="520"
+ name="outfit_gallery_tab"
+ background_visible="true"
+ help_topic="outfit_gallery_tab"
+ follows="all"
+ label="OUTFIT GALLERY"
+ layout="topleft"
+ width="315" />
+ <panel
class="outfits_list"
filename="panel_outfits_list.xml"
height="520"
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml
index d85b778db2..42a7974316 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml
@@ -9,6 +9,26 @@
name="Wearing"
top="0"
width="312">
+<panel.string
+ name="no_attachments">
+ No attachments worn.
+ </panel.string>
+ <accordion
+ fit_parent="true"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ single_expansion="true"
+ top="0"
+ name="wearables_accordion"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ width="309">
+ <accordion_tab
+ layout="topleft"
+ name="tab_wearables"
+ title="Wearables">
<wearable_items_list
follows="all"
height="400"
@@ -20,6 +40,27 @@
top="0"
width="309"
worn_indication_enabled="false" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_temp_attachments"
+ title="Temporary attachments">
+ <scroll_list
+ draw_heading="false"
+ left="3"
+ width="309"
+ height="400"
+ follows="all"
+ name="temp_attachments_list">
+ <scroll_list.columns
+ name="icon"
+ width="15" />
+ <scroll_list.columns
+ name="text"
+ width="210" />
+ </scroll_list>
+ </accordion_tab>
+ </accordion>
<panel
background_visible="true"
follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 4a5117adac..0deb1d03cf 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -138,7 +138,7 @@
initial_value="1"
layout="topleft"
left_pad="0"
- max_val="2.0"
+ max_val="4.0"
min_val="0.75"
name="ui_scale_slider"
top_pad="-14"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index a9b8e197bc..e002d9dee1 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -233,7 +233,7 @@
<slider
control_name="IndirectMaxComplexity"
- tool_tip="Controls at what point a visually complex avatar is drawn as a jelly doll"
+ tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
follows="left|top"
height="16"
initial_value="101"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 0b605cf6f7..c20f9b2c51 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -273,6 +273,18 @@
name="update_willing_to_test"
width="400"
top_pad="5"/>
+ <check_box
+ top_delta="4"
+ enabled="true"
+ follows="left|top"
+ height="14"
+ control_name="UpdaterShowReleaseNotes"
+ label="Show Release Notes after update"
+ left_delta="0"
+ mouse_opaque="true"
+ name="update_show_release_notes"
+ width="400"
+ top_pad="5"/>
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
index eb67d07601..068e4420bc 100644
--- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -374,9 +374,11 @@
layout="topleft"
tool_tip="Movie play progress"
width="200">
- <slider_bar.commit_callback
- function="MediaCtrl.JumpProgress" />
- </slider_bar>
+ <slider_bar.mouse_down_callback
+ function="MediaCtrl.MouseDown" />
+ <slider_bar.mouse_up_callback
+ function="MediaCtrl.MouseUp" />
+ </slider_bar>
</layout_panel>
<layout_panel
name="skip_back"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b19c6756bc..00237d493a 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -25,7 +25,7 @@
[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([CHANNEL])
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
</string>
- <string name="BuildConfig">Build Configuration [BUILD_CONFIG]</string>
+ <string name="BuildConfig">Build Configuration [BUILD_CONFIG] [ADDRESS_SIZE] bits</string>
<string name="AboutPosition">
You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
@@ -51,13 +51,14 @@ OpenGL Version: [OPENGL_VERSION]
J2C Decoder Version: [J2C_VERSION]
Audio Driver Version: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF Version: [LLCEFLIB_VERSION]
+LibVLC Version: [LIBVLC_VERSION]
Voice Server Version: [VOICE_VERSION]
</string>
<string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string>
<string name="AboutTime">[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second,datetime,slt]</string>
<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>
<string name="BuildConfiguration">Build Configuration</string>
-
+
<!-- progress -->
<string name="ProgressRestoring">Restoring...</string>
<string name="ProgressChangingResolution">Changing resolution...</string>
@@ -499,6 +500,7 @@ Please try logging in again in a minute.</string>
<string name="TeleportYourAgent">Teleport you</string>
<string name="ManageEstateSilently">Manage your estates silently</string>
<string name="ChangeYourDefaultAnimations">Change your default animations</string>
+ <string name="ForceSitAvatar">Force your avatar to sit</string>
<string name="NotConnected">Not Connected</string>
<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
@@ -2499,6 +2501,15 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f
<string name="av_render_most_of">You may not be rendered by most of those around you.</string>
<string name="av_render_anyone">You may not be rendered by anyone around you.</string>
+ <!-- HUD complexity rendering messages, see llavatarrendernotifier. -->
+ <string name="hud_description_total">Your HUD</string>
+ <string name="hud_name_with_joint">[OBJ_NAME] (worn on [JNT_NAME])</string>
+ <string name="hud_render_memory_warning">[HUD_DETAILS] uses a lot of texture memory</string>
+ <string name="hud_render_cost_warning">[HUD_DETAILS] contains a lot of expensive objects and textures</string>
+ <string name="hud_render_heavy_textures_warning">[HUD_DETAILS] contains a lot of large textures</string>
+ <string name="hud_render_cramped_warning">[HUD_DETAILS] contains too many objects</string>
+ <string name="hud_render_textures_warning">[HUD_DETAILS] contains too many textures</string>
+
<!-- AgeYearsA = singular,
AgeYearsB = plural,
AgeYearsC = plural for non-English languages like Russian
@@ -2566,7 +2577,8 @@ This feature is currently in Beta. Please add your name to this [http://goo.gl/f
<string name="SaveComplete">Save complete.</string>
<string name="UploadFailed">File upload failed: </string>
<string name="ObjectOutOfRange">Script (object out of range)</string>
-
+ <string name="ScriptWasDeleted">Script (deleted from inventory)</string>
+
<!-- god tools -->
<string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string>
@@ -2834,6 +2846,12 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
<string name="Multiple Media">Multiple Media</string>
<string name="Play Media">Play/Pause Media</string>
+ <!-- Drivers support/update pages -->
+ <string name="IntelDriverPage">http://www.intel.com/p/en_US/support/detect/graphics</string>
+ <string name="NvidiaDriverPage">http://www.nvidia.com/Download/index.aspx?lang=en-us</string>
+ <string name="AMDDriverPage">http://support.amd.com/us/Pages/AMDSupportHub.aspx</string>
+
+
<!-- OSMessageBox messages -->
<string name="MBCmdLineError">
An error was found parsing the command line.
@@ -3807,6 +3825,9 @@ Abuse Report</string>
<string name="DefaultMimeType">none/none</string>
<string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string>
+ <string name="outfit_photo_load_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please resize or use another image</string>
+ <string name="outfit_photo_select_dimensions_error">Max outfit photo size is [WIDTH]*[HEIGHT]. Please select another texture</string>
+ <string name="outfit_photo_verify_dimensions_error">Cannot verify photo dimensions. Please wait until photo size is displayed in picker</string>
<!-- language specific white-space characters, delimiters, spacers, item separation symbols -->
<string name="sentences_separator" value=" "></string>
diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml
index 8ea56c5262..8aaa236475 100644
--- a/indra/newview/skins/default/xui/es/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">[AMT] L$</panel.string>
- <panel left="-410" name="balance_bg" width="200">
+ <panel left="-431" name="balance_bg" width="200">
<text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="L$??"/>
<button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/>
<button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
index e2f05a525e..fef0379c2c 100644
--- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">[AMT] L$</panel.string>
- <panel left="-405" name="balance_bg" width="195">
+ <panel left="-426" name="balance_bg" width="195">
<text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="L$ ??"/>
<button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/>
<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/>
diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml
index 83d2ae5bab..295ca8d9f2 100644
--- a/indra/newview/skins/default/xui/it/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-405" name="balance_bg" width="195">
+ <panel left="-426" name="balance_bg" width="195">
<text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ ??"/>
<button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/>
<button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
index 2e1446d450..3f3845e491 100644
--- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[year, datetime, slt] [month, datetime, slt] [day, datetime, slt] ([weekday, datetime, slt])</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-370" name="balance_bg" width="160">
+ <panel left="-391" name="balance_bg" width="160">
<text name="balance" tool_tip="クリックして L$ 残高を更新" value="L$??"/>
<button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/>
<button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く" width="40"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
index cfe52ff404..c35863734f 100644
--- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-410" name="balance_bg" width="200">
+ <panel left="-431" name="balance_bg" width="200">
<text name="balance" tool_tip="Atualizar saldo de L$" value="L$??"/>
<button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/>
<button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
index 630925fa60..49c48ae654 100644
--- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour, datetime, slt]:[min, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-450" name="balance_bg" width="240">
+ <panel left="-471" name="balance_bg" width="240">
<text name="balance" tool_tip="Щелкните для обновления вашего баланса L$" value="L$??"/>
<button label="Купить L$" name="buyL" tool_tip="Щелкните для покупки L$"/>
<button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
index 9e2669ec2b..7c7bfc7e14 100644
--- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml
@@ -5,7 +5,7 @@
<panel.string name="time">[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]</panel.string>
<panel.string name="timeTooltip">[weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]</panel.string>
<panel.string name="buycurrencylabel">L$ [AMT]</panel.string>
- <panel left="-425" name="balance_bg" width="215">
+ <panel left="-446" name="balance_bg" width="215">
<text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$??"/>
<button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/>
<button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/>
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index 1b0334498e..b603157ca7 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -136,6 +136,7 @@ void LLGridManager::addSystemGrid(const std::string& label,
const std::string& helper,
const std::string& login_page,
const std::string& update_url_base,
+ const std::string& web_profile_url,
const std::string& login_id)
{
}
diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp
index 6b0be29c2d..f1f69f33f1 100644
--- a/indra/newview/tests/llversioninfo_test.cpp
+++ b/indra/newview/tests/llversioninfo_test.cpp
@@ -29,6 +29,13 @@
#include "../llversioninfo.h"
+// LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The
+// macro expands to the string name of the channel, but without quotes. We
+// need to turn it into a quoted string. This macro trick does that.
+#define stringize_inner(x) #x
+#define stringize_outer(x) stringize_inner(x)
+#define ll_viewer_channel stringize_outer(LL_VIEWER_CHANNEL)
+
namespace tut
{
struct versioninfo
@@ -50,7 +57,7 @@ namespace tut
mShortVersion = stream.str();
stream.str("");
- stream << LL_VIEWER_CHANNEL
+ stream << ll_viewer_channel
<< " "
<< mVersion;
mVersionAndChannel = stream.str();
@@ -89,7 +96,7 @@ namespace tut
LL_VIEWER_VERSION_BUILD);
ensure_equals("Channel version",
LLVersionInfo::getChannel(),
- LL_VIEWER_CHANNEL);
+ ll_viewer_channel);
ensure_equals("Version String",
LLVersionInfo::getVersion(),
mVersion);
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f3d89bb866..589d74a014 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -287,7 +287,8 @@ class ViewerManifest(LLManifest):
random.shuffle(names)
return ', '.join(names)
-class Windows_i686_Manifest(ViewerManifest):
+
+class WindowsManifest(ViewerManifest):
def final_exe(self):
return self.app_name_oneword()+".exe"
@@ -338,7 +339,7 @@ class Windows_i686_Manifest(ViewerManifest):
print "Doesn't exist:", src
def construct(self):
- super(Windows_i686_Manifest, self).construct()
+ super(WindowsManifest, self).construct()
pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
relpkgdir = os.path.join(pkgdir, "lib", "release")
@@ -386,10 +387,7 @@ class Windows_i686_Manifest(ViewerManifest):
print "Skipping fmodex audio library(assuming other audio engine)"
# For textures
- if self.args['configuration'].lower() == 'debug':
- self.path("openjpegd.dll")
- else:
- self.path("openjpeg.dll")
+ self.path("openjpeg.dll")
# 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
@@ -444,6 +442,11 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("media_plugin_cef.dll")
self.end_prefix()
+ # Media plugins - LibVLC
+ if self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"):
+ self.path("media_plugin_libvlc.dll")
+ self.end_prefix()
+
# winmm.dll shim
if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
self.path("winmm.dll")
@@ -550,6 +553,12 @@ class Windows_i686_Manifest(ViewerManifest):
self.path("zh-TW.pak")
self.end_prefix()
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"):
+ self.path("libvlc.dll")
+ self.path("libvlccore.dll")
+ self.path("plugins/")
+ self.end_prefix()
+
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
@@ -688,7 +697,17 @@ class Windows_i686_Manifest(ViewerManifest):
self.package_file = installer_file
-class Darwin_i386_Manifest(ViewerManifest):
+class Windows_i686_Manifest(WindowsManifest):
+ # specialize when we must
+ pass
+
+
+class Windows_x86_64_Manifest(WindowsManifest):
+ # specialize when we must
+ pass
+
+
+class DarwinManifest(ViewerManifest):
def is_packaging_viewer(self):
# darwin requires full app bundle packaging even for debugging.
return True
@@ -714,7 +733,7 @@ class Darwin_i386_Manifest(ViewerManifest):
# most everything goes in the Resources directory
if self.prefix(src="", dst="Resources"):
- super(Darwin_i386_Manifest, self).construct()
+ super(DarwinManifest, self).construct()
if self.prefix("cursors_mac"):
self.path("*.tif")
@@ -1041,6 +1060,20 @@ class Darwin_i386_Manifest(ViewerManifest):
self.package_file = finalname
self.remove(sparsename)
+
+class Darwin_i386_Manifest(DarwinManifest):
+ pass
+
+
+class Darwin_i686_Manifest(DarwinManifest):
+ """alias in case arch is passed as i686 instead of i386"""
+ pass
+
+
+class Darwin_x86_64_Manifest(DarwinManifest):
+ pass
+
+
class LinuxManifest(ViewerManifest):
def construct(self):
super(LinuxManifest, self).construct()
@@ -1089,8 +1122,18 @@ class LinuxManifest(ViewerManifest):
# plugins
if self.prefix(src="", dst="bin/llplugin"):
self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
+ self.path("../media_plugins/libvlc/libmedia_plugin_libvlc.so", "libmedia_plugin_libvlc.so")
self.end_prefix("bin/llplugin")
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"):
+ self.path( "plugins.dat" )
+ self.path( "*/*.so" )
+ self.end_prefix()
+
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib' ), dst="lib"):
+ self.path( "libvlc*.so*" )
+ self.end_prefix()
+
# llcommon
if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"):
print "Skipping llcommon.so (assuming llcommon was linked statically)"
@@ -1144,7 +1187,7 @@ class LinuxManifest(ViewerManifest):
def strip_binaries(self):
if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
- self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
+ self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
class Linux_i686_Manifest(LinuxManifest):
def construct(self):
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 55442b2521..8344cead57 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -102,7 +102,6 @@ target_link_libraries(lltest
${BOOST_CONTEXT_LIBRARY}
${BOOST_SYSTEM_LIBRARY}
${DL_LIBRARY}
- ${GOOGLE_PERFTOOLS_LIBRARIES}
)
if (WINDOWS)
diff --git a/indra/test/llapp_tut.cpp b/indra/test/llapp_tut.cpp
index aa5c0672e6..98e714a497 100644
--- a/indra/test/llapp_tut.cpp
+++ b/indra/test/llapp_tut.cpp
@@ -41,7 +41,7 @@ namespace tut
public:
virtual bool init() { return true; }
virtual bool cleanup() { return true; }
- virtual bool mainLoop() { return true; }
+ virtual bool frame() { return true; }
};
LLTestApp* mApp;
application()
diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt
deleted file mode 100644
index e682eaccca..0000000000
--- a/indra/test_apps/llplugintest/CMakeLists.txt
+++ /dev/null
@@ -1,336 +0,0 @@
-# -*- cmake -*-
-project(llplugintest)
-
-include(00-Common)
-include(OpenGL)
-include(LLCommon)
-include(LLPlugin)
-include(Linking)
-include(LLSharedLibs)
-include(PluginAPI)
-include(LLImage)
-include(LLMath)
-include(LLMessage)
-include(LLRender)
-include(LLWindow)
-include(Glut)
-include(Glui)
-
-include_directories(
- ${LLPLUGIN_INCLUDE_DIRS}
- ${LLCOMMON_INCLUDE_DIRS}
- ${LLIMAGE_INCLUDE_DIRS}
- ${LLMATH_INCLUDE_DIRS}
- ${LLMESSAGE_INCLUDE_DIRS}
- ${LLRENDER_INCLUDE_DIRS}
- ${LLWINDOW_INCLUDE_DIRS}
-)
-include_directories(SYSTEM
- ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
- )
-
-if (DARWIN)
- include(CMakeFindFrameworks)
- find_library(COREFOUNDATION_LIBRARY CoreFoundation)
-endif (DARWIN)
-
-### demo_plugin
-
-#set(demo_plugin_SOURCE_FILES
-# demo_plugin.cpp
-# )
-#
-#add_library(demo_plugin
-# SHARED
-# ${demo_plugin_SOURCE_FILES}
-#)
-#
-#target_link_libraries(demo_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-# ${PLUGIN_API_WINDOWS_LIBRARIES}
-#)
-#
-#add_dependencies(demo_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-#
-#if (DARWIN)
-# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
-# set_target_properties(
-# demo_plugin
-# PROPERTIES
-# PREFIX ""
-# BUILD_WITH_INSTALL_RPATH 1
-# INSTALL_NAME_DIR "@executable_path"
-# )
-#endif (DARWIN)
-
-### plugin_host
-
-#set(plugin_host_SOURCE_FILES
-# plugin_host.cpp
-# )
-#
-#add_executable(plugin_host
-# WIN32
-# ${plugin_host_SOURCE_FILES}
-#)
-#
-#set_target_properties(plugin_host
-# PROPERTIES
-# WIN32_EXECUTABLE
-# FALSE
-#)
-#
-#target_link_libraries(plugin_host
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-# ${PLUGIN_API_WINDOWS_LIBRARIES}
-#)
-#
-#add_dependencies(plugin_host
-# demo_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-
-### plugin_process_launcher
-
-#set(plugin_process_launcher_SOURCE_FILES
-# plugin_process_launcher.cpp
-# )
-#
-#add_executable(plugin_process_launcher
-# WIN32
-# ${plugin_process_launcher_SOURCE_FILES}
-#)
-#
-#set_target_properties(plugin_process_launcher
-# PROPERTIES
-# WIN32_EXECUTABLE
-# FALSE
-#)
-#
-#target_link_libraries(plugin_process_launcher
-# ${LLPLUGIN_LIBRARIES}
-# ${LLMESSAGE_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-# ${PLUGIN_API_WINDOWS_LIBRARIES}
-#)
-#
-#add_dependencies(plugin_process_launcher
-# SLPlugin
-# demo_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLMESSAGE_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-
-### media_simple_test
-
-#set(media_simple_test_SOURCE_FILES
-# media_simple_test.cpp
-# )
-#
-#add_executable(media_simple_test
-# WIN32
-# ${media_simple_test_SOURCE_FILES}
-#)
-#
-#add_dependencies(media_simple_test stage_third_party_libs)
-#
-#set_target_properties(media_simple_test
-# PROPERTIES
-# WIN32_EXECUTABLE
-# FALSE
-#)
-#
-#target_link_libraries(media_simple_test
-# ${GLUT_LIBRARY}
-# ${OPENGL_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-
-### media_plugin_test
-
-#set(media_plugin_test_SOURCE_FILES
-# media_plugin_test.cpp
-# )
-#
-#add_executable(media_plugin_test
-# WIN32
-# ${media_plugin_test_SOURCE_FILES}
-#)
-#
-#set_target_properties(media_plugin_test
-# PROPERTIES
-# WIN32_EXECUTABLE
-# FALSE
-#)
-#
-#target_link_libraries(media_plugin_test
-# ${GLUT_LIBRARY}
-# ${OPENGL_LIBRARIES}
-# ${LLPLUGIN_LIBRARIES}
-# ${LLMESSAGE_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-# ${PLUGIN_API_WINDOWS_LIBRARIES}
-#)
-#
-#add_dependencies(media_plugin_test
-# stage_third_party_libs
-# SLPlugin
-# demo_media_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLMESSAGE_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-
-### demo_media_plugin
-
-#set(demo_media_plugin_SOURCE_FILES
-# demo_media_plugin.cpp
-# )
-#
-#add_library(demo_media_plugin
-# SHARED
-# ${demo_media_plugin_SOURCE_FILES}
-#)
-#
-#target_link_libraries(demo_media_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-# ${PLUGIN_API_WINDOWS_LIBRARIES}
-#)
-#
-#add_dependencies(demo_media_plugin
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-#
-#if (DARWIN)
-# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
-# set_target_properties(
-# demo_media_plugin
-# PROPERTIES
-# PREFIX ""
-# BUILD_WITH_INSTALL_RPATH 1
-# INSTALL_NAME_DIR "@executable_path"
-# )
-#endif (DARWIN)
-
-### demo_media_plugin_2
-
-#set(demo_media_plugin_2_SOURCE_FILES
-# demo_media_plugin_2.cpp
-# )
-#
-#add_library(demo_media_plugin_2
-# SHARED
-# ${demo_media_plugin_2_SOURCE_FILES}
-#)
-#
-#target_link_libraries(demo_media_plugin_2
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-# ${PLUGIN_API_WINDOWS_LIBRARIES}
-#)
-#
-#add_dependencies(demo_media_plugin_2
-# ${LLPLUGIN_LIBRARIES}
-# ${LLCOMMON_LIBRARIES}
-#)
-#
-#if (DARWIN)
-# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
-# set_target_properties(
-# demo_media_plugin_2
-# PROPERTIES
-# PREFIX ""
-# BUILD_WITH_INSTALL_RPATH 1
-# INSTALL_NAME_DIR "@executable_path"
-# )
-#endif (DARWIN)
-
-# Gather build products of the various dependencies into the build directory for the testbed.
-
-if(WINDOWS)
- #********************
- # Plugin test library deploy
- #
- # Debug config runtime files required for the plugin test mule
- set(plugintest_debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
- set(plugintest_debug_files
- libeay32.dll
- libglib-2.0-0.dll
- libgmodule-2.0-0.dll
- libgobject-2.0-0.dll
- libgthread-2.0-0.dll
- ssleay32.dll
- )
- copy_if_different(
- ${plugintest_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug"
- out_targets
- ${plugintest_debug_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the plugin test mule
- set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
- set(plugintest_release_files
- libeay32.dll
- libglib-2.0-0.dll
- libgmodule-2.0-0.dll
- libgobject-2.0-0.dll
- libgthread-2.0-0.dll
- ssleay32.dll
- )
- copy_if_different(
- ${plugintest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- copy_if_different(
- ${plugintest_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- add_custom_target(copy_plugintest_libs ALL
- DEPENDS
- ${plugin_test_targets}
- )
-
-endif(WINDOWS)
-
-if (DARWIN)
- set(plugintest_release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
- set(plugintest_release_files
- libexception_handler.dylib
- libaprutil-1.0.dylib
- libapr-1.0.dylib
- libexpat.1.5.2.dylib
- )
- copy_if_different(
- ${plugintest_release_src_dir}
- "${PLUGINS_DESTINATION_DIR}"
- out_targets
- ${plugintest_release_files}
- )
- set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
- add_custom_target(copy_plugintest_libs ALL
- DEPENDS
- ${plugin_test_targets}
- )
-
-endif (DARWIN)
-
diff --git a/indra/test_apps/llplugintest/README.Linden b/indra/test_apps/llplugintest/README.Linden
deleted file mode 100644
index 4a9f223c21..0000000000
--- a/indra/test_apps/llplugintest/README.Linden
+++ /dev/null
@@ -1,21 +0,0 @@
-
-1. Description
-
- Exercises SLPlugin. Demonstrates mediakit plugin reuse and
- switchover as MIME type changes (web, quicktime, flash).
-
-
-2. Running
-
- 2.1 Mac
-
- Make certain '.' is included in PATH. E.g.:
-
- PATH=.:"$PATH" open build-darwin-i386/test_apps/llmediaplugintest/RelWithDebInfo/llmediaplugintest.app
-
- Otherwise the program won't find SLPlugin and will timeout and
- fail after 30 seconds and give you little information as to why.
-
- Running 'dtruss' on plugin test applications will give you a great
- deal of insight into why they aren't activating.
-
diff --git a/indra/test_apps/llplugintest/bookmarks.txt b/indra/test_apps/llplugintest/bookmarks.txt
deleted file mode 100644
index 2ff64f217f..0000000000
--- a/indra/test_apps/llplugintest/bookmarks.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-# format is description, url (don't put ',' chars in description :)
-# if no ',' found, whole line is used for both description and url
-(WK) Google Home Page,http://www.google.com
-(WK) BBC News Home Page,http://news.bbc.co.uk
-(WK) Second Life,http://secondlife.com
-(WK) WebKit Home ,http://www.webkit.org
-(WK) Yahoo News,http://news.yahoo.com
-(WK) Canvas Paint (DHTML version of MS Paint),http://www.canvaspaint.org
-(WK) DHTML Lemmings!,http://www.elizium.nu/scripts/lemmings/
-(WK) DHTML graphics demos,http://www.dhteumeuleu.com/
-(WK) Shared paint app,http://colorillo.com/ac79?1l0q6cp
-(Flash) YouTube,http://youtube.com
-(Flash) Vimeo,http://www.vimeo.com/1778399
-(Flash) Simple whiteboard,http://www.imaginationcubed.com/
-(Flash) Dabble Board,http://www.dabbleboard.com/draw
-(Flash) Bubble Shooter game,http://www.wiicade.com/playGame.aspx?gameID=72&gameName=Bubble%20Shooter
-(Flash) Pixlr photo editor,http://pixlr.com/editor/
-(Flash) Scribd,http://www.scribd.com/doc/14427744/Second-Life-Quickstart-Guide
-(Flash) MAME,http://yvern.com/fMAME/fMAME.html
-(QT) Local sample,file:///C|/Program Files/QuickTime/Sample.mov
-(QT) Movie - Watchmen Trailer,http://trailers.apple.com/movies/wb/watchmen/watchmen-tlr2_480p.mov
-(QT) Movie - Transformers - Revenge of the Fallen,http://trailers.apple.com/movies/paramount/transformers2/transformersrevengeofthefallen-tlr1_h.320.mov
-(QT) Movie - Terminator Salvation,http://trailers.apple.com/movies/wb/terminatorsalvation/terminatorsalvation-tlr3_h.320.mov
-(QT) Movie - Angels and Demons,http://trailers.apple.com/movies/sony_pictures/angelsanddemons/angelsanddemons-video_h.320.mov
-(QT) Movie - Sin City Trailer,http://trailers.apple.com/movies/miramax/sin_city/sin_city_480.mov
-(QT) Movie - The Incredibles Trailer,http://trailers.apple.com/movies/disney/the_incredibles/the_incredibles-tlr_a480.mov
-(QT) Movie - Streaming Apple Event,http://stream.qtv.apple.com/events/mar/0903lajkszg/m_090374535329zdwg_650_ref.mov
-(QT) Movie - MPEG-4 from Amazon S3,http://s3.amazonaws.com/callum-linden/flashdemo/interactive_flash_demo.mp4
-(QT) Movie - Star Trek,http://trailers.apple.com/movies/paramount/star_trek/startrek-tlr3_h.320.mov
-(QT) Movie - Ice Age 3,http://trailers.apple.com/movies/fox/ice_age_iii/iceage3-tlrd_h.320.mov
-(QT) Movie - AstroBoy,http://trailers.apple.com/movies/summit/astroboy/astroboy-tsr_h.320.mov
-(QT) Movie - Ante Up,http://trailers.apple.com/movies/independent/anteup/anteup_h.320.mov
-(QT) Movie - Every Little Step,http://trailers.apple.com/movies/sony/everylittlestep/everylittlestep-clip_h.320.mov
-(QT) Movie - The Informers,http://trailers.apple.com/movies/independent/theinformers/theinformers_h.320.mov
-(QT) Animated GIF,http://upload.wikimedia.org/wikipedia/commons/4/44/Optical.greysquares.arp-animated.gif
-(QT) Apple Text Descriptors,http://ubrowser.com/tmp/apple_text.txt
-(EX) Example Plugin,example://blah
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 53d4acc9e0..c767d52c7b 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -42,6 +42,8 @@
#include "llevents.h"
#include "lleventfilter.h"
#include "lleventcoro.h"
+#include "llexception.h"
+#include "stringize.h"
//*********************
// LLLogin
@@ -128,30 +130,23 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
{
- try
- {
- LLSD printable_params = login_params;
- //if(printable_params.has("params")
- // && printable_params["params"].has("passwd"))
- //{
- // printable_params["params"]["passwd"] = "*******";
- //}
- LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
+ LLSD printable_params = login_params;
+ if (printable_params.has("params")
+ && printable_params["params"].has("passwd"))
+ {
+ printable_params["params"]["passwd"] = "*******";
+ }
+ try
+ {
+ LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
<< " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
- // Arriving in SRVRequest state
- LLEventStream replyPump("SRVreply", true);
- // Should be an array of one or more uri strings.
-
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
// EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
// to share them -- but the EXT-3934 fix made it possible for an abandoned
// SRV response to arrive just as we were expecting the XMLRPC response.
LLEventStream loginReplyPump("loginreply", true);
- // Loop through the rewrittenURIs, counting attempts along the way.
- // Because of possible redirect responses, we may make more than one
- // attempt per rewrittenURIs entry.
LLSD::Integer attempts = 0;
LLSD request(login_params);
@@ -167,11 +162,11 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
LLSD progress_data;
progress_data["attempt"] = attempts;
progress_data["request"] = request;
- if(progress_data["request"].has("params")
- && progress_data["request"]["params"].has("passwd"))
- {
- progress_data["request"]["params"]["passwd"] = "*******";
- }
+ if (progress_data["request"].has("params")
+ && progress_data["request"]["params"].has("passwd"))
+ {
+ progress_data["request"]["params"]["passwd"] = "*******";
+ }
sendProgressEvent("offline", "authenticating", progress_data);
// We expect zero or more "Downloading" status events, followed by
@@ -189,8 +184,8 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
// Still Downloading -- send progress update.
sendProgressEvent("offline", "downloading");
}
-
- LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
+
+ LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
status = mAuthResponse["status"].asString();
// Okay, we've received our final status event for this
@@ -202,7 +197,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
break;
}
- sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
+ sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
// Here the login service at the current URI is redirecting us
// to some other URI ("indeterminate" -- why not "redirect"?).
@@ -212,8 +207,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
request["method"] = mAuthResponse["responses"]["next_method"].asString();
} // loop back to try the redirected URI
- // Here we're done with redirects for the current rewrittenURIs
- // entry.
+ // Here we're done with redirects.
if (status == "Complete")
{
// StatusComplete does not imply auth success. Check the
@@ -230,14 +224,14 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
return; // Done!
}
-// /* Sometimes we end with "Started" here. Slightly slow server?
-// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
-// */
-// if( status == "Started")
-// {
-// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
-// continue;
-// }
+// /* Sometimes we end with "Started" here. Slightly slow server?
+// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
+// */
+// if( status == "Started")
+// {
+// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
+// continue;
+// }
// If we don't recognize status at all, trouble
if (! (status == "CURLError"
@@ -250,27 +244,25 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
}
// Here status IS one of the errors tested above.
-
- // Here we got through all the rewrittenURIs without succeeding. Tell
- // caller this didn't work out so well. Of course, the only failure data
- // we can reasonably show are from the last of the rewrittenURIs.
-
- // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
- // llsd with no "responses" node. To make the output from an incomplete login symmetrical
- // to success, add a data/message and data/reason fields.
- LLSD error_response;
- error_response["reason"] = mAuthResponse["status"];
- error_response["errorcode"] = mAuthResponse["errorcode"];
- error_response["message"] = mAuthResponse["error"];
- if(mAuthResponse.has("certificate"))
- {
- error_response["certificate"] = mAuthResponse["certificate"];
- }
- sendProgressEvent("offline", "fail.login", error_response);
- }
- catch (...) {
- LL_ERRS() << "login exception caught" << LL_ENDL;
- }
+ // Tell caller this didn't work out so well.
+
+ // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
+ // llsd with no "responses" node. To make the output from an incomplete login symmetrical
+ // to success, add a data/message and data/reason fields.
+ LLSD error_response;
+ error_response["reason"] = mAuthResponse["status"];
+ error_response["errorcode"] = mAuthResponse["errorcode"];
+ error_response["message"] = mAuthResponse["error"];
+ if(mAuthResponse.has("certificate"))
+ {
+ error_response["certificate"] = mAuthResponse["certificate"];
+ }
+ sendProgressEvent("offline", "fail.login", error_response);
+ }
+ catch (...) {
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
+ << "('" << uri << "', " << printable_params << ")"));
+ }
}
void LLLogin::Impl::disconnect()
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index 382689afa0..04e0395c50 100644
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -27,7 +27,7 @@
#include "llupdatedownloader.h"
#include "httpcommon.h"
-#include <stdexcept>
+#include "llexception.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <curl/curl.h>
@@ -85,11 +85,11 @@ private:
namespace {
class DownloadError:
- public std::runtime_error
+ public LLException
{
public:
DownloadError(const char * message):
- std::runtime_error(message)
+ LLException(message)
{
; // No op.
}
@@ -467,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u
if(!mCurl)
{
- throw DownloadError("failed to initialize curl");
+ LLTHROW(DownloadError("failed to initialize curl"));
}
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true));
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true));
@@ -508,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
if(mHeaderList == 0)
{
- throw DownloadError("cannot add Range header");
+ LLTHROW(DownloadError("cannot add Range header"));
}
throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList));
@@ -524,7 +524,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std
mDownloadData["hash"] = hash;
mDownloadData["current_version"] = ll_get_version();
LLSD path = uri.pathArray();
- if(path.size() == 0) throw DownloadError("no file path");
+ if(path.size() == 0) LLTHROW(DownloadError("no file path"));
std::string fileName = path[path.size() - 1].asString();
std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);
mDownloadData["path"] = filePath;
@@ -547,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
if(code != CURLE_OK) {
const char * errorString = curl_easy_strerror(code);
if(errorString != 0) {
- throw DownloadError(curl_easy_strerror(code));
+ LLTHROW(DownloadError(curl_easy_strerror(code)));
} else {
- throw DownloadError("unknown curl error");
+ LLTHROW(DownloadError("unknown curl error"));
}
} else {
; // No op.
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
index a0e2c0b362..1c7629da23 100644
--- a/indra/viewer_components/updater/llupdateinstaller.cpp
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -30,23 +30,25 @@
#include "llupdateinstaller.h"
#include "lldir.h"
#include "llsd.h"
+#include "llexception.h"
#if defined(LL_WINDOWS)
#pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!).
#endif
#include <boost/lexical_cast.hpp>
-
namespace {
- class RelocateError {};
-
-
+ struct RelocateError: public LLException
+ {
+ RelocateError(): LLException("llupdateinstaller: RelocateError") {}
+ };
+
std::string copy_to_temp(std::string const & path)
{
std::string scriptFile = gDirUtilp->getBaseFileName(path);
std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
- if(status != APR_SUCCESS) throw RelocateError();
+ if(status != APR_SUCCESS) LLTHROW(RelocateError());
return newPath;
}
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 788955a1b2..1665e41e70 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -32,6 +32,7 @@
#include "lltimer.h"
#include "llupdatechecker.h"
#include "llupdateinstaller.h"
+#include "llexception.h"
#include <boost/scoped_ptr.hpp>
#include <boost/weak_ptr.hpp>
@@ -190,8 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string& channel,
{
if(mIsChecking || mIsDownloading)
{
- throw LLUpdaterService::UsageError("LLUpdaterService::initialize call "
- "while updater is running.");
+ LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call "
+ "while updater is running."));
}
mChannel = channel;
@@ -222,8 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
{
if(mChannel.empty() || mVersion.empty())
{
- throw LLUpdaterService::UsageError("Set params before call to "
- "LLUpdaterService::startCheck().");
+ LLTHROW(LLUpdaterService::UsageError("Set params before call to "
+ "LLUpdaterService::startCheck()."));
}
mIsChecking = true;
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
index 95bbe1695c..78e8c6b290 100644
--- a/indra/viewer_components/updater/llupdaterservice.h
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -29,16 +29,17 @@
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include "llhasheduniqueid.h"
+#include "llexception.h"
class LLUpdaterServiceImpl;
class LLUpdaterService
{
public:
- class UsageError: public std::runtime_error
+ class UsageError: public LLException
{
public:
- UsageError(const std::string& msg) : std::runtime_error(msg) {}
+ UsageError(const std::string& msg) : LLException(msg) {}
};
// Name of the event pump through which update events will be delivered.
diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp
index 23c29e6b18..167acf6ac7 100644
--- a/indra/win_crash_logger/llcrashloggerwindows.cpp
+++ b/indra/win_crash_logger/llcrashloggerwindows.cpp
@@ -454,7 +454,7 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles()
//mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); //Not initialized.
}
-bool LLCrashLoggerWindows::mainLoop()
+bool LLCrashLoggerWindows::frame()
{
LL_INFOS() << "CrashSubmitBehavior is " << mCrashBehavior << LL_ENDL;
@@ -503,14 +503,14 @@ bool LLCrashLoggerWindows::mainLoop()
TranslateMessage(&msg);
DispatchMessage(&msg);
}
- return msg.wParam;
+ return true; // msg.wParam;
}
else
{
LL_WARNS() << "Unknown crash behavior " << mCrashBehavior << LL_ENDL;
- return 1;
+ return true; // 1;
}
- return 0;
+ return true; // 0;
}
void LLCrashLoggerWindows::updateApplication(const std::string& message)
diff --git a/indra/win_crash_logger/llcrashloggerwindows.h b/indra/win_crash_logger/llcrashloggerwindows.h
index 1812e2737e..f89b8708dc 100644
--- a/indra/win_crash_logger/llcrashloggerwindows.h
+++ b/indra/win_crash_logger/llcrashloggerwindows.h
@@ -46,7 +46,7 @@ public:
static LLCrashLoggerWindows* sInstance;
virtual bool init();
- virtual bool mainLoop();
+ virtual bool frame();
virtual void updateApplication(const std::string& message = LLStringUtil::null);
virtual bool cleanup();
virtual void gatherPlatformSpecificFiles();
diff --git a/indra/win_crash_logger/win_crash_logger.cpp b/indra/win_crash_logger/win_crash_logger.cpp
index 366edd894b..7466dbb766 100644
--- a/indra/win_crash_logger/win_crash_logger.cpp
+++ b/indra/win_crash_logger/win_crash_logger.cpp
@@ -52,7 +52,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
}
app.processingLoop();
- app.mainLoop();
+ app.frame();
app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
return 0;
diff --git a/scripts/packages-formatter.py b/scripts/packages-formatter.py
index 928d340b69..f91f5819b7 100755
--- a/scripts/packages-formatter.py
+++ b/scripts/packages-formatter.py
@@ -29,6 +29,12 @@ import sys
import errno
import re
import subprocess
+import argparse
+
+parser = argparse.ArgumentParser(description='Format dependency version and copyright information for the viewer About box content')
+parser.add_argument('channel', help='viewer channel name')
+parser.add_argument('version', help='viewer version number')
+args = parser.parse_args()
_autobuild=os.getenv('AUTOBUILD', 'autobuild')
@@ -50,9 +56,8 @@ def autobuild(*args):
# Don't attempt to interpret anything but ENOENT
raise
# Here it's ENOENT: subprocess can't find the autobuild executable.
- print >>sys.stderr, "packages-formatter on %s: can't run autobuild:\n%s\n%s" % \
- (sys.platform, ' '.join(command), err)
- sys.exit(1)
+ sys.exit("packages-formatter on %s: can't run autobuild:\n%s\n%s" % \
+ (sys.platform, ' '.join(command), err))
# no exceptions yet, let caller read stdout
return child.stdout
@@ -84,6 +89,7 @@ for line in copyrights:
else:
sys.exit("Unrecognized --copyrights output: %s" % line)
+print "%s %s" % (args.channel, args.version)
print viewer_copyright
for pkg in sorted(version):
print ': '.join([pkg, version[pkg]])