summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags1
-rw-r--r--README.md2
-rw-r--r--[-rwxr-xr-x]autobuild.xml42
-rwxr-xr-xbuild.sh1
-rwxr-xr-xdoc/contributions.txt19
-rw-r--r--indra/cmake/00-Common.cmake4
-rw-r--r--indra/integration_tests/llimage_libtest/llimage_libtest.cpp3
-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/llappearance/llavatarappearancedefines.h3
-rw-r--r--indra/llappearance/lltexlayer.h4
-rw-r--r--indra/llappearance/llwearabletype.cpp3
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp2
-rw-r--r--indra/llcommon/CMakeLists.txt11
-rw-r--r--indra/llcommon/llapp.cpp3
-rw-r--r--indra/llcommon/llapr.cpp2
-rw-r--r--indra/llcommon/llassettype.cpp3
-rw-r--r--indra/llcommon/llcleanup.cpp29
-rw-r--r--indra/llcommon/llcleanup.h33
-rw-r--r--indra/llcommon/llcommon.cpp5
-rw-r--r--indra/llcommon/llcoro_get_id.cpp32
-rw-r--r--indra/llcommon/llcoro_get_id.h30
-rw-r--r--indra/llcommon/llcoros.cpp114
-rw-r--r--indra/llcommon/llcoros.h26
-rw-r--r--indra/llcommon/llerror.cpp66
-rw-r--r--indra/llcommon/llerror.h1
-rw-r--r--indra/llcommon/llerrorcontrol.h5
-rw-r--r--indra/llcommon/llevents.cpp259
-rw-r--r--indra/llcommon/llevents.h11
-rw-r--r--indra/llcommon/llfile.cpp4
-rw-r--r--indra/llcommon/llfile.h2
-rw-r--r--indra/llcommon/llheteromap.cpp32
-rw-r--r--indra/llcommon/llheteromap.h95
-rw-r--r--indra/llcommon/llinitdestroyclass.cpp30
-rw-r--r--indra/llcommon/llinitdestroyclass.h175
-rw-r--r--indra/llcommon/llinitparam.cpp7
-rw-r--r--indra/llcommon/llinitparam.h1
-rw-r--r--indra/llcommon/llmetricperformancetester.cpp2
-rw-r--r--indra/llcommon/llmetricperformancetester.h2
-rw-r--r--indra/llcommon/llpounceable.h216
-rw-r--r--indra/llcommon/llregistry.h7
-rw-r--r--indra/llcommon/llsdparam.h1
-rw-r--r--indra/llcommon/llsdserialize.cpp1
-rw-r--r--indra/llcommon/llsingleton.cpp440
-rw-r--r--indra/llcommon/llsingleton.h637
-rw-r--r--indra/llcommon/lluriparser.cpp4
-rw-r--r--indra/llcommon/lluriparser.h2
-rw-r--r--indra/llcommon/tests/llerror_test.cpp4
-rw-r--r--indra/llcommon/tests/llheteromap_test.cpp163
-rw-r--r--indra/llcommon/tests/llleap_test.cpp5
-rw-r--r--indra/llcommon/tests/llpounceable_test.cpp230
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp5
-rw-r--r--indra/llcommon/tests/llsingleton_test.cpp207
-rw-r--r--indra/llcorehttp/CMakeLists.txt5
-rwxr-xr-x[-rw-r--r--]indra/llcorehttp/tests/llcorehttp_test.cpp3
-rw-r--r--indra/llcorehttp/tests/test_httprequest.hpp67
-rwxr-xr-xindra/llcorehttp/tests/test_llcorehttp_peer.py6
-rw-r--r--indra/llcrashlogger/llcrashlogger.cpp3
-rw-r--r--indra/llimage/llimage.cpp37
-rw-r--r--indra/llinventory/lleconomy.cpp25
-rw-r--r--indra/llinventory/lleconomy.h21
-rw-r--r--indra/llinventory/llfoldertype.cpp3
-rw-r--r--indra/llinventory/llinventorytype.cpp3
-rw-r--r--indra/llmath/llmath.h5
-rw-r--r--indra/llmath/llvolume.cpp27
-rw-r--r--indra/llmessage/llcoproceduremanager.h6
-rw-r--r--indra/llmessage/llcorehttputil.cpp2
-rw-r--r--indra/llmessage/llexperiencecache.h3
-rw-r--r--indra/llmessage/llproxy.h8
-rw-r--r--indra/llmessage/llxfer.cpp2
-rw-r--r--indra/llmessage/llxfer_file.cpp6
-rw-r--r--indra/llmessage/llxfermanager.cpp42
-rw-r--r--indra/llmessage/llxfermanager.h3
-rw-r--r--indra/llmessage/message.cpp9
-rw-r--r--indra/llmessage/message.h7
-rw-r--r--indra/llmessage/tests/llhttpclient_test.cpp3
-rw-r--r--indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp3
-rw-r--r--indra/llmessage/tests/lltrustedmessageservice_test.cpp3
-rw-r--r--indra/llmessage/tests/networkio.h3
-rwxr-xr-xindra/llmessage/tests/test_llsdmessage_peer.py6
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp3
-rw-r--r--indra/llplugin/llpluginclassmedia.h8
-rw-r--r--indra/llprimitive/lldaeloader.cpp17
-rw-r--r--indra/llprimitive/llmodel.cpp159
-rw-r--r--indra/llprimitive/llmodel.h1
-rw-r--r--indra/llrender/llfontgl.cpp7
-rw-r--r--indra/llrender/llimagegl.cpp19
-rw-r--r--indra/llrender/llimagegl.h2
-rw-r--r--indra/llrender/llrender.cpp11
-rw-r--r--indra/llrender/llvertexbuffer.cpp4
-rw-r--r--indra/llui/llclipboard.cpp10
-rw-r--r--indra/llui/llclipboard.h4
-rw-r--r--indra/llui/llcommandmanager.h6
-rw-r--r--indra/llui/llcontainerview.h4
-rw-r--r--indra/llui/llflatlistview.cpp114
-rw-r--r--indra/llui/llflatlistview.h11
-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/llfunctorregistry.h16
-rw-r--r--indra/llui/lllayoutstack.h4
-rw-r--r--indra/llui/lllineeditor.cpp25
-rw-r--r--indra/llui/lllineeditor.h7
-rw-r--r--indra/llui/llmenugl.h4
-rw-r--r--indra/llui/llnotifications.h4
-rw-r--r--indra/llui/llpanel.h3
-rw-r--r--indra/llui/llresmgr.h4
-rw-r--r--indra/llui/llscrollcontainer.h4
-rw-r--r--indra/llui/llspellcheck.h5
-rw-r--r--indra/llui/llspinctrl.cpp2
-rw-r--r--indra/llui/llstatview.h4
-rw-r--r--indra/llui/lltextbase.cpp76
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/lltextparser.h4
-rw-r--r--indra/llui/lltextvalidate.cpp9
-rw-r--r--indra/llui/lltextvalidate.h1
-rw-r--r--indra/llui/lltooltip.h3
-rw-r--r--indra/llui/llui.cpp5
-rw-r--r--indra/llui/llui.h89
-rw-r--r--indra/llui/lluicolortable.h3
-rw-r--r--indra/llui/lluictrl.h13
-rw-r--r--indra/llui/lluictrlfactory.h76
-rw-r--r--indra/llui/llurlentry.cpp19
-rw-r--r--indra/llui/llurlregistry.h7
-rw-r--r--indra/llui/llview.cpp24
-rw-r--r--indra/llui/llviewereventrecorder.h7
-rw-r--r--indra/llui/llviewquery.h6
-rw-r--r--indra/llui/llxuiparser.h12
-rwxr-xr-x[-rw-r--r--]indra/llui/tests/llurlentry_stub.cpp3
-rw-r--r--indra/llvfs/lldir.cpp7
-rw-r--r--indra/llvfs/llvfs.cpp11
-rw-r--r--indra/llvfs/llvfs.h1
-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/llwindowwin32.cpp144
-rw-r--r--indra/llwindow/llwindowwin32.h4
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp1
-rw-r--r--indra/media_plugins/cef/windows_volume_catcher.cpp9
-rw-r--r--indra/newview/CMakeLists.txt6
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/commands.xml10
-rw-r--r--indra/newview/app_settings/settings.xml145
-rw-r--r--indra/newview/app_settings/settings_per_account.xml19
-rw-r--r--indra/newview/llaccountingcostmanager.h4
-rw-r--r--indra/newview/llagent.cpp24
-rw-r--r--indra/newview/llagent.h2
-rw-r--r--indra/newview/llagentpicksinfo.h8
-rw-r--r--indra/newview/llagentwearables.cpp68
-rw-r--r--indra/newview/llagentwearables.h3
-rw-r--r--indra/newview/llappdelegate-objc.mm2
-rw-r--r--indra/newview/llappearancemgr.cpp21
-rw-r--r--indra/newview/llappearancemgr.h14
-rw-r--r--indra/newview/llappviewer.cpp148
-rw-r--r--indra/newview/llappviewer.h3
-rw-r--r--indra/newview/llappviewerwin32.cpp4
-rw-r--r--indra/newview/llattachmentsmgr.h6
-rw-r--r--indra/newview/llautoreplace.h3
-rw-r--r--indra/newview/llavataractions.cpp13
-rw-r--r--indra/newview/llavatariconctrl.h11
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h7
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.h6
-rw-r--r--indra/newview/llavatarrendernotifier.cpp223
-rw-r--r--indra/newview/llavatarrendernotifier.h66
-rw-r--r--indra/newview/llchannelmanager.h6
-rw-r--r--indra/newview/llchatbar.cpp5
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp26
-rw-r--r--indra/newview/llchicletbar.cpp2
-rw-r--r--indra/newview/llchicletbar.h5
-rw-r--r--indra/newview/llconversationlog.cpp7
-rw-r--r--indra/newview/llconversationlog.h3
-rw-r--r--indra/newview/lldaycyclemanager.h2
-rw-r--r--indra/newview/lldeferredsounds.h2
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.cpp3
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.h6
-rw-r--r--indra/newview/lldrawpoolalpha.cpp4
-rw-r--r--indra/newview/llenvmanager.cpp11
-rw-r--r--indra/newview/llenvmanager.h4
-rw-r--r--indra/newview/llestateinfomodel.h4
-rw-r--r--indra/newview/llexperiencelog.h3
-rw-r--r--indra/newview/llfacebookconnect.h5
-rw-r--r--indra/newview/llfasttimerview.cpp4
-rw-r--r--indra/newview/llfavoritesbar.h12
-rw-r--r--indra/newview/llfeaturemanager.h26
-rw-r--r--indra/newview/llfilteredwearablelist.cpp5
-rw-r--r--indra/newview/llfilteredwearablelist.h5
-rw-r--r--indra/newview/llflickrconnect.h5
-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/llfloaterbvhpreview.cpp2
-rw-r--r--indra/newview/llfloatergesture.cpp3
-rw-r--r--indra/newview/llfloaterimcontainer.cpp2
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp48
-rw-r--r--indra/newview/llfloaterimnearbychathandler.cpp10
-rw-r--r--indra/newview/llfloatermodelpreview.cpp38
-rw-r--r--indra/newview/llfloatermodelpreview.h3
-rw-r--r--indra/newview/llfloatermodeluploadbase.cpp1
-rw-r--r--indra/newview/llfloaternamedesc.cpp4
-rw-r--r--indra/newview/llfloateroutfitphotopreview.cpp289
-rw-r--r--indra/newview/llfloateroutfitphotopreview.h77
-rw-r--r--indra/newview/llfloaterpay.cpp146
-rw-r--r--indra/newview/llfloaterpreference.cpp10
-rw-r--r--indra/newview/llfloaterreporter.cpp108
-rw-r--r--indra/newview/llfloaterreporter.h9
-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.cpp5
-rw-r--r--indra/newview/llfriendcard.h5
-rw-r--r--indra/newview/llgesturemgr.h4
-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/llgroupmgr.h4
-rw-r--r--indra/newview/llhints.h1
-rw-r--r--indra/newview/llhudmanager.h4
-rw-r--r--indra/newview/llhudtext.cpp17
-rw-r--r--indra/newview/llimagefiltersmanager.h5
-rw-r--r--indra/newview/llimview.h6
-rw-r--r--indra/newview/llinspectgroup.cpp3
-rw-r--r--indra/newview/llinventorybridge.cpp41
-rw-r--r--indra/newview/llinventorybridge.h1
-rw-r--r--indra/newview/llinventoryfilter.cpp17
-rw-r--r--indra/newview/llinventoryicon.cpp3
-rw-r--r--indra/newview/llinventoryitemslist.cpp207
-rw-r--r--indra/newview/llinventoryitemslist.h28
-rw-r--r--indra/newview/llinventorymodel.cpp23
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.h4
-rw-r--r--indra/newview/llinventoryobserver.cpp25
-rw-r--r--indra/newview/llinventoryobserver.h4
-rw-r--r--indra/newview/lllocalbitmaps.cpp5
-rw-r--r--indra/newview/lllocationhistory.h2
-rw-r--r--indra/newview/lllocationinputctrl.cpp2
-rw-r--r--indra/newview/lllogchat.cpp24
-rw-r--r--indra/newview/lllogininstance.h6
-rw-r--r--indra/newview/llmainlooprepeater.h3
-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/llmarketplacefunctions.h13
-rw-r--r--indra/newview/llmaterialmgr.h4
-rw-r--r--indra/newview/llmediactrl.cpp6
-rw-r--r--indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp3
-rw-r--r--indra/newview/llmenuoptionpathfindingrebakenavmesh.h4
-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/llmutelist.cpp40
-rw-r--r--indra/newview/llmutelist.h9
-rwxr-xr-x[-rw-r--r--]indra/newview/llnavigationbar.h7
-rw-r--r--indra/newview/llnotificationmanager.h6
-rw-r--r--indra/newview/llnotificationofferhandler.cpp26
-rw-r--r--indra/newview/llnotificationstorage.cpp7
-rw-r--r--indra/newview/lloutfitgallery.cpp47
-rw-r--r--indra/newview/lloutfitgallery.h3
-rw-r--r--indra/newview/lloutfitobserver.h5
-rw-r--r--indra/newview/llpaneleditwearable.cpp3
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp2
-rw-r--r--indra/newview/llpanelmaininventory.cpp14
-rw-r--r--indra/newview/llpaneloutfitedit.cpp7
-rw-r--r--indra/newview/llpaneloutfitedit.h1
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp8
-rw-r--r--indra/newview/llpanelplaceprofile.cpp12
-rw-r--r--indra/newview/llpanelplaces.cpp41
-rw-r--r--indra/newview/llpanelprofile.cpp14
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp6
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp6
-rw-r--r--indra/newview/llpanelteleporthistory.cpp4
-rw-r--r--indra/newview/llpaneltopinfobar.h6
-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/llpathfindingmanager.cpp3
-rw-r--r--indra/newview/llpathfindingmanager.h6
-rw-r--r--indra/newview/llpathfindingpathtool.cpp1
-rw-r--r--indra/newview/llpathfindingpathtool.h6
-rw-r--r--indra/newview/llpersistentnotificationstorage.cpp5
-rw-r--r--indra/newview/llpersistentnotificationstorage.h4
-rw-r--r--indra/newview/llpresetsmanager.cpp7
-rw-r--r--indra/newview/llpresetsmanager.h6
-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/llproductinforequest.h3
-rw-r--r--indra/newview/llrecentpeople.h1
-rw-r--r--indra/newview/llregioninfomodel.h3
-rw-r--r--indra/newview/llremoteparcelrequest.h3
-rw-r--r--indra/newview/llrootview.h4
-rw-r--r--indra/newview/llscenemonitor.h4
-rw-r--r--indra/newview/llscreenchannel.cpp8
-rw-r--r--indra/newview/llscriptfloater.h1
-rw-r--r--indra/newview/llsearchhistory.h3
-rw-r--r--indra/newview/llselectmgr.cpp7
-rw-r--r--indra/newview/llselectmgr.h6
-rw-r--r--indra/newview/llsidepanelappearance.cpp2
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp8
-rw-r--r--indra/newview/llspeakers.h8
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp6
-rw-r--r--indra/newview/llstartup.cpp9
-rw-r--r--indra/newview/llstatusbar.cpp6
-rw-r--r--indra/newview/llstylemap.h1
-rw-r--r--indra/newview/llsyntaxid.h5
-rw-r--r--indra/newview/llsyswellwindow.h1
-rw-r--r--indra/newview/llteleporthistory.h5
-rw-r--r--indra/newview/llteleporthistorystorage.h5
-rw-r--r--indra/newview/lltextureatlasmanager.h5
-rw-r--r--indra/newview/lltexturecache.cpp173
-rw-r--r--indra/newview/lltexturectrl.cpp2
-rw-r--r--indra/newview/lltoolbrush.h2
-rw-r--r--indra/newview/lltoolcomp.cpp2
-rw-r--r--indra/newview/lltoolcomp.h28
-rw-r--r--indra/newview/lltooldraganddrop.h5
-rw-r--r--indra/newview/lltoolface.h4
-rw-r--r--indra/newview/lltoolfocus.cpp1
-rw-r--r--indra/newview/lltoolfocus.h4
-rw-r--r--indra/newview/lltoolgrab.cpp52
-rw-r--r--indra/newview/lltoolgrab.h21
-rw-r--r--indra/newview/lltoolindividual.h4
-rw-r--r--indra/newview/lltoolmgr.cpp2
-rw-r--r--indra/newview/lltoolmgr.h4
-rw-r--r--indra/newview/lltoolobjpicker.h2
-rw-r--r--indra/newview/lltoolpie.h2
-rw-r--r--indra/newview/lltoolpipette.h4
-rw-r--r--indra/newview/lltoolselectland.h4
-rw-r--r--indra/newview/lltransientfloatermgr.h4
-rw-r--r--indra/newview/lltwitterconnect.h4
-rw-r--r--indra/newview/llviewchildren.cpp5
-rw-r--r--indra/newview/llviewerassettype.cpp3
-rw-r--r--indra/newview/llviewerassetupload.cpp2
-rw-r--r--indra/newview/llvieweraudio.h6
-rw-r--r--indra/newview/llviewercamera.cpp10
-rw-r--r--indra/newview/llviewercamera.h6
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerfoldertype.cpp3
-rw-r--r--indra/newview/llviewerhelp.h2
-rw-r--r--indra/newview/llviewerinventory.cpp244
-rw-r--r--indra/newview/llviewerinventory.h2
-rw-r--r--indra/newview/llviewerjoystick.h6
-rw-r--r--indra/newview/llviewerkeyboard.cpp1
-rw-r--r--indra/newview/llviewermedia.cpp95
-rw-r--r--indra/newview/llviewermedia.h7
-rw-r--r--indra/newview/llviewermedia_streamingaudio.cpp3
-rw-r--r--indra/newview/llviewermediafocus.h6
-rw-r--r--indra/newview/llviewermenu.cpp15
-rw-r--r--indra/newview/llviewermenu.h3
-rw-r--r--indra/newview/llviewermenufile.cpp20
-rw-r--r--indra/newview/llviewermessage.cpp51
-rw-r--r--indra/newview/llviewermessage.h1
-rw-r--r--indra/newview/llviewernetwork.cpp37
-rw-r--r--indra/newview/llviewernetwork.h17
-rw-r--r--indra/newview/llviewerobject.cpp90
-rw-r--r--indra/newview/llviewerobject.h17
-rw-r--r--indra/newview/llviewerparcelmgr.h5
-rw-r--r--indra/newview/llviewerpartsim.h3
-rw-r--r--indra/newview/llviewerstats.h8
-rw-r--r--indra/newview/llviewerstatsrecorder.h6
-rw-r--r--indra/newview/llviewertexture.cpp4
-rw-r--r--indra/newview/llviewertexturelist.h1
-rw-r--r--indra/newview/llviewerwearable.cpp7
-rw-r--r--indra/newview/llviewerwearable.h2
-rw-r--r--indra/newview/llviewerwindow.cpp89
-rw-r--r--indra/newview/llviewerwindow.h9
-rw-r--r--indra/newview/llvoavatar.cpp90
-rw-r--r--indra/newview/llvocache.h8
-rw-r--r--indra/newview/llvoicechannel.h2
-rw-r--r--indra/newview/llvoiceclient.h10
-rw-r--r--indra/newview/llvoicevivox.h13
-rw-r--r--indra/newview/llvovolume.cpp21
-rw-r--r--indra/newview/llvovolume.h2
-rw-r--r--indra/newview/llwatchdog.h4
-rw-r--r--indra/newview/llwaterparammanager.h6
-rw-r--r--indra/newview/llwearableitemslist.cpp24
-rw-r--r--indra/newview/llwearableitemslist.h4
-rw-r--r--indra/newview/llwearablelist.h4
-rw-r--r--indra/newview/llwindebug.h1
-rw-r--r--indra/newview/llwlparammanager.h6
-rw-r--r--indra/newview/llworld.h2
-rw-r--r--indra/newview/llworldmap.h4
-rw-r--r--indra/newview/llworldmapmessage.h6
-rw-r--r--indra/newview/llxmlrpclistener.cpp2
-rw-r--r--indra/newview/pipeline.cpp12
-rw-r--r--indra/newview/pipeline.h2
-rw-r--r--indra/newview/skins/default/textures/textures.xml4
-rw-r--r--indra/newview/skins/default/textures/toolbar_icons/report_abuse.pngbin0 -> 407 bytes
-rw-r--r--indra/newview/skins/default/xui/da/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/de/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_camera.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_destinations.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_edit_hover_height.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_facebook.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_flickr.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_moveview.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml65
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay.xml24
-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_texture_ctrl.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_twitter.xml3
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml1
-rw-r--r--indra/newview/skins/default/xui/en/inspect_group.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_tab.xml7
-rw-r--r--indra/newview/skins/default/xui/en/mime_types.xml2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml253
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml5
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml13
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_gallery.xml3
-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.xml3
-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.xml13
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml3
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml39
-rw-r--r--indra/newview/skins/default/xui/en/widgets/slider.xml1
-rw-r--r--indra/newview/skins/default/xui/en/widgets/texture_picker.xml3
-rw-r--r--indra/newview/skins/default/xui/es/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/es/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/fr/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/it/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/it/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/ja/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/pl/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/pt/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/ru/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/tr/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/zh/strings.xml1
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp1
-rw-r--r--indra/newview/tests/llremoteparcelrequest_test.cpp3
-rw-r--r--indra/test/message_tut.cpp2
470 files changed, 7184 insertions, 8799 deletions
diff --git a/.hgtags b/.hgtags
index 44ca1e0d7d..c9870bfb0f 100755
--- a/.hgtags
+++ b/.hgtags
@@ -520,3 +520,4 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release
b280a1c797a3891e68dbc237e73de9cf19f426e9 4.1.1-release
+bfbba2244320dc2ae47758cd7edd8fa3b67dc756 4.1.2-release
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 2d49fb17c0..f485aa0cb7 100755..100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1484,11 +1484,11 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>db992d58c46c80df7d4d31f8a4784b98</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/317959/arch/Darwin/installer/llceflib-1.5.3.317959-darwin-317959.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,11 +1498,11 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>bb3818628131a99cd789febfad9dc2c2</string>
+ <string>1156121b4ccbb4aa29bc01f15c589f98</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/317959/arch/CYGWIN/installer/llceflib-1.5.3.317959-windows-317959.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/321153/arch/CYGWIN/installer/llceflib-1.5.3.321153-windows-321153.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -2657,14 +2657,6 @@
<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>
@@ -2703,20 +2695,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>-DUNATTENDED:BOOL=ON</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
<string>-DUSE_KDU=FALSE</string>
</array>
@@ -2745,14 +2728,6 @@
<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>
@@ -2789,20 +2764,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>-DUNATTENDED:BOOL=ON</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
<string>-DUSE_KDU=FALSE</string>
</array>
diff --git a/build.sh b/build.sh
index cd2a9ebf5e..ab7a1faa37 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\"" \
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 92534e2fd8..c206132d18 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -190,9 +190,26 @@ 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
+ MAINT-6773
+ MAINT-6906
+ MAINT-6911
+ MAINT-6917
+ STORM-2140
+ MAINT-6912
+ MAINT-6929
STORM-2141
Aralara Rajal
Arare Chantilly
@@ -791,6 +808,7 @@ Kitty Barnett
MAINT-6152
MAINT-6153
MAINT-6154
+ MAINT-6568
Kolor Fall
Komiko Okamoto
Korvel Noh
@@ -1022,6 +1040,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..adc134c48c 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -83,8 +83,8 @@ if (WINDOWS)
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)
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 3d27b4a5b5..f4dba16a94 100644
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -42,6 +42,7 @@
#include "lldiriterator.h"
#include "v4coloru.h"
#include "llsdserialize.h"
+#include "llcleanup.h"
// system libraries
#include <iostream>
@@ -634,7 +635,7 @@ int main(int argc, char** argv)
}
// Cleanup and exit
- LLImage::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLImage);
if (fast_timer_log_thread)
{
fast_timer_log_thread->shutdown();
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/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h
index 8a1d2c4707..d6223bb4d2 100644
--- a/indra/llappearance/llavatarappearancedefines.h
+++ b/indra/llappearance/llavatarappearancedefines.h
@@ -127,8 +127,7 @@ class LLAvatarAppearanceDictionary : public LLSingleton<LLAvatarAppearanceDictio
//--------------------------------------------------------------------
// Constructors and Destructors
//--------------------------------------------------------------------
-public:
- LLAvatarAppearanceDictionary();
+ LLSINGLETON(LLAvatarAppearanceDictionary);
virtual ~LLAvatarAppearanceDictionary();
private:
void createAssociations();
diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h
index 959d6e499a..9318b23fd1 100644
--- a/indra/llappearance/lltexlayer.h
+++ b/indra/llappearance/lltexlayer.h
@@ -293,9 +293,9 @@ protected:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList>
{
-public:
- LLTexLayerStaticImageList();
+ LLSINGLETON(LLTexLayerStaticImageList);
~LLTexLayerStaticImageList();
+public:
LLGLTexture* getTexture(const std::string& file_name, BOOL is_mask);
LLImageTGA* getImageTGA(const std::string& file_name);
void deleteCachedImages();
diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
index 87109a5906..207e0c4011 100644
--- a/indra/llappearance/llwearabletype.cpp
+++ b/indra/llappearance/llwearabletype.cpp
@@ -71,8 +71,7 @@ struct WearableEntry : public LLDictionaryEntry
class LLWearableDictionary : public LLSingleton<LLWearableDictionary>,
public LLDictionary<LLWearableType::EType, WearableEntry>
{
-public:
- LLWearableDictionary();
+ LLSINGLETON(LLWearableDictionary);
};
LLWearableDictionary::LLWearableDictionary()
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 410a5819b3..d9ab7c1b38 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -40,8 +40,10 @@ set(llcommon_SOURCE_FILES
llbase64.cpp
llbitpack.cpp
llcallbacklist.cpp
+ llcleanup.cpp
llcommon.cpp
llcommonutils.cpp
+ llcoro_get_id.cpp
llcoros.cpp
llcrc.cpp
llcriticaldamp.cpp
@@ -66,7 +68,9 @@ set(llcommon_SOURCE_FILES
llformat.cpp
llframetimer.cpp
llheartbeat.cpp
+ llheteromap.cpp
llinitparam.cpp
+ llinitdestroyclass.cpp
llinstancetracker.cpp
llleap.cpp
llleaplistener.cpp
@@ -135,8 +139,10 @@ set(llcommon_HEADER_FILES
llbitpack.h
llboost.h
llcallbacklist.h
+ llcleanup.h
llcommon.h
llcommonutils.h
+ llcoro_get_id.h
llcoros.h
llcrc.h
llcriticaldamp.h
@@ -168,7 +174,9 @@ set(llcommon_HEADER_FILES
llhandle.h
llhash.h
llheartbeat.h
+ llheteromap.h
llindexedvector.h
+ llinitdestroyclass.h
llinitparam.h
llinstancetracker.h
llkeythrottle.h
@@ -185,6 +193,7 @@ set(llcommon_HEADER_FILES
llmortician.h
llnametable.h
llpointer.h
+ llpounceable.h
llpredicate.h
llpreprocessor.h
llpriqueuemap.h
@@ -329,6 +338,8 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llpounceable "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llheteromap "" "${test_libs}")
## 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
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index eb0699ad41..2c76f29020 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -48,6 +48,7 @@
#include "lleventtimer.h"
#include "google_breakpad/exception_handler.h"
#include "stringize.h"
+#include "llcleanup.h"
//
// Signal handling
@@ -177,7 +178,7 @@ LLApp::~LLApp()
if(mExceptionHandler != 0) delete mExceptionHandler;
- LLCommon::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLCommon);
}
// static
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/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 5ae2df3994..4304db36be 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -63,8 +63,7 @@ struct AssetEntry : public LLDictionaryEntry
class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
public LLDictionary<LLAssetType::EType, AssetEntry>
{
-public:
- LLAssetDictionary();
+ LLSINGLETON(LLAssetDictionary);
};
LLAssetDictionary::LLAssetDictionary()
diff --git a/indra/llcommon/llcleanup.cpp b/indra/llcommon/llcleanup.cpp
new file mode 100644
index 0000000000..c5283507bf
--- /dev/null
+++ b/indra/llcommon/llcleanup.cpp
@@ -0,0 +1,29 @@
+/**
+ * @file llcleanup.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-30
+ * @brief Implementation for llcleanup.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llcleanup.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llerror.h"
+#include "llerrorcontrol.h"
+
+void log_subsystem_cleanup(const char* file, int line, const char* function,
+ const char* classname)
+{
+ LL_INFOS("Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): "
+ << "calling " << classname << "::cleanupClass() in "
+ << function << LL_ENDL;
+}
diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h
new file mode 100644
index 0000000000..a319171b5f
--- /dev/null
+++ b/indra/llcommon/llcleanup.h
@@ -0,0 +1,33 @@
+/**
+ * @file llcleanup.h
+ * @author Nat Goodspeed
+ * @date 2015-05-20
+ * @brief Mechanism for cleaning up subsystem resources
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCLEANUP_H)
+#define LL_LLCLEANUP_H
+
+#include <boost/current_function.hpp>
+
+// Instead of directly calling SomeClass::cleanupClass(), use
+// SUBSYSTEM_CLEANUP(SomeClass);
+// This logs the call as well as performing it. That gives us a baseline
+// subsystem shutdown order against which to compare subsequent dynamic
+// shutdown schemes.
+#define SUBSYSTEM_CLEANUP(CLASSNAME) \
+ do { \
+ log_subsystem_cleanup(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \
+ CLASSNAME::cleanupClass(); \
+ } while (0)
+// Use ancient do { ... } while (0) macro trick to permit a block of
+// statements with the same syntax as a single statement.
+
+void log_subsystem_cleanup(const char* file, int line, const char* function,
+ const char* classname);
+
+#endif /* ! defined(LL_LLCLEANUP_H) */
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 19642b0982..439ff4e628 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -31,6 +31,7 @@
#include "llthread.h"
#include "lltrace.h"
#include "lltracethreadrecorder.h"
+#include "llcleanup.h"
//static
BOOL LLCommon::sAprInitialized = FALSE;
@@ -63,11 +64,11 @@ void LLCommon::cleanupClass()
sMasterThreadRecorder = NULL;
LLTrace::set_master_thread_recorder(NULL);
LLThreadSafeRefCount::cleanupThreadSafeRefCount();
- LLTimer::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLTimer);
if (sAprInitialized)
{
ll_cleanup_apr();
sAprInitialized = FALSE;
}
- LLMemory::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLMemory);
}
diff --git a/indra/llcommon/llcoro_get_id.cpp b/indra/llcommon/llcoro_get_id.cpp
new file mode 100644
index 0000000000..24ed1fe0c9
--- /dev/null
+++ b/indra/llcommon/llcoro_get_id.cpp
@@ -0,0 +1,32 @@
+/**
+ * @file llcoro_get_id.cpp
+ * @author Nat Goodspeed
+ * @date 2016-09-03
+ * @brief Implementation for llcoro_get_id.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llcoro_get_id.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llcoros.h"
+
+namespace llcoro
+{
+
+id get_id()
+{
+ // An instance of Current can convert to LLCoros::CoroData*, which can
+ // implicitly convert to void*, which is an llcoro::id.
+ return LLCoros::Current();
+}
+
+} // llcoro
diff --git a/indra/llcommon/llcoro_get_id.h b/indra/llcommon/llcoro_get_id.h
new file mode 100644
index 0000000000..4c1dca6f19
--- /dev/null
+++ b/indra/llcommon/llcoro_get_id.h
@@ -0,0 +1,30 @@
+/**
+ * @file llcoro_get_id.h
+ * @author Nat Goodspeed
+ * @date 2016-09-03
+ * @brief Supplement the functionality in llcoro.h.
+ *
+ * This is broken out as a separate header file to resolve
+ * circularity: LLCoros isa LLSingleton, yet LLSingleton machinery
+ * requires llcoro::get_id().
+ *
+ * Be very suspicious of anyone else #including this header.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCORO_GET_ID_H)
+#define LL_LLCORO_GET_ID_H
+
+namespace llcoro
+{
+
+/// Get an opaque, distinct token for the running coroutine (or main).
+typedef void* id;
+id get_id();
+
+} // llcoro
+
+#endif /* ! defined(LL_LLCORO_GET_ID_H) */
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 8e516d8beb..3ffce4810a 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -40,32 +40,79 @@
#include "stringize.h"
#include "llexception.h"
-// do nothing, when we need nothing done
+namespace {
+void no_op() {}
+} // anonymous namespace
+
+// Do nothing, when we need nothing done. This is a static member of LLCoros
+// because CoroData is a private nested class.
void LLCoros::no_cleanup(CoroData*) {}
// CoroData for the currently-running coroutine. Use a thread_specific_ptr
// because each thread potentially has its own distinct pool of coroutines.
-// This thread_specific_ptr does NOT own the CoroData object! That's owned by
-// LLCoros::mCoros. It merely identifies it. For this reason we instantiate
-// it with a no-op cleanup function.
-boost::thread_specific_ptr<LLCoros::CoroData>
-LLCoros::sCurrentCoro(LLCoros::no_cleanup);
+LLCoros::Current::Current()
+{
+ // Use a function-static instance so this thread_specific_ptr is
+ // instantiated on demand. Since we happen to know it's consumed by
+ // LLSingleton, this is likely to happen before the runtime has finished
+ // initializing module-static data. For the same reason, we can't package
+ // this pointer in an LLSingleton.
+
+ // This thread_specific_ptr does NOT own the CoroData object! That's owned
+ // by LLCoros::mCoros. It merely identifies it. For this reason we
+ // instantiate it with a no-op cleanup function.
+ static boost::thread_specific_ptr<LLCoros::CoroData> sCurrent(LLCoros::no_cleanup);
+
+ // If this is the first time we're accessing sCurrent for the running
+ // thread, its get() will be NULL. This could be a problem, in that
+ // llcoro::get_id() would return the same (NULL) token value for the "main
+ // coroutine" in every thread, whereas what we really want is a distinct
+ // value for every distinct stack in the process. So if get() is NULL,
+ // give it a heap CoroData: this ensures that llcoro::get_id() will return
+ // distinct values.
+ // This tactic is "leaky": sCurrent explicitly does not destroy any
+ // CoroData to which it points, and we do NOT enter these "main coroutine"
+ // CoroData instances in the LLCoros::mCoros map. They are dummy entries,
+ // and they will leak at process shutdown: one CoroData per thread.
+ if (! sCurrent.get())
+ {
+ // It's tempting to provide a distinct name for each thread's "main
+ // coroutine." But as getName() has always returned the empty string
+ // to mean "not in a coroutine," empty string should suffice here --
+ // and truthfully the additional (thread-safe!) machinery to ensure
+ // uniqueness just doesn't feel worth the trouble.
+ // We use a no-op callable and a minimal stack size because, although
+ // CoroData's constructor in fact initializes its mCoro with a
+ // coroutine with that stack size, no one ever actually enters it by
+ // calling mCoro().
+ sCurrent.reset(new CoroData(0, // no prev
+ "", // not a named coroutine
+ no_op, // no-op callable
+ 1024)); // stacksize moot
+ }
+
+ mCurrent = &sCurrent;
+}
//static
LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller)
{
- CoroData* current = sCurrentCoro.get();
- if (! current)
- {
- LL_ERRS("LLCoros") << "Calling " << caller << " from non-coroutine context!" << LL_ENDL;
- }
+ CoroData* current = Current();
+ // With the dummy CoroData set in LLCoros::Current::Current(), this
+ // pointer should never be NULL.
+ llassert_always(current);
return *current;
}
//static
LLCoros::coro::self& LLCoros::get_self()
{
- return *get_CoroData("get_self()").mSelf;
+ CoroData& current = get_CoroData("get_self()");
+ if (! current.mSelf)
+ {
+ LL_ERRS("LLCoros") << "Calling get_self() from non-coroutine context!" << LL_ENDL;
+ }
+ return *current.mSelf;
}
//static
@@ -80,20 +127,23 @@ bool LLCoros::get_consuming()
return get_CoroData("get_consuming()").mConsuming;
}
-llcoro::Suspending::Suspending():
- mSuspended(LLCoros::sCurrentCoro.get())
+llcoro::Suspending::Suspending()
{
- // Revert mCurrentCoro to the value it had at the moment we last switched
+ LLCoros::Current current;
+ // Remember currently-running coroutine: we're about to suspend it.
+ mSuspended = current;
+ // Revert Current to the value it had at the moment we last switched
// into this coroutine.
- LLCoros::sCurrentCoro.reset(mSuspended->mPrev);
+ current.reset(mSuspended->mPrev);
}
llcoro::Suspending::~Suspending()
{
+ LLCoros::Current current;
// Okay, we're back, update our mPrev
- mSuspended->mPrev = LLCoros::sCurrentCoro.get();
- // and reinstate our sCurrentCoro.
- LLCoros::sCurrentCoro.reset(mSuspended);
+ mSuspended->mPrev = current;
+ // and reinstate our Current.
+ current.reset(mSuspended);
}
LLCoros::LLCoros():
@@ -213,13 +263,7 @@ bool LLCoros::kill(const std::string& name)
std::string LLCoros::getName() const
{
- CoroData* current = sCurrentCoro.get();
- if (! current)
- {
- // not in a coroutine
- return "";
- }
- return current->mName;
+ return Current()->mName;
}
void LLCoros::setStackSize(S32 stacksize)
@@ -229,8 +273,8 @@ void LLCoros::setStackSize(S32 stacksize)
}
// Top-level wrapper around caller's coroutine callable. This function accepts
-// the coroutine library's implicit coro::self& parameter and sets sCurrentSelf
-// but does not pass it down to the caller's callable.
+// the coroutine library's implicit coro::self& parameter and saves it, but
+// does not pass it down to the caller's callable.
void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& callable)
{
// capture the 'self' param in CoroData
@@ -254,8 +298,8 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
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);
+ // data->mPrev, but this is our last chance to reset Current.
+ Current().reset(data->mPrev);
}
/*****************************************************************************
@@ -278,7 +322,7 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name,
mPrev(prev),
mName(name),
// Wrap the caller's callable in our toplevel() function so we can manage
- // sCurrentCoro appropriately at startup and shutdown of each coroutine.
+ // Current appropriately at startup and shutdown of each coroutine.
mCoro(boost::bind(toplevel, _1, this, callable), stacksize),
// don't consume events unless specifically directed
mConsuming(false),
@@ -289,13 +333,13 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name,
std::string LLCoros::launch(const std::string& prefix, const callable_t& callable)
{
std::string name(generateDistinctName(prefix));
- // pass the current value of sCurrentCoro as previous context
- CoroData* newCoro = new CoroData(sCurrentCoro.get(), name,
- callable, mStackSize);
+ Current current;
+ // pass the current value of Current as previous context
+ CoroData* newCoro = new CoroData(current, name, callable, mStackSize);
// Store it in our pointer map
mCoros.insert(name, newCoro);
// also set it as current
- sCurrentCoro.reset(newCoro);
+ current.reset(newCoro);
/* Run the coroutine until its first wait, then return here */
(newCoro->mCoro)(std::nothrow);
return name;
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 39316ed0e6..bbe2d22af4 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -35,8 +35,10 @@
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/function.hpp>
#include <boost/thread/tss.hpp>
+#include <boost/noncopyable.hpp>
#include <string>
#include <stdexcept>
+#include "llcoro_get_id.h" // for friend declaration
// forward-declare helper class
namespace llcoro
@@ -83,6 +85,7 @@ class Suspending;
*/
class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
{
+ LLSINGLETON(LLCoros);
public:
/// Canonical boost::dcoroutines::coroutine signature we use
typedef boost::dcoroutines::coroutine<void()> coro;
@@ -173,9 +176,8 @@ public:
class Future;
private:
- LLCoros();
- friend class LLSingleton<LLCoros>;
friend class llcoro::Suspending;
+ friend llcoro::id llcoro::get_id();
std::string generateDistinctName(const std::string& prefix) const;
bool cleanup(const LLSD&);
struct CoroData;
@@ -222,8 +224,22 @@ private:
typedef boost::ptr_map<std::string, CoroData> CoroMap;
CoroMap mCoros;
- // identify the current coroutine's CoroData
- static boost::thread_specific_ptr<LLCoros::CoroData> sCurrentCoro;
+ // Identify the current coroutine's CoroData. Use a little helper class so
+ // a caller can either use a temporary instance, or instantiate a named
+ // variable and access it multiple times.
+ class Current
+ {
+ public:
+ Current();
+
+ operator LLCoros::CoroData*() { return get(); }
+ LLCoros::CoroData* operator->() { return get(); }
+ LLCoros::CoroData* get() { return mCurrent->get(); }
+ void reset(LLCoros::CoroData* ptr) { mCurrent->reset(ptr); }
+
+ private:
+ boost::thread_specific_ptr<LLCoros::CoroData>* mCurrent;
+ };
};
namespace llcoro
@@ -231,7 +247,7 @@ namespace llcoro
/// Instantiate one of these in a block surrounding any leaf point when
/// control literally switches away from this coroutine.
-class Suspending
+class Suspending: boost::noncopyable
{
public:
Suspending();
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 5ed348e13c..229442cec1 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -239,6 +239,14 @@ namespace
{
std::string className(const std::type_info& type)
{
+ return LLError::Log::demangle(type.name());
+ }
+} // anonymous
+
+namespace LLError
+{
+ std::string Log::demangle(const char* mangled)
+ {
#ifdef __GNUC__
// GCC: type_info::name() returns a mangled class name,st demangle
@@ -252,31 +260,34 @@ namespace
// but gcc 3.3 libstc++'s implementation of demangling is broken
// and fails without.
- char* name = abi::__cxa_demangle(type.name(),
+ char* name = abi::__cxa_demangle(mangled,
abi_name_buf, &abi_name_len, &status);
// this call can realloc the abi_name_buf pointer (!)
- return name ? name : type.name();
+ return name ? name : mangled;
#elif LL_WINDOWS
// DevStudio: type_info::name() includes the text "class " at the start
static const std::string class_prefix = "class ";
-
- std::string name = type.name();
- std::string::size_type p = name.find(class_prefix);
- if (p == std::string::npos)
+ std::string name = mangled;
+ if (0 != name.compare(0, class_prefix.length(), class_prefix))
{
+ LL_DEBUGS() << "Did not see '" << class_prefix << "' prefix on '"
+ << name << "'" << LL_ENDL;
return name;
}
- return name.substr(p + class_prefix.size());
+ return name.substr(class_prefix.length());
-#else
- return type.name();
+#else
+ return mangled;
#endif
}
+} // LLError
+namespace
+{
std::string functionName(const std::string& preprocessor_name)
{
#if LL_WINDOWS
@@ -363,9 +374,8 @@ namespace
class Globals : public LLSingleton<Globals>
{
+ LLSINGLETON(Globals);
public:
- Globals();
-
std::ostringstream messageStream;
bool messageStreamInUse;
@@ -438,11 +448,10 @@ namespace LLError
class Settings : public LLSingleton<Settings>
{
+ LLSINGLETON(Settings);
public:
- Settings();
-
SettingsConfigPtr getSettingsConfig();
-
+
void reset();
SettingsStoragePtr saveAndReset();
void restore(SettingsStoragePtr pSettingsStorage);
@@ -450,7 +459,7 @@ namespace LLError
private:
SettingsConfigPtr mSettingsConfig;
};
-
+
SettingsConfig::SettingsConfig()
: LLRefCount(),
mPrintLocation(false),
@@ -475,8 +484,7 @@ namespace LLError
mRecorders.clear();
}
- Settings::Settings()
- : LLSingleton<Settings>(),
+ Settings::Settings():
mSettingsConfig(new SettingsConfig())
{
}
@@ -485,26 +493,31 @@ namespace LLError
{
return mSettingsConfig;
}
-
+
void Settings::reset()
{
Globals::getInstance()->invalidateCallSites();
mSettingsConfig = new SettingsConfig();
}
-
+
SettingsStoragePtr Settings::saveAndReset()
{
SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
reset();
return oldSettingsConfig;
}
-
+
void Settings::restore(SettingsStoragePtr pSettingsStorage)
{
Globals::getInstance()->invalidateCallSites();
SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
mSettingsConfig = newSettingsConfig;
}
+
+ bool is_available()
+ {
+ return Settings::instanceExists() && Globals::instanceExists();
+ }
}
namespace LLError
@@ -921,11 +934,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 +941,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 7cbe4334b3..ce4d4552df 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -190,6 +190,7 @@ namespace LLError
static std::ostringstream* out();
static void flush(std::ostringstream* out, char* message);
static void flush(std::ostringstream*, const CallSite&);
+ static std::string demangle(const char* mangled);
};
struct LL_COMMON_API CallSite
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 56ac52e5de..56e84f7172 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -189,6 +189,11 @@ namespace LLError
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
LL_COMMON_API int shouldLogCallCount();
+
+ // Check whether Globals exists. This should only be used by LLSingleton
+ // infrastructure to avoid trying to log when our internal LLSingleton is
+ // unavailable -- circularity ensues.
+ LL_COMMON_API bool is_available();
};
#endif // LL_LLERRORCONTROL_H
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 19d700a3b0..97270e4931 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -276,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
@@ -314,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())
+ 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
{
+ // 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())
+ {
LLTHROW(DupListenerName("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);
+ }
+ // 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);
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)
- {
- // Remember the iterator belonging to our new node, and which
- // placement value was 'previous' at that point.
- mydmi = dmi;
- myprev = previous;
- continue;
}
- // 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)
+ // 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)
{
- // 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)
+ // 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;
+ }
}
- }
- // NOW remove the offending listener node.
- mDeps.remove(name);
- // Having constructed a description of the order change, inform caller.
+ 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()));
+ }
+ // 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;
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 1526128725..7cff7dfd45 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -229,7 +229,7 @@ class LLEventPump;
*/
class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
{
- friend class LLSingleton<LLEventPumps>;
+ LLSINGLETON(LLEventPumps);
public:
/**
* Find or create an LLEventPump instance with a specific name. We return
@@ -272,7 +272,6 @@ private:
void unregister(const LLEventPump&);
private:
- LLEventPumps();
~LLEventPumps();
testable:
@@ -385,6 +384,8 @@ 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
@@ -496,6 +497,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/llfile.cpp b/indra/llcommon/llfile.cpp
index 873a7bce25..7b559861bb 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -239,7 +239,7 @@ int LLFile::close(LLFILE * file)
}
-int LLFile::remove(const std::string& filename)
+int LLFile::remove(const std::string& filename, int supress_error)
{
#if LL_WINDOWS
std::string utf8filename = filename;
@@ -248,7 +248,7 @@ int LLFile::remove(const std::string& filename)
#else
int rc = ::remove(filename.c_str());
#endif
- return warnif("remove", filename, rc);
+ return warnif("remove", filename, rc, supress_error);
}
int LLFile::rename(const std::string& filename, const std::string& newname)
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 3e25228aeb..d8f84daf2b 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -72,7 +72,7 @@ public:
static int mkdir(const std::string& filename, int perms = 0700);
static int rmdir(const std::string& filename);
- static int remove(const std::string& filename);
+ static int remove(const std::string& filename, int supress_error = 0);
static int rename(const std::string& filename,const std::string& newname);
static bool copy(const std::string from, const std::string to);
diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp
new file mode 100644
index 0000000000..7c19196e0c
--- /dev/null
+++ b/indra/llcommon/llheteromap.cpp
@@ -0,0 +1,32 @@
+/**
+ * @file llheteromap.cpp
+ * @author Nat Goodspeed
+ * @date 2016-10-12
+ * @brief Implementation for llheteromap.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llheteromap.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+
+LLHeteroMap::~LLHeteroMap()
+{
+ // For each entry in our map, we must call its deleter, which is the only
+ // record we have of its original type.
+ for (TypeMap::iterator mi(mMap.begin()), me(mMap.end()); mi != me; ++mi)
+ {
+ // mi->second is the std::pair; mi->second.first is the void*;
+ // mi->second.second points to the deleter function
+ (mi->second.second)(mi->second.first);
+ mi->second.first = NULL;
+ }
+}
diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h
new file mode 100644
index 0000000000..9d6f303d08
--- /dev/null
+++ b/indra/llcommon/llheteromap.h
@@ -0,0 +1,95 @@
+/**
+ * @file llheteromap.h
+ * @author Nat Goodspeed
+ * @date 2016-10-12
+ * @brief Map capable of storing objects of diverse types, looked up by type.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLHETEROMAP_H)
+#define LL_LLHETEROMAP_H
+
+#include <typeinfo>
+#include <utility> // std::pair
+#include <map>
+
+/**
+ * LLHeteroMap addresses an odd requirement. Usually when you want to put
+ * objects of different classes into a runtime collection of any kind, you
+ * derive them all from a common base class and store pointers to that common
+ * base class.
+ *
+ * LLInitParam::BaseBlock uses disturbing raw-pointer arithmetic to find data
+ * members in its subclasses. It seems that no BaseBlock subclass can be
+ * stored in a polymorphic class of any kind: the presence of a vtbl pointer
+ * in the layout silently throws off the reinterpret_cast arithmetic. Bad
+ * Things result. (Many thanks to Nicky D for this analysis!)
+ *
+ * LLHeteroMap collects objects WITHOUT a common base class, retrieves them by
+ * object type and destroys them when the LLHeteroMap is destroyed.
+ */
+class LLHeteroMap
+{
+public:
+ ~LLHeteroMap();
+
+ /// find or create
+ template <class T>
+ T& obtain()
+ {
+ // Look up map entry by typeid(T). We don't simply use mMap[typeid(T)]
+ // because that requires default-constructing T on every lookup. For
+ // some kinds of T, that could be expensive.
+ TypeMap::iterator found = mMap.find(&typeid(T));
+ if (found == mMap.end())
+ {
+ // Didn't find typeid(T). Create an entry. Because we're storing
+ // only a void* in the map, discarding type information, make sure
+ // we capture that type information in our deleter.
+ void* ptr = new T();
+ void (*dlfn)(void*) = &deleter<T>;
+ std::pair<TypeMap::iterator, bool> inserted =
+ mMap.insert(TypeMap::value_type(&typeid(T),
+ TypeMap::mapped_type(ptr, dlfn)));
+ // Okay, now that we have an entry, claim we found it.
+ found = inserted.first;
+ }
+ // found->second is the std::pair; second.first is the void*
+ // pointer to the object in question. Cast it to correct type and
+ // dereference it.
+ return *(static_cast<T*>(found->second.first));
+ }
+
+private:
+ template <class T>
+ static
+ void deleter(void* p)
+ {
+ delete static_cast<T*>(p);
+ }
+
+ // Comparing two std::type_info* values is tricky, because the standard
+ // does not guarantee that there will be only one type_info instance for a
+ // given type. In other words, &typeid(A) in one part of the program may
+ // not always equal &typeid(A) in some other part. Use special comparator.
+ struct type_info_ptr_comp
+ {
+ bool operator()(const std::type_info* lhs, const std::type_info* rhs)
+ {
+ return lhs->before(*rhs);
+ }
+ };
+
+ // What we actually store is a map from std::type_info (permitting lookup
+ // by object type) to a void* pointer to the object PLUS its deleter.
+ typedef std::map<
+ const std::type_info*, std::pair<void*, void (*)(void*)>,
+ type_info_ptr_comp>
+ TypeMap;
+ TypeMap mMap;
+};
+
+#endif /* ! defined(LL_LLHETEROMAP_H) */
diff --git a/indra/llcommon/llinitdestroyclass.cpp b/indra/llcommon/llinitdestroyclass.cpp
new file mode 100644
index 0000000000..e6382a7924
--- /dev/null
+++ b/indra/llcommon/llinitdestroyclass.cpp
@@ -0,0 +1,30 @@
+/**
+ * @file llinitdestroyclass.cpp
+ * @author Nat Goodspeed
+ * @date 2016-08-30
+ * @brief Implementation for llinitdestroyclass.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llinitdestroyclass.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llerror.h"
+
+void LLCallbackRegistry::fireCallbacks() const
+{
+ for (FuncList::const_iterator fi = mCallbacks.begin(), fe = mCallbacks.end();
+ fi != fe; ++fi)
+ {
+ LL_INFOS("LLInitDestroyClass") << "calling " << fi->first << "()" << LL_ENDL;
+ fi->second();
+ }
+}
diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h
new file mode 100644
index 0000000000..5f979614fe
--- /dev/null
+++ b/indra/llcommon/llinitdestroyclass.h
@@ -0,0 +1,175 @@
+/**
+ * @file llinitdestroyclass.h
+ * @author Nat Goodspeed
+ * @date 2015-05-27
+ * @brief LLInitClass / LLDestroyClass mechanism
+ *
+ * The LLInitClass template, extracted from llui.h, ensures that control will
+ * reach a static initClass() method. LLDestroyClass does the same for a
+ * static destroyClass() method.
+ *
+ * The distinguishing characteristics of these templates are:
+ *
+ * - All LLInitClass<T>::initClass() methods are triggered by an explicit call
+ * to LLInitClassList::instance().fireCallbacks(). Presumably this call
+ * happens sometime after all static objects in the program have been
+ * initialized. In other words, each LLInitClass<T>::initClass() method
+ * should be able to make some assumptions about global program state.
+ *
+ * - Similarly, LLDestroyClass<T>::destroyClass() methods are triggered by
+ * LLDestroyClassList::instance().fireCallbacks(). Again, presumably this
+ * happens at a well-defined moment in the program's shutdown sequence.
+ *
+ * - The initClass() calls happen in an unspecified sequence. You may not rely
+ * on the relative ordering of LLInitClass<T>::initClass() versus another
+ * LLInitClass<U>::initClass() method. If you need such a guarantee, use
+ * LLSingleton instead and make the dependency explicit.
+ *
+ * - Similarly, LLDestroyClass<T>::destroyClass() may happen either before or
+ * after LLDestroyClass<U>::destroyClass(). You cannot rely on that order.
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLINITDESTROYCLASS_H)
+#define LL_LLINITDESTROYCLASS_H
+
+#include "llsingleton.h"
+#include <boost/function.hpp>
+#include <typeinfo>
+#include <vector>
+#include <utility> // std::pair
+
+/**
+ * LLCallbackRegistry is an implementation detail base class for
+ * LLInitClassList and LLDestroyClassList. It accumulates the initClass() or
+ * destroyClass() callbacks for registered classes.
+ */
+class LLCallbackRegistry
+{
+public:
+ typedef boost::function<void()> func_t;
+
+ void registerCallback(const std::string& name, const func_t& func)
+ {
+ mCallbacks.push_back(FuncList::value_type(name, func));
+ }
+
+ void fireCallbacks() const;
+
+private:
+ // Arguably this should be a boost::signals2::signal, which is, after all,
+ // a sequence of callables. We manage it by hand so we can log a name for
+ // each registered function we call.
+ typedef std::vector< std::pair<std::string, func_t> > FuncList;
+ FuncList mCallbacks;
+};
+
+/**
+ * LLInitClassList is the LLCallbackRegistry for LLInitClass. It stores the
+ * registered initClass() methods. It must be an LLSingleton because
+ * LLInitClass registers its initClass() method at static construction time
+ * (before main()), requiring LLInitClassList to be fully constructed on
+ * demand regardless of module initialization order.
+ */
+class LLInitClassList :
+ public LLCallbackRegistry,
+ public LLSingleton<LLInitClassList>
+{
+ LLSINGLETON_EMPTY_CTOR(LLInitClassList);
+};
+
+/**
+ * LLDestroyClassList is the LLCallbackRegistry for LLDestroyClass. It stores
+ * the registered destroyClass() methods. It must be an LLSingleton because
+ * LLDestroyClass registers its destroyClass() method at static construction
+ * time (before main()), requiring LLDestroyClassList to be fully constructed
+ * on demand regardless of module initialization order.
+ */
+class LLDestroyClassList :
+ public LLCallbackRegistry,
+ public LLSingleton<LLDestroyClassList>
+{
+ LLSINGLETON_EMPTY_CTOR(LLDestroyClassList);
+};
+
+/**
+ * LLRegisterWith is an implementation detail for LLInitClass and
+ * LLDestroyClass. It is intended to be used as a static class member whose
+ * constructor registers the specified callback with the LLMumbleClassList
+ * singleton registry specified as the template argument.
+ */
+template<typename T>
+class LLRegisterWith
+{
+public:
+ LLRegisterWith(const std::string& name, const LLCallbackRegistry::func_t& func)
+ {
+ T::instance().registerCallback(name, func);
+ }
+
+ // this avoids a MSVC bug where non-referenced static members are "optimized" away
+ // even if their constructors have side effects
+ S32 reference()
+ {
+ S32 dummy;
+ dummy = 0;
+ return dummy;
+ }
+};
+
+/**
+ * Derive MyClass from LLInitClass<MyClass> (the Curiously Recurring Template
+ * Pattern) to ensure that the static method MyClass::initClass() will be
+ * called (along with all other LLInitClass<T> subclass initClass() methods)
+ * when someone calls LLInitClassList::instance().fireCallbacks(). This gives
+ * the application specific control over the timing of all such
+ * initializations, without having to insert calls for every such class into
+ * generic application code.
+ */
+template<typename T>
+class LLInitClass
+{
+public:
+ LLInitClass() { sRegister.reference(); }
+
+ // When this static member is initialized, the subclass initClass() method
+ // is registered on LLInitClassList. See sRegister definition below.
+ static LLRegisterWith<LLInitClassList> sRegister;
+};
+
+/**
+ * Derive MyClass from LLDestroyClass<MyClass> (the Curiously Recurring
+ * Template Pattern) to ensure that the static method MyClass::destroyClass()
+ * will be called (along with other LLDestroyClass<T> subclass destroyClass()
+ * methods) when someone calls LLDestroyClassList::instance().fireCallbacks().
+ * This gives the application specific control over the timing of all such
+ * cleanup calls, without having to insert calls for every such class into
+ * generic application code.
+ */
+template<typename T>
+class LLDestroyClass
+{
+public:
+ LLDestroyClass() { sRegister.reference(); }
+
+ // When this static member is initialized, the subclass destroyClass()
+ // method is registered on LLInitClassList. See sRegister definition
+ // below.
+ static LLRegisterWith<LLDestroyClassList> sRegister;
+};
+
+// Here's where LLInitClass<T> specifies the subclass initClass() method.
+template <typename T>
+LLRegisterWith<LLInitClassList>
+LLInitClass<T>::sRegister(std::string(typeid(T).name()) + "::initClass",
+ &T::initClass);
+// Here's where LLDestroyClass<T> specifies the subclass destroyClass() method.
+template <typename T>
+LLRegisterWith<LLDestroyClassList>
+LLDestroyClass<T>::sRegister(std::string(typeid(T).name()) + "::destroyClass",
+ &T::destroyClass);
+
+#endif /* ! defined(LL_LLINITDESTROYCLASS_H) */
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index aa2f4eb289..1d104cf55d 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -193,7 +193,12 @@ namespace LLInitParam
{
if (!silent)
{
- p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
+ std::string file_name = p.getCurrentFileName();
+ if(!file_name.empty())
+ {
+ file_name = "in file: " + file_name;
+ }
+ p.parserWarning(llformat("Failed to parse parameter \"%s\" %s", p.getCurrentElementName().c_str(), file_name.c_str()));
}
return false;
}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index c65b05f610..f1f4226c40 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -551,6 +551,7 @@ namespace LLInitParam
}
virtual std::string getCurrentElementName() = 0;
+ virtual std::string getCurrentFileName() = 0;
virtual void parserWarning(const std::string& message);
virtual void parserError(const std::string& message);
void setParseSilently(bool silent) { mParseSilently = silent; }
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 1fc821d9a9..16fc365da1 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -40,7 +40,7 @@
LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;
/*static*/
-void LLMetricPerformanceTesterBasic::cleanClass()
+void LLMetricPerformanceTesterBasic::cleanupClass()
{
for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
{
diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h
index 1a18cdf36f..e6b46be1cf 100644
--- a/indra/llcommon/llmetricperformancetester.h
+++ b/indra/llcommon/llmetricperformancetester.h
@@ -156,7 +156,7 @@ public:
/**
* @brief Delete all testers and reset the tester map
*/
- static void cleanClass() ;
+ static void cleanupClass() ;
private:
// Add a tester to the map. Returns false if adding fails.
diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h
new file mode 100644
index 0000000000..0421ce966a
--- /dev/null
+++ b/indra/llcommon/llpounceable.h
@@ -0,0 +1,216 @@
+/**
+ * @file llpounceable.h
+ * @author Nat Goodspeed
+ * @date 2015-05-22
+ * @brief LLPounceable is tangentially related to a future: it's a holder for
+ * a value that may or may not exist yet. Unlike a future, though,
+ * LLPounceable freely allows reading the held value. (If the held
+ * type T does not have a distinguished "empty" value, consider using
+ * LLPounceable<boost::optional<T>>.)
+ *
+ * LLPounceable::callWhenReady() is this template's claim to fame. It
+ * allows its caller to "pounce" on the held value as soon as it
+ * becomes non-empty. Call callWhenReady() with any C++ callable
+ * accepting T. If the held value is already non-empty, callWhenReady()
+ * will immediately call the callable with the held value. If the held
+ * value is empty, though, callWhenReady() will enqueue the callable
+ * for later. As soon as LLPounceable is assigned a non-empty held
+ * value, it will flush the queue of deferred callables.
+ *
+ * Consider a global LLMessageSystem* gMessageSystem. Message system
+ * initialization happens at a very specific point during viewer
+ * initialization. Other subsystems want to register callbacks on the
+ * LLMessageSystem instance as soon as it's initialized, but their own
+ * initialization may precede that. If we define gMessageSystem to be
+ * an LLPounceable<LLMessageSystem*>, a subsystem can use
+ * callWhenReady() to either register immediately (if gMessageSystem
+ * is already up and runnning) or register as soon as gMessageSystem
+ * is set with a new, initialized instance.
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLPOUNCEABLE_H)
+#define LL_LLPOUNCEABLE_H
+
+#include "llsingleton.h"
+#include <boost/noncopyable.hpp>
+#include <boost/call_traits.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/utility/value_init.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/signals2/signal.hpp>
+
+// Forward declare the user template, since we want to be able to point to it
+// in some of its implementation classes.
+template <typename T, class TAG>
+class LLPounceable;
+
+template <typename T, typename TAG>
+struct LLPounceableTraits
+{
+ // Our "queue" is a signal object with correct signature.
+ typedef boost::signals2::signal<void (typename boost::call_traits<T>::param_type)> signal_t;
+ // Call callWhenReady() with any callable accepting T.
+ typedef typename signal_t::slot_type func_t;
+ // owner pointer type
+ typedef LLPounceable<T, TAG>* owner_ptr;
+};
+
+// Tag types distinguish the two different implementations of LLPounceable's
+// queue.
+struct LLPounceableQueue {};
+struct LLPounceableStatic {};
+
+// generic LLPounceableQueueImpl deliberately omitted: only the above tags are
+// legal
+template <typename T, class TAG>
+class LLPounceableQueueImpl;
+
+// The implementation selected by LLPounceableStatic uses an LLSingleton
+// because we can't count on a data member queue being initialized at the time
+// we start getting callWhenReady() calls. This is that LLSingleton.
+template <typename T>
+class LLPounceableQueueSingleton:
+ public LLSingleton<LLPounceableQueueSingleton<T> >
+{
+ LLSINGLETON_EMPTY_CTOR(LLPounceableQueueSingleton);
+
+ typedef LLPounceableTraits<T, LLPounceableStatic> traits;
+ typedef typename traits::owner_ptr owner_ptr;
+ typedef typename traits::signal_t signal_t;
+
+ // For a given held type T, every LLPounceable<T, LLPounceableStatic>
+ // instance will call on the SAME LLPounceableQueueSingleton instance --
+ // given how class statics work. We must keep a separate queue for each
+ // LLPounceable instance. Use a hash map for that.
+ typedef boost::unordered_map<owner_ptr, signal_t> map_t;
+
+public:
+ // Disambiguate queues belonging to different LLPounceables.
+ signal_t& get(owner_ptr owner)
+ {
+ // operator[] has find-or-create semantics -- just what we want!
+ return mMap[owner];
+ }
+
+private:
+ map_t mMap;
+};
+
+// LLPounceableQueueImpl that uses the above LLSingleton
+template <typename T>
+class LLPounceableQueueImpl<T, LLPounceableStatic>
+{
+public:
+ typedef LLPounceableTraits<T, LLPounceableStatic> traits;
+ typedef typename traits::owner_ptr owner_ptr;
+ typedef typename traits::signal_t signal_t;
+
+ signal_t& get(owner_ptr owner) const
+ {
+ // this Impl contains nothing; it delegates to the Singleton
+ return LLPounceableQueueSingleton<T>::instance().get(owner);
+ }
+};
+
+// The implementation selected by LLPounceableQueue directly contains the
+// queue of interest, suitable for an LLPounceable we can trust to be fully
+// initialized when it starts getting callWhenReady() calls.
+template <typename T>
+class LLPounceableQueueImpl<T, LLPounceableQueue>
+{
+public:
+ typedef LLPounceableTraits<T, LLPounceableQueue> traits;
+ typedef typename traits::owner_ptr owner_ptr;
+ typedef typename traits::signal_t signal_t;
+
+ signal_t& get(owner_ptr)
+ {
+ return mQueue;
+ }
+
+private:
+ signal_t mQueue;
+};
+
+// LLPounceable<T> is for an LLPounceable instance on the heap or the stack.
+// LLPounceable<T, LLPounceableStatic> is for a static LLPounceable instance.
+template <typename T, class TAG=LLPounceableQueue>
+class LLPounceable: public boost::noncopyable
+{
+private:
+ typedef LLPounceableTraits<T, TAG> traits;
+ typedef typename traits::owner_ptr owner_ptr;
+ typedef typename traits::signal_t signal_t;
+
+public:
+ typedef typename traits::func_t func_t;
+
+ // By default, both the initial value and the distinguished empty value
+ // are a default-constructed T instance. However you can explicitly
+ // specify each.
+ LLPounceable(typename boost::call_traits<T>::value_type init =boost::value_initialized<T>(),
+ typename boost::call_traits<T>::param_type empty=boost::value_initialized<T>()):
+ mHeld(init),
+ mEmpty(empty)
+ {}
+
+ // make read access to mHeld as cheap and transparent as possible
+ operator T () const { return mHeld; }
+ typename boost::remove_pointer<T>::type operator*() const { return *mHeld; }
+ typename boost::call_traits<T>::value_type operator->() const { return mHeld; }
+ // uncomment 'explicit' as soon as we allow C++11 compilation
+ /*explicit*/ operator bool() const { return bool(mHeld); }
+ bool operator!() const { return ! mHeld; }
+
+ // support both assignment (dumb ptr idiom) and reset() (smart ptr)
+ void operator=(typename boost::call_traits<T>::param_type value)
+ {
+ reset(value);
+ }
+
+ void reset(typename boost::call_traits<T>::param_type value)
+ {
+ mHeld = value;
+ // If this new value is non-empty, flush anything pending in the queue.
+ if (mHeld != mEmpty)
+ {
+ signal_t& signal(get_signal());
+ signal(mHeld);
+ signal.disconnect_all_slots();
+ }
+ }
+
+ // our claim to fame
+ void callWhenReady(const func_t& func)
+ {
+ if (mHeld != mEmpty)
+ {
+ // If the held value is already non-empty, immediately call func()
+ func(mHeld);
+ }
+ else
+ {
+ // Held value still empty, queue func() for later. By default,
+ // connect() enqueues slots in FIFO order.
+ get_signal().connect(func);
+ }
+ }
+
+private:
+ signal_t& get_signal() { return mQueue.get(this); }
+
+ // Store both the current and the empty value.
+ // MAYBE: Might be useful to delegate to LLPounceableTraits the meaning of
+ // testing for "empty." For some types we want operator!(); for others we
+ // want to compare to a distinguished value.
+ typename boost::call_traits<T>::value_type mHeld, mEmpty;
+ // This might either contain the queue (LLPounceableQueue) or delegate to
+ // an LLSingleton (LLPounceableStatic).
+ LLPounceableQueueImpl<T, TAG> mQueue;
+};
+
+#endif /* ! defined(LL_LLPOUNCEABLE_H) */
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index 29950c108d..750fe9fdc8 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -247,7 +247,10 @@ class LLRegistrySingleton
: public LLRegistry<KEY, VALUE, COMPARATOR>,
public LLSingleton<DERIVED_TYPE>
{
- friend class LLSingleton<DERIVED_TYPE>;
+ // This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton)
+ // because the concrete class is actually DERIVED_TYPE, not
+ // LLRegistrySingleton. So each concrete subclass needs
+ // LLSINGLETON(whatever) -- not this intermediate base class.
public:
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
typedef const KEY& ref_const_key_t;
@@ -269,7 +272,7 @@ public:
~ScopedRegistrar()
{
- if (!singleton_t::destroyed())
+ if (singleton_t::instanceExists())
{
popScope();
}
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 09f1bdf1e3..93910b70ae 100644
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -66,6 +66,7 @@ public:
}
/*virtual*/ std::string getCurrentElementName();
+ /*virtual*/ std::string getCurrentFileName(){ return LLStringUtil::null; }
private:
void writeSDImpl(LLSD& sd,
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index d49ff0feb5..81ba8631c6 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -1200,6 +1200,7 @@ bool LLSDBinaryParser::parseString(
read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
S32 size = (S32)ntohl(value_nbo);
if(mCheckLimits && (size > mMaxBytesLeft)) return false;
+ if(size < 0) return false;
std::vector<char> buf;
if(size)
{
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index 9b49e52377..9025e53bb2 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -25,7 +25,445 @@
*/
#include "linden_common.h"
-
#include "llsingleton.h"
+#include "llerror.h"
+#include "llerrorcontrol.h" // LLError::is_available()
+#include "lldependencies.h"
+#include "llcoro_get_id.h"
+#include <boost/foreach.hpp>
+#include <boost/unordered_map.hpp>
+#include <algorithm>
+#include <iostream> // std::cerr in dire emergency
+#include <sstream>
+#include <stdexcept>
+
+namespace {
+void log(LLError::ELevel level,
+ const char* p1, const char* p2, const char* p3, const char* p4);
+
+void logdebugs(const char* p1="", const char* p2="", const char* p3="", const char* p4="");
+
+bool oktolog();
+} // anonymous namespace
+
+// Our master list of all LLSingletons is itself an LLSingleton. We used to
+// store it in a function-local static, but that could get destroyed before
+// the last of the LLSingletons -- and ~LLSingletonBase() definitely wants to
+// remove itself from the master list. Since the whole point of this master
+// list is to help track inter-LLSingleton dependencies, and since we have
+// this implicit dependency from every LLSingleton to the master list, make it
+// an LLSingleton.
+class LLSingletonBase::MasterList:
+ public LLSingleton<LLSingletonBase::MasterList>
+{
+ LLSINGLETON_EMPTY_CTOR(MasterList);
+
+public:
+ // No need to make this private with accessors; nobody outside this source
+ // file can see it.
+
+ // This is the master list of all instantiated LLSingletons (save the
+ // MasterList itself) in arbitrary order. You MUST call dep_sort() before
+ // traversing this list.
+ LLSingletonBase::list_t mMaster;
+
+ // We need to maintain a stack of LLSingletons currently being
+ // initialized, either in the constructor or in initSingleton(). However,
+ // managing that as a stack depends on having a DISTINCT 'initializing'
+ // stack for every C++ stack in the process! And we have a distinct C++
+ // stack for every running coroutine. It would be interesting and cool to
+ // implement a generic coroutine-local-storage mechanism and use that
+ // here. The trouble is that LLCoros is itself an LLSingleton, so
+ // depending on LLCoros functionality could dig us into infinite
+ // recursion. (Moreover, when we reimplement LLCoros on top of
+ // Boost.Fiber, that library already provides fiber_specific_ptr -- so
+ // it's not worth a great deal of time and energy implementing a generic
+ // equivalent on top of boost::dcoroutine, which is on its way out.)
+ // Instead, use a map of llcoro::id to select the appropriate
+ // coro-specific 'initializing' stack. llcoro::get_id() is carefully
+ // implemented to avoid requiring LLCoros.
+ typedef boost::unordered_map<llcoro::id, LLSingletonBase::list_t> InitializingMap;
+ InitializingMap mInitializing;
+
+ // non-static method, cf. LLSingletonBase::get_initializing()
+ list_t& get_initializing_()
+ {
+ // map::operator[] has find-or-create semantics, exactly what we need
+ // here. It returns a reference to the selected mapped_type instance.
+ return mInitializing[llcoro::get_id()];
+ }
+
+ void cleanup_initializing_()
+ {
+ InitializingMap::iterator found = mInitializing.find(llcoro::get_id());
+ if (found != mInitializing.end())
+ {
+ mInitializing.erase(found);
+ }
+ }
+};
+
+//static
+LLSingletonBase::list_t& LLSingletonBase::get_master()
+{
+ return LLSingletonBase::MasterList::instance().mMaster;
+}
+
+void LLSingletonBase::add_master()
+{
+ // As each new LLSingleton is constructed, add to the master list.
+ get_master().push_back(this);
+}
+
+void LLSingletonBase::remove_master()
+{
+ // When an LLSingleton is destroyed, remove from master list.
+ // add_master() used to capture the iterator to the newly-added list item
+ // so we could directly erase() it from the master list. Unfortunately
+ // that runs afoul of destruction-dependency order problems. So search the
+ // master list, and remove this item IF FOUND. We have few enough
+ // LLSingletons, and they are so rarely destroyed (once per run), that the
+ // cost of a linear search should not be an issue.
+ get_master().remove(this);
+}
+
+//static
+LLSingletonBase::list_t& LLSingletonBase::get_initializing()
+{
+ return LLSingletonBase::MasterList::instance().get_initializing_();
+}
+
+//static
+LLSingletonBase::list_t& LLSingletonBase::get_initializing_from(MasterList* master)
+{
+ return master->get_initializing_();
+}
+
+LLSingletonBase::~LLSingletonBase() {}
+
+void LLSingletonBase::push_initializing(const char* name)
+{
+ // log BEFORE pushing so logging singletons don't cry circularity
+ log_initializing("Pushing", name);
+ get_initializing().push_back(this);
+}
+
+void LLSingletonBase::pop_initializing()
+{
+ list_t& list(get_initializing());
+
+ if (list.empty())
+ {
+ logerrs("Underflow in stack of currently-initializing LLSingletons at ",
+ demangle(typeid(*this).name()).c_str(), "::getInstance()");
+ }
+
+ // Now we know list.back() exists: capture it
+ LLSingletonBase* back(list.back());
+ // and pop it
+ list.pop_back();
+
+ // The viewer launches an open-ended number of coroutines. While we don't
+ // expect most of them to initialize LLSingleton instances, our present
+ // get_initializing() logic could lead to an open-ended number of map
+ // entries. So every time we pop the stack back to empty, delete the entry
+ // entirely.
+ if (list.empty())
+ {
+ MasterList::instance().cleanup_initializing_();
+ }
+
+ // Now validate the newly-popped LLSingleton.
+ if (back != this)
+ {
+ logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ",
+ demangle(typeid(*this).name()).c_str(), "::getInstance() trying to pop ",
+ demangle(typeid(*back).name()).c_str());
+ }
+
+ // log AFTER popping so logging singletons don't cry circularity
+ log_initializing("Popping", typeid(*back).name());
+}
+
+//static
+void LLSingletonBase::log_initializing(const char* verb, const char* name)
+{
+ if (oktolog())
+ {
+ LL_DEBUGS("LLSingleton") << verb << ' ' << demangle(name) << ';';
+ list_t& list(get_initializing());
+ for (list_t::const_reverse_iterator ri(list.rbegin()), rend(list.rend());
+ ri != rend; ++ri)
+ {
+ LLSingletonBase* sb(*ri);
+ LL_CONT << ' ' << demangle(typeid(*sb).name());
+ }
+ LL_ENDL;
+ }
+}
+
+void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initState)
+{
+ // Did this getInstance() call come from another LLSingleton, or from
+ // vanilla application code? Note that although this is a nontrivial
+ // method, the vast majority of its calls arrive here with initializing
+ // empty().
+ if (! initializing.empty())
+ {
+ // getInstance() is being called by some other LLSingleton. But -- is
+ // this a circularity? That is, does 'this' already appear in the
+ // initializing stack?
+ // For what it's worth, normally 'initializing' should contain very
+ // few elements.
+ list_t::const_iterator found =
+ std::find(initializing.begin(), initializing.end(), this);
+ if (found != initializing.end())
+ {
+ // Report the circularity. Requiring the coder to dig through the
+ // logic to diagnose exactly how we got here is less than helpful.
+ std::ostringstream out;
+ for ( ; found != initializing.end(); ++found)
+ {
+ // 'found' is an iterator; *found is an LLSingletonBase*; **found
+ // is the actual LLSingletonBase instance.
+ LLSingletonBase* foundp(*found);
+ out << demangle(typeid(*foundp).name()) << " -> ";
+ }
+ // We promise to capture dependencies from both the constructor
+ // and the initSingleton() method, so an LLSingleton's instance
+ // pointer is on the initializing list during both. Now that we've
+ // detected circularity, though, we must distinguish the two. If
+ // the recursive call is from the constructor, we CAN'T honor it:
+ // otherwise we'd be returning a pointer to a partially-
+ // constructed object! But from initSingleton() is okay: that
+ // method exists specifically to support circularity.
+ // Decide which log helper to call based on initState. They have
+ // identical signatures.
+ ((initState == CONSTRUCTING)? logerrs : logwarns)
+ ("LLSingleton circularity: ", out.str().c_str(),
+ demangle(typeid(*this).name()).c_str(), "");
+ }
+ else
+ {
+ // Here 'this' is NOT already in the 'initializing' stack. Great!
+ // Record the dependency.
+ // initializing.back() is the LLSingletonBase* currently being
+ // initialized. Store 'this' in its mDepends set.
+ LLSingletonBase* current(initializing.back());
+ if (current->mDepends.insert(this).second)
+ {
+ // only log the FIRST time we hit this dependency!
+ logdebugs(demangle(typeid(*current).name()).c_str(),
+ " depends on ", demangle(typeid(*this).name()).c_str());
+ }
+ }
+ }
+}
+
+//static
+LLSingletonBase::vec_t LLSingletonBase::dep_sort()
+{
+ // While it would theoretically be possible to maintain a static
+ // SingletonDeps through the life of the program, dynamically adding and
+ // removing LLSingletons as they are created and destroyed, in practice
+ // it's less messy to construct it on demand. The overhead of doing so
+ // should happen basically twice: once for cleanupAll(), once for
+ // deleteAll().
+ typedef LLDependencies<LLSingletonBase*> SingletonDeps;
+ SingletonDeps sdeps;
+ list_t& master(get_master());
+ BOOST_FOREACH(LLSingletonBase* sp, master)
+ {
+ // Build the SingletonDeps structure by adding, for each
+ // LLSingletonBase* sp in the master list, sp itself. It has no
+ // associated value type in our SingletonDeps, hence the 0. We don't
+ // record the LLSingletons it must follow; rather, we record the ones
+ // it must precede. Copy its mDepends to a KeyList to express that.
+ sdeps.add(sp, 0,
+ SingletonDeps::KeyList(),
+ SingletonDeps::KeyList(sp->mDepends.begin(), sp->mDepends.end()));
+ }
+ vec_t ret;
+ ret.reserve(master.size());
+ // We should be able to effect this with a transform_iterator that
+ // extracts just the first (key) element from each sorted_iterator, then
+ // uses vec_t's range constructor... but frankly this is more
+ // straightforward, as long as we remember the above reserve() call!
+ BOOST_FOREACH(SingletonDeps::sorted_iterator::value_type pair, sdeps.sort())
+ {
+ ret.push_back(pair.first);
+ }
+ // The master list is not itself pushed onto the master list. Add it as
+ // the very last entry -- it is the LLSingleton on which ALL others
+ // depend! -- so our caller will process it.
+ ret.push_back(MasterList::getInstance());
+ return ret;
+}
+
+//static
+void LLSingletonBase::cleanupAll()
+{
+ // It's essential to traverse these in dependency order.
+ BOOST_FOREACH(LLSingletonBase* sp, dep_sort())
+ {
+ // Call cleanupSingleton() only if we haven't already done so for this
+ // instance.
+ if (! sp->mCleaned)
+ {
+ sp->mCleaned = true;
+
+ logdebugs("calling ",
+ demangle(typeid(*sp).name()).c_str(), "::cleanupSingleton()");
+ try
+ {
+ sp->cleanupSingleton();
+ }
+ catch (const std::exception& e)
+ {
+ logwarns("Exception in ", demangle(typeid(*sp).name()).c_str(),
+ "::cleanupSingleton(): ", e.what());
+ }
+ catch (...)
+ {
+ logwarns("Unknown exception in ", demangle(typeid(*sp).name()).c_str(),
+ "::cleanupSingleton()");
+ }
+ }
+ }
+}
+
+//static
+void LLSingletonBase::deleteAll()
+{
+ // It's essential to traverse these in dependency order.
+ BOOST_FOREACH(LLSingletonBase* sp, dep_sort())
+ {
+ // Capture the class name first: in case of exception, don't count on
+ // being able to extract it later.
+ const std::string name = demangle(typeid(*sp).name());
+ try
+ {
+ // Call static method through instance function pointer.
+ if (! sp->mDeleteSingleton)
+ {
+ // This Should Not Happen... but carry on.
+ logwarns(name.c_str(), "::mDeleteSingleton not initialized!");
+ }
+ else
+ {
+ // properly initialized: call it.
+ logdebugs("calling ", name.c_str(), "::deleteSingleton()");
+ // From this point on, DO NOT DEREFERENCE sp!
+ sp->mDeleteSingleton();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ logwarns("Exception in ", name.c_str(), "::deleteSingleton(): ", e.what());
+ }
+ catch (...)
+ {
+ logwarns("Unknown exception in ", name.c_str(), "::deleteSingleton()");
+ }
+ }
+}
+
+/*------------------------ Final cleanup management ------------------------*/
+class LLSingletonBase::MasterRefcount
+{
+public:
+ // store a POD int so it will be statically initialized to 0
+ int refcount;
+};
+static LLSingletonBase::MasterRefcount sMasterRefcount;
+
+LLSingletonBase::ref_ptr_t LLSingletonBase::get_master_refcount()
+{
+ // Calling this method constructs a new ref_ptr_t, which implicitly calls
+ // intrusive_ptr_add_ref(MasterRefcount*).
+ return &sMasterRefcount;
+}
+
+void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount* mrc)
+{
+ // Count outstanding SingletonLifetimeManager instances.
+ ++mrc->refcount;
+}
+
+void intrusive_ptr_release(LLSingletonBase::MasterRefcount* mrc)
+{
+ // Notice when each SingletonLifetimeManager instance is destroyed.
+ if (! --mrc->refcount)
+ {
+ // The last instance was destroyed. Time to kill any remaining
+ // LLSingletons -- but in dependency order.
+ LLSingletonBase::deleteAll();
+ }
+}
+
+/*---------------------------- Logging helpers -----------------------------*/
+namespace {
+bool oktolog()
+{
+ // See comments in log() below.
+ return sMasterRefcount.refcount && LLError::is_available();
+}
+
+void log(LLError::ELevel level,
+ const char* p1, const char* p2, const char* p3, const char* p4)
+{
+ // Check whether we're in the implicit final LLSingletonBase::deleteAll()
+ // call. We've carefully arranged for deleteAll() to be called when the
+ // last SingletonLifetimeManager instance is destroyed -- in other words,
+ // when the last translation unit containing an LLSingleton instance
+ // cleans up static data. That could happen after std::cerr is destroyed!
+ // The is_available() test below ensures that we'll stop logging once
+ // LLError has been cleaned up. If we had a similar portable test for
+ // std::cerr, this would be a good place to use it. As we do not, just
+ // don't log anything during implicit final deleteAll(). Detect that by
+ // the master refcount having gone to zero.
+ if (sMasterRefcount.refcount == 0)
+ return;
+
+ // Check LLError::is_available() because some of LLError's infrastructure
+ // is itself an LLSingleton. If that LLSingleton has not yet been
+ // initialized, trying to log will engage LLSingleton machinery... and
+ // around and around we go.
+ if (LLError::is_available())
+ {
+ LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL;
+ }
+ else
+ {
+ // Caller may be a test program, or something else whose stderr is
+ // visible to the user.
+ std::cerr << p1 << p2 << p3 << p4 << std::endl;
+ }
+}
+
+void logdebugs(const char* p1, const char* p2, const char* p3, const char* p4)
+{
+ log(LLError::LEVEL_DEBUG, p1, p2, p3, p4);
+}
+} // anonymous namespace
+
+//static
+void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, const char* p4)
+{
+ log(LLError::LEVEL_WARN, p1, p2, p3, p4);
+}
+
+//static
+void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4)
+{
+ log(LLError::LEVEL_ERROR, p1, p2, p3, p4);
+ // The other important side effect of LL_ERRS() is
+ // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
+ LLError::crashAndLoop(std::string());
+}
+std::string LLSingletonBase::demangle(const char* mangled)
+{
+ return LLError::Log::demangle(mangled);
+}
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 6e6291a165..1b915dfd6e 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -25,188 +25,495 @@
#ifndef LLSINGLETON_H
#define LLSINGLETON_H
-#include "llerror.h" // *TODO: eliminate this
-
-#include <typeinfo>
#include <boost/noncopyable.hpp>
+#include <boost/unordered_set.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <list>
+#include <vector>
+#include <typeinfo>
+
+class LLSingletonBase: private boost::noncopyable
+{
+public:
+ class MasterList;
+ class MasterRefcount;
+ typedef boost::intrusive_ptr<MasterRefcount> ref_ptr_t;
+
+private:
+ // All existing LLSingleton instances are tracked in this master list.
+ typedef std::list<LLSingletonBase*> list_t;
+ static list_t& get_master();
+ // This, on the other hand, is a stack whose top indicates the LLSingleton
+ // currently being initialized.
+ static list_t& get_initializing();
+ static list_t& get_initializing_from(MasterList*);
+ // Produce a vector<LLSingletonBase*> of master list, in dependency order.
+ typedef std::vector<LLSingletonBase*> vec_t;
+ static vec_t dep_sort();
+
+ bool mCleaned; // cleanupSingleton() has been called
+ // we directly depend on these other LLSingletons
+ typedef boost::unordered_set<LLSingletonBase*> set_t;
+ set_t mDepends;
+
+protected:
+ typedef enum e_init_state
+ {
+ UNINITIALIZED = 0, // must be default-initialized state
+ CONSTRUCTING,
+ INITIALIZING,
+ INITIALIZED,
+ DELETED
+ } EInitState;
+
+ // Define tag<T> to pass to our template constructor. You can't explicitly
+ // invoke a template constructor with ordinary template syntax:
+ // http://stackoverflow.com/a/3960925/5533635
+ template <typename T>
+ struct tag
+ {
+ typedef T type;
+ };
+
+ // Base-class constructor should only be invoked by the DERIVED_TYPE
+ // constructor, which passes tag<DERIVED_TYPE> for various purposes.
+ template <typename DERIVED_TYPE>
+ LLSingletonBase(tag<DERIVED_TYPE>);
+ virtual ~LLSingletonBase();
+
+ // Every new LLSingleton should be added to/removed from the master list
+ void add_master();
+ void remove_master();
+ // with a little help from our friends.
+ template <class T> friend struct LLSingleton_manage_master;
+
+ // Maintain a stack of the LLSingleton subclass instance currently being
+ // initialized. We use this to notice direct dependencies: we want to know
+ // if A requires B. We deduce a dependency if while initializing A,
+ // control reaches B::getInstance().
+ // We want &A to be at the top of that stack during both A::A() and
+ // A::initSingleton(), since a call to B::getInstance() might occur during
+ // either.
+ // Unfortunately the desired timespan does not correspond neatly with a
+ // single C++ scope, else we'd use RAII to track it. But we do know that
+ // LLSingletonBase's constructor definitely runs just before
+ // LLSingleton's, which runs just before the specific subclass's.
+ void push_initializing(const char*);
+ // LLSingleton is, and must remain, the only caller to initSingleton().
+ // That being the case, we control exactly when it happens -- and we can
+ // pop the stack immediately thereafter.
+ void pop_initializing();
+private:
+ // logging
+ static void log_initializing(const char* verb, const char* name);
+protected:
+ // If a given call to B::getInstance() happens during either A::A() or
+ // A::initSingleton(), record that A directly depends on B.
+ void capture_dependency(list_t& initializing, EInitState);
+
+ // delegate LL_ERRS() logging to llsingleton.cpp
+ static void logerrs(const char* p1, const char* p2="",
+ const char* p3="", const char* p4="");
+ // delegate LL_WARNS() logging to llsingleton.cpp
+ static void logwarns(const char* p1, const char* p2="",
+ const char* p3="", const char* p4="");
+ static std::string demangle(const char* mangled);
+
+ // obtain canonical ref_ptr_t
+ static ref_ptr_t get_master_refcount();
+
+ // Default methods in case subclass doesn't declare them.
+ virtual void initSingleton() {}
+ virtual void cleanupSingleton() {}
+
+ // deleteSingleton() isn't -- and shouldn't be -- a virtual method. It's a
+ // class static. However, given only Foo*, deleteAll() does need to be
+ // able to reach Foo::deleteSingleton(). Make LLSingleton (which declares
+ // deleteSingleton()) store a pointer here. Since we know it's a static
+ // class method, a classic-C function pointer will do.
+ void (*mDeleteSingleton)();
+
+public:
+ /**
+ * Call this to call the cleanupSingleton() method for every LLSingleton
+ * constructed since the start of the last cleanupAll() call. (Any
+ * LLSingleton constructed DURING a cleanupAll() call won't be cleaned up
+ * until the next cleanupAll() call.) cleanupSingleton() neither deletes
+ * nor destroys its LLSingleton; therefore it's safe to include logic that
+ * might take significant realtime or even throw an exception.
+ *
+ * The most important property of cleanupAll() is that cleanupSingleton()
+ * methods are called in dependency order, leaf classes last. Thus, given
+ * two LLSingleton subclasses A and B, if A's dependency on B is properly
+ * expressed as a B::getInstance() or B::instance() call during either
+ * A::A() or A::initSingleton(), B will be cleaned up after A.
+ *
+ * If a cleanupSingleton() method throws an exception, the exception is
+ * logged, but cleanupAll() attempts to continue calling the rest of the
+ * cleanupSingleton() methods.
+ */
+ static void cleanupAll();
+ /**
+ * Call this to call the deleteSingleton() method for every LLSingleton
+ * constructed since the start of the last deleteAll() call. (Any
+ * LLSingleton constructed DURING a deleteAll() call won't be cleaned up
+ * until the next deleteAll() call.) deleteSingleton() deletes and
+ * destroys its LLSingleton. Any cleanup logic that might take significant
+ * realtime -- or throw an exception -- must not be placed in your
+ * LLSingleton's destructor, but rather in its cleanupSingleton() method.
+ *
+ * The most important property of deleteAll() is that deleteSingleton()
+ * methods are called in dependency order, leaf classes last. Thus, given
+ * two LLSingleton subclasses A and B, if A's dependency on B is properly
+ * expressed as a B::getInstance() or B::instance() call during either
+ * A::A() or A::initSingleton(), B will be cleaned up after A.
+ *
+ * If a deleteSingleton() method throws an exception, the exception is
+ * logged, but deleteAll() attempts to continue calling the rest of the
+ * deleteSingleton() methods.
+ */
+ static void deleteAll();
+};
+
+// support ref_ptr_t
+void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount*);
+void intrusive_ptr_release(LLSingletonBase::MasterRefcount*);
-// LLSingleton implements the getInstance() method part of the Singleton
-// pattern. It can't make the derived class constructors protected, though, so
-// you have to do that yourself.
-//
-// There are two ways to use LLSingleton. The first way is to inherit from it
-// while using the typename that you'd like to be static as the template
-// parameter, like so:
-//
-// class Foo: public LLSingleton<Foo>{};
-//
-// Foo& instance = Foo::instance();
-//
-// The second way is to use the singleton class directly, without inheritance:
-//
-// typedef LLSingleton<Foo> FooSingleton;
-//
-// Foo& instance = FooSingleton::instance();
-//
-// In this case, the class being managed as a singleton needs to provide an
-// initSingleton() method since the LLSingleton virtual method won't be
-// available
-//
-// As currently written, it is not thread-safe.
+// Most of the time, we want LLSingleton_manage_master() to forward its
+// methods to real LLSingletonBase methods.
+template <class T>
+struct LLSingleton_manage_master
+{
+ void add(LLSingletonBase* sb) { sb->add_master(); }
+ void remove(LLSingletonBase* sb) { sb->remove_master(); }
+ void push_initializing(LLSingletonBase* sb) { sb->push_initializing(typeid(T).name()); }
+ void pop_initializing (LLSingletonBase* sb) { sb->pop_initializing(); }
+ LLSingletonBase::list_t& get_initializing(T*) { return LLSingletonBase::get_initializing(); }
+};
+// But for the specific case of LLSingletonBase::MasterList, don't.
+template <>
+struct LLSingleton_manage_master<LLSingletonBase::MasterList>
+{
+ void add(LLSingletonBase*) {}
+ void remove(LLSingletonBase*) {}
+ void push_initializing(LLSingletonBase*) {}
+ void pop_initializing (LLSingletonBase*) {}
+ LLSingletonBase::list_t& get_initializing(LLSingletonBase::MasterList* instance)
+ {
+ return LLSingletonBase::get_initializing_from(instance);
+ }
+};
+
+// Now we can implement LLSingletonBase's template constructor.
template <typename DERIVED_TYPE>
-class LLSingleton : private boost::noncopyable
+LLSingletonBase::LLSingletonBase(tag<DERIVED_TYPE>):
+ mCleaned(false),
+ mDeleteSingleton(NULL)
+{
+ // Make this the currently-initializing LLSingleton.
+ LLSingleton_manage_master<DERIVED_TYPE>().push_initializing(this);
+}
+
+/**
+ * LLSingleton implements the getInstance() method part of the Singleton
+ * pattern. It can't make the derived class constructors protected, though, so
+ * you have to do that yourself.
+ *
+ * Derive your class from LLSingleton, passing your subclass name as
+ * LLSingleton's template parameter, like so:
+ *
+ * class Foo: public LLSingleton<Foo>
+ * {
+ * // use this macro at start of every LLSingleton subclass
+ * LLSINGLETON(Foo);
+ * public:
+ * // ...
+ * };
+ *
+ * Foo& instance = Foo::instance();
+ *
+ * LLSingleton recognizes a couple special methods in your derived class.
+ *
+ * If you override LLSingleton<T>::initSingleton(), your method will be called
+ * immediately after the instance is constructed. This is useful for breaking
+ * circular dependencies: if you find that your LLSingleton subclass
+ * constructor references other LLSingleton subclass instances in a chain
+ * leading back to yours, move the instance reference from your constructor to
+ * your initSingleton() method.
+ *
+ * If you override LLSingleton<T>::cleanupSingleton(), your method will be
+ * called if someone calls LLSingletonBase::cleanupAll(). The significant part
+ * of this promise is that cleanupAll() will call individual
+ * cleanupSingleton() methods in reverse dependency order.
+ *
+ * That is, consider LLSingleton subclasses C, B and A. A depends on B, which
+ * in turn depends on C. These dependencies are expressed as calls to
+ * B::instance() or B::getInstance(), and C::instance() or C::getInstance().
+ * It shouldn't matter whether these calls appear in A::A() or
+ * A::initSingleton(), likewise B::B() or B::initSingleton().
+ *
+ * We promise that if you later call LLSingletonBase::cleanupAll():
+ * 1. A::cleanupSingleton() will be called before
+ * 2. B::cleanupSingleton(), which will be called before
+ * 3. C::cleanupSingleton().
+ * Put differently, if your LLSingleton subclass constructor or
+ * initSingleton() method explicitly depends on some other LLSingleton
+ * subclass, you may continue to rely on that other subclass in your
+ * cleanupSingleton() method.
+ *
+ * We introduce a special cleanupSingleton() method because cleanupSingleton()
+ * operations can involve nontrivial realtime, or might throw an exception. A
+ * destructor should do neither!
+ *
+ * If your cleanupSingleton() method throws an exception, we log that
+ * exception but proceed with the remaining cleanupSingleton() calls.
+ *
+ * Similarly, if at some point you call LLSingletonBase::deleteAll(), all
+ * remaining LLSingleton instances will be destroyed in dependency order. (Or
+ * call MySubclass::deleteSingleton() to specifically destroy the canonical
+ * MySubclass instance.)
+ *
+ * As currently written, LLSingleton is not thread-safe.
+ */
+template <typename DERIVED_TYPE>
+class LLSingleton : public LLSingletonBase
{
-
private:
- typedef enum e_init_state
- {
- UNINITIALIZED,
- CONSTRUCTING,
- INITIALIZING,
- INITIALIZED,
- DELETED
- } EInitState;
-
static DERIVED_TYPE* constructSingleton()
{
return new DERIVED_TYPE();
}
-
- // stores pointer to singleton instance
- struct SingletonLifetimeManager
- {
- SingletonLifetimeManager()
- {
- construct();
- }
-
- static void construct()
- {
- sData.mInitState = CONSTRUCTING;
- sData.mInstance = constructSingleton();
- sData.mInitState = INITIALIZING;
- }
-
- ~SingletonLifetimeManager()
- {
- if (sData.mInitState != DELETED)
- {
- deleteSingleton();
- }
- }
- };
-
+
+ // We know of no way to instruct the compiler that every subclass
+ // constructor MUST be private. However, we can make the LLSINGLETON()
+ // macro both declare a private constructor and provide the required
+ // friend declaration. How can we ensure that every subclass uses
+ // LLSINGLETON()? By making that macro provide a definition for this pure
+ // virtual method. If you get "can't instantiate class due to missing pure
+ // virtual method" for this method, then add LLSINGLETON(yourclass) in the
+ // subclass body.
+ virtual void you_must_use_LLSINGLETON_macro() = 0;
+
+ // stores pointer to singleton instance
+ struct SingletonLifetimeManager
+ {
+ SingletonLifetimeManager():
+ mMasterRefcount(LLSingletonBase::get_master_refcount())
+ {
+ construct();
+ }
+
+ static void construct()
+ {
+ sData.mInitState = CONSTRUCTING;
+ sData.mInstance = constructSingleton();
+ sData.mInitState = INITIALIZING;
+ }
+
+ ~SingletonLifetimeManager()
+ {
+ // The dependencies between LLSingletons, and the arbitrary order
+ // of static-object destruction, mean that we DO NOT WANT this
+ // destructor to delete this LLSingleton. This destructor will run
+ // without regard to any other LLSingleton whose cleanup might
+ // depend on its existence. What we really want is to count the
+ // runtime's attempts to cleanup LLSingleton static data -- and on
+ // the very last one, call LLSingletonBase::deleteAll(). That
+ // method will properly honor cross-LLSingleton dependencies. This
+ // is why we store an intrusive_ptr to a MasterRefcount: our
+ // ref_ptr_t member counts SingletonLifetimeManager instances.
+ // Once the runtime destroys the last of these, THEN we can delete
+ // every remaining LLSingleton.
+ }
+
+ LLSingletonBase::ref_ptr_t mMasterRefcount;
+ };
+
+protected:
+ // Pass DERIVED_TYPE explicitly to LLSingletonBase's constructor because,
+ // until our subclass constructor completes, *this isn't yet a
+ // full-fledged DERIVED_TYPE.
+ LLSingleton(): LLSingletonBase(LLSingletonBase::tag<DERIVED_TYPE>())
+ {
+ // populate base-class function pointer with the static
+ // deleteSingleton() function for this particular specialization
+ mDeleteSingleton = &deleteSingleton;
+
+ // add this new instance to the master list
+ LLSingleton_manage_master<DERIVED_TYPE>().add(this);
+ }
+
public:
- virtual ~LLSingleton()
- {
- sData.mInstance = NULL;
- sData.mInitState = DELETED;
- }
-
- /**
- * @brief Immediately delete the singleton.
- *
- * A subsequent call to LLProxy::getInstance() will construct a new
- * instance of the class.
- *
- * LLSingletons are normally destroyed after main() has exited and the C++
- * runtime is cleaning up statically-constructed objects. Some classes
- * derived from LLSingleton have objects that are part of a runtime system
- * that is terminated before main() exits. Calling the destructor of those
- * objects after the termination of their respective systems can cause
- * crashes and other problems during termination of the project. Using this
- * method to destroy the singleton early can prevent these crashes.
- *
- * An example where this is needed is for a LLSingleton that has an APR
- * object as a member that makes APR calls on destruction. The APR system is
- * shut down explicitly before main() exits. This causes a crash on exit.
- * Using this method before the call to apr_terminate() and NOT calling
- * getInstance() again will prevent the crash.
- */
- static void deleteSingleton()
- {
- delete sData.mInstance;
- sData.mInstance = NULL;
- sData.mInitState = DELETED;
- }
-
-
- static DERIVED_TYPE* getInstance()
- {
- static SingletonLifetimeManager sLifeTimeMgr;
-
- switch (sData.mInitState)
- {
- case UNINITIALIZED:
- // should never be uninitialized at this point
- llassert(false);
- return NULL;
- case CONSTRUCTING:
- LL_ERRS() << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << LL_ENDL;
- return NULL;
- case INITIALIZING:
- // go ahead and flag ourselves as initialized so we can be reentrant during initialization
- sData.mInitState = INITIALIZED;
- // initialize singleton after constructing it so that it can reference other singletons which in turn depend on it,
- // thus breaking cyclic dependencies
- sData.mInstance->initSingleton();
- return sData.mInstance;
- case INITIALIZED:
- return sData.mInstance;
- case DELETED:
- LL_WARNS() << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << LL_ENDL;
- SingletonLifetimeManager::construct();
- // same as first time construction
- sData.mInitState = INITIALIZED;
- sData.mInstance->initSingleton();
- return sData.mInstance;
- }
-
- return NULL;
- }
-
- static DERIVED_TYPE* getIfExists()
- {
- return sData.mInstance;
- }
-
- // Reference version of getInstance()
- // Preferred over getInstance() as it disallows checking for NULL
- static DERIVED_TYPE& instance()
- {
- return *getInstance();
- }
-
- // Has this singleton been created uet?
- // Use this to avoid accessing singletons before the can safely be constructed
- static bool instanceExists()
- {
- return sData.mInitState == INITIALIZED;
- }
-
- // Has this singleton already been deleted?
- // Use this to avoid accessing singletons from a static object's destructor
- static bool destroyed()
- {
- return sData.mInitState == DELETED;
- }
+ virtual ~LLSingleton()
+ {
+ // remove this instance from the master list
+ LLSingleton_manage_master<DERIVED_TYPE>().remove(this);
+ sData.mInstance = NULL;
+ sData.mInitState = DELETED;
+ }
-private:
+ /**
+ * @brief Immediately delete the singleton.
+ *
+ * A subsequent call to LLProxy::getInstance() will construct a new
+ * instance of the class.
+ *
+ * Without an explicit call to LLSingletonBase::deleteAll(), LLSingletons
+ * are implicitly destroyed after main() has exited and the C++ runtime is
+ * cleaning up statically-constructed objects. Some classes derived from
+ * LLSingleton have objects that are part of a runtime system that is
+ * terminated before main() exits. Calling the destructor of those objects
+ * after the termination of their respective systems can cause crashes and
+ * other problems during termination of the project. Using this method to
+ * destroy the singleton early can prevent these crashes.
+ *
+ * An example where this is needed is for a LLSingleton that has an APR
+ * object as a member that makes APR calls on destruction. The APR system is
+ * shut down explicitly before main() exits. This causes a crash on exit.
+ * Using this method before the call to apr_terminate() and NOT calling
+ * getInstance() again will prevent the crash.
+ */
+ static void deleteSingleton()
+ {
+ delete sData.mInstance;
+ sData.mInstance = NULL;
+ sData.mInitState = DELETED;
+ }
+
+ static DERIVED_TYPE* getInstance()
+ {
+ static SingletonLifetimeManager sLifeTimeMgr;
- virtual void initSingleton() {}
+ switch (sData.mInitState)
+ {
+ case UNINITIALIZED:
+ // should never be uninitialized at this point
+ logerrs("Uninitialized singleton ",
+ demangle(typeid(DERIVED_TYPE).name()).c_str());
+ return NULL;
- struct SingletonData
- {
- // explicitly has a default constructor so that member variables are zero initialized in BSS
- // and only changed by singleton logic, not constructor running during startup
- EInitState mInitState;
- DERIVED_TYPE* mInstance;
- };
- static SingletonData sData;
+ case CONSTRUCTING:
+ logerrs("Tried to access singleton ",
+ demangle(typeid(DERIVED_TYPE).name()).c_str(),
+ " from singleton constructor!");
+ return NULL;
+
+ case INITIALIZING:
+ // go ahead and flag ourselves as initialized so we can be
+ // reentrant during initialization
+ sData.mInitState = INITIALIZED;
+ // initialize singleton after constructing it so that it can
+ // reference other singletons which in turn depend on it, thus
+ // breaking cyclic dependencies
+ sData.mInstance->initSingleton();
+ // pop this off stack of initializing singletons
+ LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance);
+ break;
+
+ case INITIALIZED:
+ break;
+
+ case DELETED:
+ logwarns("Trying to access deleted singleton ",
+ demangle(typeid(DERIVED_TYPE).name()).c_str(),
+ " -- creating new instance");
+ SingletonLifetimeManager::construct();
+ // same as first time construction
+ sData.mInitState = INITIALIZED;
+ sData.mInstance->initSingleton();
+ // pop this off stack of initializing singletons
+ LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance);
+ break;
+ }
+
+ // By this point, if DERIVED_TYPE was pushed onto the initializing
+ // stack, it has been popped off. So the top of that stack, if any, is
+ // an LLSingleton that directly depends on DERIVED_TYPE. If this call
+ // came from another LLSingleton, rather than from vanilla application
+ // code, record the dependency.
+ sData.mInstance->capture_dependency(
+ LLSingleton_manage_master<DERIVED_TYPE>().get_initializing(sData.mInstance),
+ sData.mInitState);
+ return sData.mInstance;
+ }
+
+ // Reference version of getInstance()
+ // Preferred over getInstance() as it disallows checking for NULL
+ static DERIVED_TYPE& instance()
+ {
+ return *getInstance();
+ }
+
+ // Has this singleton been created yet?
+ // Use this to avoid accessing singletons before they can safely be constructed.
+ static bool instanceExists()
+ {
+ return sData.mInitState == INITIALIZED;
+ }
+
+private:
+ struct SingletonData
+ {
+ // explicitly has a default constructor so that member variables are zero initialized in BSS
+ // and only changed by singleton logic, not constructor running during startup
+ EInitState mInitState;
+ DERIVED_TYPE* mInstance;
+ };
+ static SingletonData sData;
};
template<typename T>
typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
+/**
+ * Use LLSINGLETON(Foo); at the start of an LLSingleton<Foo> subclass body
+ * when you want to declare an out-of-line constructor:
+ *
+ * @code
+ * class Foo: public LLSingleton<Foo>
+ * {
+ * // use this macro at start of every LLSingleton subclass
+ * LLSINGLETON(Foo);
+ * public:
+ * // ...
+ * };
+ * // ...
+ * [inline]
+ * Foo::Foo() { ... }
+ * @endcode
+ *
+ * Unfortunately, this mechanism does not permit you to define even a simple
+ * (but nontrivial) constructor within the class body. If it's literally
+ * trivial, use LLSINGLETON_EMPTY_CTOR(); if not, use LLSINGLETON() and define
+ * the constructor outside the class body. If you must define it in a header
+ * file, use 'inline' (unless it's a template class) to avoid duplicate-symbol
+ * errors at link time.
+ */
+#define LLSINGLETON(DERIVED_CLASS) \
+private: \
+ /* implement LLSingleton pure virtual method whose sole purpose */ \
+ /* is to remind people to use this macro */ \
+ virtual void you_must_use_LLSINGLETON_macro() {} \
+ friend class LLSingleton<DERIVED_CLASS>; \
+ DERIVED_CLASS()
+
+/**
+ * Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo>
+ * subclass body when the constructor is trivial:
+ *
+ * @code
+ * class Foo: public LLSingleton<Foo>
+ * {
+ * // use this macro at start of every LLSingleton subclass
+ * LLSINGLETON_EMPTY_CTOR(Foo);
+ * public:
+ * // ...
+ * };
+ * @endcode
+ */
+#define LLSINGLETON_EMPTY_CTOR(DERIVED_CLASS) \
+ /* LLSINGLETON() is carefully implemented to permit exactly this */ \
+ LLSINGLETON(DERIVED_CLASS) {}
+
#endif
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/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 8bace8ac41..20de205454 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -564,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/llheteromap_test.cpp b/indra/llcommon/tests/llheteromap_test.cpp
new file mode 100644
index 0000000000..686bffb878
--- /dev/null
+++ b/indra/llcommon/tests/llheteromap_test.cpp
@@ -0,0 +1,163 @@
+/**
+ * @file llheteromap_test.cpp
+ * @author Nat Goodspeed
+ * @date 2016-10-12
+ * @brief Test for llheteromap.
+ *
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Copyright (c) 2016, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llheteromap.h"
+// STL headers
+#include <set>
+// std headers
+// external library headers
+
+// (pacify clang)
+std::ostream& operator<<(std::ostream& out, const std::set<std::string>& strset);
+// other Linden headers
+#include "../test/lltut.h"
+
+static std::string clog;
+static std::set<std::string> dlog;
+
+// want to be able to use ensure_equals() on a set<string>
+std::ostream& operator<<(std::ostream& out, const std::set<std::string>& strset)
+{
+ out << '{';
+ const char* delim = "";
+ for (std::set<std::string>::const_iterator si(strset.begin()), se(strset.end());
+ si != se; ++si)
+ {
+ out << delim << '"' << *si << '"';
+ delim = ", ";
+ }
+ out << '}';
+ return out;
+}
+
+// unrelated test classes
+struct Chalk
+{
+ int dummy;
+ std::string name;
+
+ Chalk():
+ dummy(0)
+ {
+ clog.append("a");
+ }
+
+ ~Chalk()
+ {
+ dlog.insert("a");
+ }
+
+private:
+ Chalk(const Chalk&); // no implementation
+};
+
+struct Cheese
+{
+ std::string name;
+
+ Cheese()
+ {
+ clog.append("e");
+ }
+
+ ~Cheese()
+ {
+ dlog.insert("e");
+ }
+
+private:
+ Cheese(const Cheese&); // no implementation
+};
+
+struct Chowdah
+{
+ char displace[17];
+ std::string name;
+
+ Chowdah()
+ {
+ displace[0] = '\0';
+ clog.append("o");
+ }
+
+ ~Chowdah()
+ {
+ dlog.insert("o");
+ }
+
+private:
+ Chowdah(const Chowdah&); // no implementation
+};
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llheteromap_data
+ {
+ llheteromap_data()
+ {
+ clog.erase();
+ dlog.clear();
+ }
+ };
+ typedef test_group<llheteromap_data> llheteromap_group;
+ typedef llheteromap_group::object object;
+ llheteromap_group llheteromapgrp("llheteromap");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("create, get, delete");
+
+ {
+ LLHeteroMap map;
+
+ {
+ // create each instance
+ Chalk& chalk = map.obtain<Chalk>();
+ chalk.name = "Chalk";
+
+ Cheese& cheese = map.obtain<Cheese>();
+ cheese.name = "Cheese";
+
+ Chowdah& chowdah = map.obtain<Chowdah>();
+ chowdah.name = "Chowdah";
+ } // refs go out of scope
+
+ {
+ // verify each instance
+ Chalk& chalk = map.obtain<Chalk>();
+ ensure_equals(chalk.name, "Chalk");
+
+ Cheese& cheese = map.obtain<Cheese>();
+ ensure_equals(cheese.name, "Cheese");
+
+ Chowdah& chowdah = map.obtain<Chowdah>();
+ ensure_equals(chowdah.name, "Chowdah");
+ }
+ } // destroy map
+
+ // Chalk, Cheese and Chowdah should have been created in specific order
+ ensure_equals(clog, "aeo");
+
+ // We don't care what order they're destroyed in, as long as each is
+ // appropriately destroyed.
+ std::set<std::string> dtorset;
+ for (const char* cp = "aeo"; *cp; ++cp)
+ dtorset.insert(std::string(1, *cp));
+ ensure_equals(dlog, dtorset);
+ }
+} // 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/llpounceable_test.cpp b/indra/llcommon/tests/llpounceable_test.cpp
new file mode 100644
index 0000000000..2f4915ce11
--- /dev/null
+++ b/indra/llcommon/tests/llpounceable_test.cpp
@@ -0,0 +1,230 @@
+/**
+ * @file llpounceable_test.cpp
+ * @author Nat Goodspeed
+ * @date 2015-05-22
+ * @brief Test for llpounceable.
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llpounceable.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+/*----------------------------- string testing -----------------------------*/
+void append(std::string* dest, const std::string& src)
+{
+ dest->append(src);
+}
+
+/*-------------------------- Data-struct testing ---------------------------*/
+struct Data
+{
+ Data(const std::string& data):
+ mData(data)
+ {}
+ const std::string mData;
+};
+
+void setter(Data** dest, Data* ptr)
+{
+ *dest = ptr;
+}
+
+static Data* static_check = 0;
+
+// Set up an extern pointer to an LLPounceableStatic so the linker will fill
+// in the forward reference from below, before runtime.
+extern LLPounceable<Data*, LLPounceableStatic> gForward;
+
+struct EnqueueCall
+{
+ EnqueueCall()
+ {
+ // Intentionally use a forward reference to an LLPounceableStatic that
+ // we believe is NOT YET CONSTRUCTED. This models the scenario in
+ // which a constructor in another translation unit runs before
+ // constructors in this one. We very specifically want callWhenReady()
+ // to work even in that case: we need the LLPounceableQueueImpl to be
+ // initialized even if the LLPounceable itself is not.
+ gForward.callWhenReady(boost::bind(setter, &static_check, _1));
+ }
+} nqcall;
+// When this declaration is processed, we should enqueue the
+// setter(&static_check, _1) call for when gForward is set non-NULL. Needless
+// to remark, we want this call not to crash.
+
+// Now declare gForward. Its constructor should not run until after nqcall's.
+LLPounceable<Data*, LLPounceableStatic> gForward;
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llpounceable_data
+ {
+ };
+ typedef test_group<llpounceable_data> llpounceable_group;
+ typedef llpounceable_group::object object;
+ llpounceable_group llpounceablegrp("llpounceable");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("LLPounceableStatic out-of-order test");
+ // LLPounceable<T, LLPounceableStatic>::callWhenReady() must work even
+ // before LLPounceable's constructor runs. That's the whole point of
+ // implementing it with an LLSingleton queue. This models (say)
+ // LLPounceableStatic<LLMessageSystem*, LLPounceableStatic>.
+ ensure("static_check should still be null", ! static_check);
+ Data myData("test<1>");
+ gForward = &myData; // should run setter
+ ensure_equals("static_check should be &myData", static_check, &myData);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("LLPounceableQueue different queues");
+ // We expect that LLPounceable<T, LLPounceableQueue> should have
+ // different queues because that specialization stores the queue
+ // directly in the LLPounceable instance.
+ Data *aptr = 0, *bptr = 0;
+ LLPounceable<Data*> a, b;
+ a.callWhenReady(boost::bind(setter, &aptr, _1));
+ b.callWhenReady(boost::bind(setter, &bptr, _1));
+ ensure("aptr should be null", ! aptr);
+ ensure("bptr should be null", ! bptr);
+ Data adata("a"), bdata("b");
+ a = &adata;
+ ensure_equals("aptr should be &adata", aptr, &adata);
+ // but we haven't yet set b
+ ensure("bptr should still be null", !bptr);
+ b = &bdata;
+ ensure_equals("bptr should be &bdata", bptr, &bdata);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("LLPounceableStatic different queues");
+ // LLPounceable<T, LLPounceableStatic> should also have a distinct
+ // queue for each instance, but that engages an additional map lookup
+ // because there's only one LLSingleton for each T.
+ Data *aptr = 0, *bptr = 0;
+ LLPounceable<Data*, LLPounceableStatic> a, b;
+ a.callWhenReady(boost::bind(setter, &aptr, _1));
+ b.callWhenReady(boost::bind(setter, &bptr, _1));
+ ensure("aptr should be null", ! aptr);
+ ensure("bptr should be null", ! bptr);
+ Data adata("a"), bdata("b");
+ a = &adata;
+ ensure_equals("aptr should be &adata", aptr, &adata);
+ // but we haven't yet set b
+ ensure("bptr should still be null", !bptr);
+ b = &bdata;
+ ensure_equals("bptr should be &bdata", bptr, &bdata);
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("LLPounceable<T> looks like T");
+ // We want LLPounceable<T, TAG> to be drop-in replaceable for a plain
+ // T for read constructs. In particular, it should behave like a dumb
+ // pointer -- and with zero abstraction cost for such usage.
+ Data* aptr = 0;
+ Data a("a");
+ // should be able to initialize a pounceable (when its constructor
+ // runs)
+ LLPounceable<Data*> pounceable(&a);
+ // should be able to pass LLPounceable<T> to function accepting T
+ setter(&aptr, pounceable);
+ ensure_equals("aptr should be &a", aptr, &a);
+ // should be able to dereference with *
+ ensure_equals("deref with *", (*pounceable).mData, "a");
+ // should be able to dereference with ->
+ ensure_equals("deref with ->", pounceable->mData, "a");
+ // bool operations
+ ensure("test with operator bool()", pounceable);
+ ensure("test with operator !()", ! (! pounceable));
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("Multiple callWhenReady() queue items");
+ Data *p1 = 0, *p2 = 0, *p3 = 0;
+ Data a("a");
+ LLPounceable<Data*> pounceable;
+ // queue up a couple setter() calls for later
+ pounceable.callWhenReady(boost::bind(setter, &p1, _1));
+ pounceable.callWhenReady(boost::bind(setter, &p2, _1));
+ // should still be pending
+ ensure("p1 should be null", !p1);
+ ensure("p2 should be null", !p2);
+ ensure("p3 should be null", !p3);
+ pounceable = 0;
+ // assigning a new empty value shouldn't flush the queue
+ ensure("p1 should still be null", !p1);
+ ensure("p2 should still be null", !p2);
+ ensure("p3 should still be null", !p3);
+ // using whichever syntax
+ pounceable.reset(0);
+ // try to make ensure messages distinct... tough to pin down which
+ // ensure() failed if multiple ensure() calls in the same test<n> have
+ // the same message!
+ ensure("p1 should again be null", !p1);
+ ensure("p2 should again be null", !p2);
+ ensure("p3 should again be null", !p3);
+ pounceable.reset(&a); // should flush queue
+ ensure_equals("p1 should be &a", p1, &a);
+ ensure_equals("p2 should be &a", p2, &a);
+ ensure("p3 still not set", !p3);
+ // immediate call
+ pounceable.callWhenReady(boost::bind(setter, &p3, _1));
+ ensure_equals("p3 should be &a", p3, &a);
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ set_test_name("queue order");
+ std::string data;
+ LLPounceable<std::string*> pounceable;
+ pounceable.callWhenReady(boost::bind(append, _1, "a"));
+ pounceable.callWhenReady(boost::bind(append, _1, "b"));
+ pounceable.callWhenReady(boost::bind(append, _1, "c"));
+ pounceable = &data;
+ ensure_equals("callWhenReady() must preserve chronological order",
+ data, "abc");
+
+ std::string data2;
+ pounceable = NULL;
+ pounceable.callWhenReady(boost::bind(append, _1, "d"));
+ pounceable.callWhenReady(boost::bind(append, _1, "e"));
+ pounceable.callWhenReady(boost::bind(append, _1, "f"));
+ pounceable = &data2;
+ ensure_equals("LLPounceable must reset queue when fired",
+ data2, "def");
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ set_test_name("compile-fail test, uncomment to check");
+ // The following declaration should fail: only LLPounceableQueue and
+ // LLPounceableStatic should work as tags.
+// LLPounceable<Data*, int> pounceable;
+ }
+} // namespace tut
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/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp
index 385289aefe..56886bc73f 100644
--- a/indra/llcommon/tests/llsingleton_test.cpp
+++ b/indra/llcommon/tests/llsingleton_test.cpp
@@ -30,47 +30,172 @@
#include "llsingleton.h"
#include "../test/lltut.h"
+
+// Capture execution sequence by appending to log string.
+std::string sLog;
+
+#define DECLARE_CLASS(CLS) \
+struct CLS: public LLSingleton<CLS> \
+{ \
+ LLSINGLETON(CLS); \
+ ~CLS(); \
+public: \
+ static enum dep_flag { \
+ DEP_NONE, /* no dependency */ \
+ DEP_CTOR, /* dependency in ctor */ \
+ DEP_INIT /* dependency in initSingleton */ \
+ } sDepFlag; \
+ \
+ void initSingleton(); \
+ void cleanupSingleton(); \
+}; \
+ \
+CLS::dep_flag CLS::sDepFlag = DEP_NONE
+
+DECLARE_CLASS(A);
+DECLARE_CLASS(B);
+
+#define DEFINE_MEMBERS(CLS, OTHER) \
+CLS::CLS() \
+{ \
+ sLog.append(#CLS); \
+ if (sDepFlag == DEP_CTOR) \
+ { \
+ (void)OTHER::instance(); \
+ } \
+} \
+ \
+void CLS::initSingleton() \
+{ \
+ sLog.append("i" #CLS); \
+ if (sDepFlag == DEP_INIT) \
+ { \
+ (void)OTHER::instance(); \
+ } \
+} \
+ \
+void CLS::cleanupSingleton() \
+{ \
+ sLog.append("x" #CLS); \
+} \
+ \
+CLS::~CLS() \
+{ \
+ sLog.append("~" #CLS); \
+}
+
+DEFINE_MEMBERS(A, B)
+DEFINE_MEMBERS(B, A)
+
namespace tut
{
- struct singleton
- {
- // We need a class created with the LLSingleton template to test with.
- class LLSingletonTest: public LLSingleton<LLSingletonTest>
- {
-
- };
- };
-
- typedef test_group<singleton> singleton_t;
- typedef singleton_t::object singleton_object_t;
- tut::singleton_t tut_singleton("LLSingleton");
-
- template<> template<>
- void singleton_object_t::test<1>()
- {
-
- }
- template<> template<>
- void singleton_object_t::test<2>()
- {
- LLSingletonTest* singleton_test = LLSingletonTest::getInstance();
- ensure(singleton_test);
- }
- template<> template<>
- void singleton_object_t::test<3>()
- {
- //Construct the instance
- LLSingletonTest::getInstance();
- ensure(LLSingletonTest::instanceExists());
-
- //Delete the instance
- LLSingletonTest::deleteSingleton();
- ensure(LLSingletonTest::destroyed());
- ensure(!LLSingletonTest::instanceExists());
-
- //Construct it again.
- LLSingletonTest* singleton_test = LLSingletonTest::getInstance();
- ensure(singleton_test);
- ensure(LLSingletonTest::instanceExists());
- }
+ struct singleton
+ {
+ // We need a class created with the LLSingleton template to test with.
+ class LLSingletonTest: public LLSingleton<LLSingletonTest>
+ {
+ LLSINGLETON_EMPTY_CTOR(LLSingletonTest);
+ };
+ };
+
+ typedef test_group<singleton> singleton_t;
+ typedef singleton_t::object singleton_object_t;
+ tut::singleton_t tut_singleton("LLSingleton");
+
+ template<> template<>
+ void singleton_object_t::test<1>()
+ {
+
+ }
+ template<> template<>
+ void singleton_object_t::test<2>()
+ {
+ LLSingletonTest* singleton_test = LLSingletonTest::getInstance();
+ ensure(singleton_test);
+ }
+
+ template<> template<>
+ void singleton_object_t::test<3>()
+ {
+ //Construct the instance
+ LLSingletonTest::getInstance();
+ ensure(LLSingletonTest::instanceExists());
+
+ //Delete the instance
+ LLSingletonTest::deleteSingleton();
+ ensure(!LLSingletonTest::instanceExists());
+
+ //Construct it again.
+ LLSingletonTest* singleton_test = LLSingletonTest::getInstance();
+ ensure(singleton_test);
+ ensure(LLSingletonTest::instanceExists());
+ }
+
+#define TESTS(CLS, OTHER, N0, N1, N2, N3) \
+ template<> template<> \
+ void singleton_object_t::test<N0>() \
+ { \
+ set_test_name("just " #CLS); \
+ CLS::sDepFlag = CLS::DEP_NONE; \
+ OTHER::sDepFlag = OTHER::DEP_NONE; \
+ sLog.clear(); \
+ \
+ (void)CLS::instance(); \
+ ensure_equals(sLog, #CLS "i" #CLS); \
+ LLSingletonBase::cleanupAll(); \
+ ensure_equals(sLog, #CLS "i" #CLS "x" #CLS); \
+ LLSingletonBase::deleteAll(); \
+ ensure_equals(sLog, #CLS "i" #CLS "x" #CLS "~" #CLS); \
+ } \
+ \
+ template<> template<> \
+ void singleton_object_t::test<N1>() \
+ { \
+ set_test_name(#CLS " ctor depends " #OTHER); \
+ CLS::sDepFlag = CLS::DEP_CTOR; \
+ OTHER::sDepFlag = OTHER::DEP_NONE; \
+ sLog.clear(); \
+ \
+ (void)CLS::instance(); \
+ ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS); \
+ LLSingletonBase::cleanupAll(); \
+ ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER); \
+ LLSingletonBase::deleteAll(); \
+ ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \
+ } \
+ \
+ template<> template<> \
+ void singleton_object_t::test<N2>() \
+ { \
+ set_test_name(#CLS " init depends " #OTHER); \
+ CLS::sDepFlag = CLS::DEP_INIT; \
+ OTHER::sDepFlag = OTHER::DEP_NONE; \
+ sLog.clear(); \
+ \
+ (void)CLS::instance(); \
+ ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER); \
+ LLSingletonBase::cleanupAll(); \
+ ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \
+ LLSingletonBase::deleteAll(); \
+ ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \
+ } \
+ \
+ template<> template<> \
+ void singleton_object_t::test<N3>() \
+ { \
+ set_test_name(#CLS " circular init"); \
+ CLS::sDepFlag = CLS::DEP_INIT; \
+ OTHER::sDepFlag = OTHER::DEP_CTOR; \
+ sLog.clear(); \
+ \
+ (void)CLS::instance(); \
+ ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER); \
+ LLSingletonBase::cleanupAll(); \
+ ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \
+ LLSingletonBase::deleteAll(); \
+ ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \
+ }
+
+ TESTS(A, B, 4, 5, 6, 7)
+ TESTS(B, A, 8, 9, 10, 11)
}
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index 0bb0348d26..b03ee6eeda 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -93,6 +93,7 @@ target_link_libraries(
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${BOOST_THREAD_LIBRARY}
+ ${BOOST_SYSTEM_LIBRARY}
)
# tests
@@ -129,8 +130,8 @@ if (LL_TESTS)
${CURL_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
- ${BOOST_SYSTEM_LIBRARY}
${BOOST_THREAD_LIBRARY}
+ ${BOOST_SYSTEM_LIBRARY}
)
# If http_proxy is in the current environment (e.g. to fetch s3-proxy
@@ -197,8 +198,8 @@ endif (DARWIN)
${CURL_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
- ${BOOST_SYSTEM_LIBRARY}
${BOOST_THREAD_LIBRARY}
+ ${BOOST_SYSTEM_LIBRARY}
)
add_executable(http_texture_load
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index bef762f5ce..a310fc0508 100644..100755
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
@@ -46,6 +46,7 @@
#include "test_httprequestqueue.hpp"
#include "llproxy.h"
+#include "llcleanup.h"
unsigned long ssl_thread_id_callback(void);
void ssl_locking_callback(int mode, int type, const char * file, int line);
@@ -101,7 +102,7 @@ void init_curl()
void term_curl()
{
- LLProxy::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLProxy);
CRYPTO_set_locking_callback(NULL);
for (int i(0); i < ssl_mutex_count; ++i)
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index 463e55dd7e..6cd7960ecd 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -729,7 +729,7 @@ void HttpRequestTestObjectType::test<7>()
#if 0 // defined(WIN32)
// Can't do this on any platform anymore, the LL logging system holds
// on to memory and produces what looks like memory leaks...
-
+
// printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
#endif
@@ -1459,21 +1459,21 @@ void HttpRequestTestObjectType::test<14>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
- LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
- std::string url_base(get_base_url() + "/sleep/"); // path to a 30-second sleep
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+ std::string url_base(get_base_url() + "/sleep/"); // path to a 30-second sleep
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
HttpOptions::ptr_t opts;
-
+
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
-
+
// Start threading early so that thread memory is invariant
// over the test.
HttpRequest::startThread();
@@ -1482,10 +1482,10 @@ void HttpRequestTestObjectType::test<14>()
req = new HttpRequest();
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
- opts = HttpOptions::ptr_t(new HttpOptions);
- opts->setRetries(0); // Don't retry
+ opts = HttpOptions::ptr_t(new HttpOptions);
+ opts->setRetries(0); // Don't retry
opts->setTimeout(2);
-
+
// Issue a GET that sleeps
mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
@@ -1494,8 +1494,8 @@ void HttpRequestTestObjectType::test<14>()
0,
0,
opts,
- HttpHeaders::ptr_t(),
- handlerp);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1513,7 +1513,7 @@ void HttpRequestTestObjectType::test<14>()
mStatus = HttpStatus();
handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
-
+
// Run the notification pump again
count = 0;
limit = LOOP_COUNT_LONG;
@@ -1535,30 +1535,29 @@ void HttpRequestTestObjectType::test<14>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options
- opts.reset();
-
+ opts.reset();
+
// release the request object
delete req;
req = NULL;
// Shut down service
HttpRequest::destroyService();
-
+
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
-#if defined(WIN32)
- // Can only do this memory test on Windows. On other platforms,
- // the LL logging system holds on to memory and produces what looks
- // like memory leaks...
-
- // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
+#if 0 // defined(WIN32)
+ // Can't do this on any platform anymore, the LL logging system holds
+ // on to memory and produces what looks like memory leaks...
+
+ // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
#endif
}
catch (...)
{
stop_thread(req);
- opts.reset();
+ opts.reset();
delete req;
HttpRequest::destroyService();
throw;
@@ -3065,12 +3064,11 @@ void HttpRequestTestObjectType::test<22>()
// Shut down service
HttpRequest::destroyService();
-
-#if defined(WIN32)
- // Can only do this memory test on Windows. On other platforms,
- // the LL logging system holds on to memory and produces what looks
- // like memory leaks...
-
+
+#if 0 // defined(WIN32)
+ // Can't do this on any platform anymore, the LL logging system holds
+ // on to memory and produces what looks like memory leaks...
+
// printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
#endif
@@ -3195,12 +3193,11 @@ void HttpRequestTestObjectType::test<23>()
// Shut down service
HttpRequest::destroyService();
-
-#if defined(WIN32)
- // Can only do this memory test on Windows. On other platforms,
- // the LL logging system holds on to memory and produces what looks
- // like memory leaks...
-
+
+#if 0 // defined(WIN32)
+ // Can't do this on any platform anymore, the LL logging system holds
+ // on to memory and produces what looks like memory leaks...
+
// printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
#endif
diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py
index 04cde651c4..6c5f37d407 100755
--- a/indra/llcorehttp/tests/test_llcorehttp_peer.py
+++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py
@@ -42,10 +42,8 @@ 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
from testrunner import freeport, run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index dfb344c908..dca49be051 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -45,6 +45,7 @@
#include "llhttpsdhandler.h"
#include "httpcommon.h"
#include "httpresponse.h"
+#include "llcleanup.h"
#include <curl/curl.h>
#include <openssl/crypto.h>
@@ -623,7 +624,7 @@ void LLCrashLogger::commonCleanup()
{
term_curl();
LLError::logToFile(""); //close crashreport.log
- LLProxy::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLProxy);
}
void LLCrashLogger::init_curl()
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index f71607096c..43b6b3bcd6 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -705,18 +705,21 @@ void LLImageBase::deleteData()
// virtual
U8* LLImageBase::allocateData(S32 size)
{
+ //make this function thread-safe.
+ static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16; //256 MB
+ mBadBufferAllocation = false;
+
if (size < 0)
{
size = mWidth * mHeight * mComponents;
if (size <= 0)
{
- LL_ERRS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL;
+ LL_WARNS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL;
+ mBadBufferAllocation = true;
}
- }
-
- //make this function thread-safe.
- static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16 ; //256 MB
- if (size < 1 || size > MAX_BUFFER_SIZE)
+ }
+
+ if (!mBadBufferAllocation && (size < 1 || size > MAX_BUFFER_SIZE))
{
LL_INFOS() << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << LL_ENDL ;
if(mAllowOverSize)
@@ -725,25 +728,31 @@ U8* LLImageBase::allocateData(S32 size)
}
else
{
- LL_ERRS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL;
+ LL_WARNS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL;
+ mBadBufferAllocation = true;
}
}
- if (!mData || size != mDataSize)
+
+ if (!mBadBufferAllocation && (!mData || size != mDataSize))
{
deleteData(); // virtual
- mBadBufferAllocation = false ;
mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!mData)
{
LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL;
- size = 0 ;
- mWidth = mHeight = 0 ;
- mBadBufferAllocation = true ;
+ mBadBufferAllocation = true;
}
- mDataSize = size;
- claimMem(mDataSize);
}
+ if (mBadBufferAllocation)
+ {
+ size = 0;
+ mWidth = mHeight = 0;
+ mData = NULL;
+ }
+ mDataSize = size;
+ claimMem(mDataSize);
+
return mData;
}
diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp
index e10402196f..2a023d8c24 100644
--- a/indra/llinventory/lleconomy.cpp
+++ b/indra/llinventory/lleconomy.cpp
@@ -31,7 +31,7 @@
#include "v3math.h"
-LLGlobalEconomy::LLGlobalEconomy()
+LLBaseEconomy::LLBaseEconomy()
: mObjectCount( -1 ),
mObjectCapacity( -1 ),
mPriceObjectClaim( -1 ),
@@ -45,15 +45,15 @@ LLGlobalEconomy::LLGlobalEconomy()
mPriceGroupCreate( -1 )
{ }
-LLGlobalEconomy::~LLGlobalEconomy()
+LLBaseEconomy::~LLBaseEconomy()
{ }
-void LLGlobalEconomy::addObserver(LLEconomyObserver* observer)
+void LLBaseEconomy::addObserver(LLEconomyObserver* observer)
{
mObservers.push_back(observer);
}
-void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer)
+void LLBaseEconomy::removeObserver(LLEconomyObserver* observer)
{
std::list<LLEconomyObserver*>::iterator it =
std::find(mObservers.begin(), mObservers.end(), observer);
@@ -63,7 +63,7 @@ void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer)
}
}
-void LLGlobalEconomy::notifyObservers()
+void LLBaseEconomy::notifyObservers()
{
for (std::list<LLEconomyObserver*>::iterator it = mObservers.begin();
it != mObservers.end();
@@ -74,7 +74,7 @@ void LLGlobalEconomy::notifyObservers()
}
// static
-void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data)
+void LLBaseEconomy::processEconomyData(LLMessageSystem *msg, LLBaseEconomy* econ_data)
{
S32 i;
F32 f;
@@ -117,7 +117,7 @@ void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy*
econ_data->notifyObservers();
}
-S32 LLGlobalEconomy::calculateTeleportCost(F32 distance) const
+S32 LLBaseEconomy::calculateTeleportCost(F32 distance) const
{
S32 min_cost = getTeleportMinPrice();
F32 exponent = getTeleportPriceExponent();
@@ -135,13 +135,13 @@ S32 LLGlobalEconomy::calculateTeleportCost(F32 distance) const
return cost;
}
-S32 LLGlobalEconomy::calculateLightRent(const LLVector3& object_size) const
+S32 LLBaseEconomy::calculateLightRent(const LLVector3& object_size) const
{
F32 intensity_mod = llmax(object_size.magVec(), 1.f);
return (S32)(intensity_mod * getPriceRentLight());
}
-void LLGlobalEconomy::print()
+void LLBaseEconomy::print()
{
LL_INFOS() << "Global Economy Settings: " << LL_ENDL;
LL_INFOS() << "Object Capacity: " << mObjectCapacity << LL_ENDL;
@@ -159,8 +159,7 @@ void LLGlobalEconomy::print()
}
LLRegionEconomy::LLRegionEconomy()
-: LLGlobalEconomy(),
- mPriceObjectRent( -1.f ),
+: mPriceObjectRent( -1.f ),
mPriceObjectScaleFactor( -1.f ),
mEnergyEfficiency( -1.f ),
mBasePriceParcelClaimDefault(-1),
@@ -187,7 +186,7 @@ void LLRegionEconomy::processEconomyData(LLMessageSystem *msg, void** user_data)
LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data;
- LLGlobalEconomy::processEconomyData(msg, this_ptr);
+ LLBaseEconomy::processEconomyData(msg, this_ptr);
msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelClaim, i);
this_ptr->setBasePriceParcelClaimDefault(i);
@@ -252,7 +251,7 @@ S32 LLRegionEconomy::getPriceParcelRent() const
void LLRegionEconomy::print()
{
- this->LLGlobalEconomy::print();
+ this->LLBaseEconomy::print();
LL_INFOS() << "Region Economy Settings: " << LL_ENDL;
LL_INFOS() << "Land (square meters): " << mAreaTotal << LL_ENDL;
diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h
index 47fcf688a2..cdfde171c1 100644
--- a/indra/llinventory/lleconomy.h
+++ b/indra/llinventory/lleconomy.h
@@ -42,18 +42,11 @@ public:
virtual void onEconomyDataChange() = 0;
};
-class LLGlobalEconomy
+class LLBaseEconomy
{
public:
- LLGlobalEconomy();
- virtual ~LLGlobalEconomy();
-
- // This class defines its singleton internally as a typedef instead of inheriting from
- // LLSingleton like most others because the LLRegionEconomy sub-class might also
- // become a singleton and this pattern will more easily disambiguate them.
- typedef LLSingleton<LLGlobalEconomy> Singleton;
-
- void initSingleton() { }
+ LLBaseEconomy();
+ virtual ~LLBaseEconomy();
virtual void print();
@@ -61,7 +54,7 @@ public:
void removeObserver(LLEconomyObserver* observer);
void notifyObservers();
- static void processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data);
+ static void processEconomyData(LLMessageSystem *msg, LLBaseEconomy* econ_data);
S32 calculateTeleportCost(F32 distance) const;
S32 calculateLightRent(const LLVector3& object_size) const;
@@ -108,8 +101,12 @@ private:
std::list<LLEconomyObserver*> mObservers;
};
+class LLGlobalEconomy: public LLSingleton<LLGlobalEconomy>, public LLBaseEconomy
+{
+ LLSINGLETON_EMPTY_CTOR(LLGlobalEconomy);
+};
-class LLRegionEconomy : public LLGlobalEconomy
+class LLRegionEconomy : public LLBaseEconomy
{
public:
LLRegionEconomy();
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 86aca77de8..b0daf639fa 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -51,8 +51,7 @@ struct FolderEntry : public LLDictionaryEntry
class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
public LLDictionary<LLFolderType::EType, FolderEntry>
{
-public:
- LLFolderDictionary();
+ LLSINGLETON(LLFolderDictionary);
protected:
virtual LLFolderType::EType notFound() const
{
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index 8807b36117..d1e6807f52 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -63,8 +63,7 @@ struct InventoryEntry : public LLDictionaryEntry
class LLInventoryDictionary : public LLSingleton<LLInventoryDictionary>,
public LLDictionary<LLInventoryType::EType, InventoryEntry>
{
-public:
- LLInventoryDictionary();
+ LLSINGLETON(LLInventoryDictionary);
};
LLInventoryDictionary::LLInventoryDictionary()
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 93b9f22b25..692284e04b 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -254,6 +254,11 @@ inline int round_int(double x)
}
#endif // BOGUS_ROUND
+inline F64 ll_round(const F64 val)
+{
+ return F64(floor(val + 0.5f));
+}
+
inline F32 ll_round( F32 val, F32 nearest )
{
return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest;
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/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h
index 497367b80c..7d0e83180c 100644
--- a/indra/llmessage/llcoproceduremanager.h
+++ b/indra/llmessage/llcoproceduremanager.h
@@ -37,7 +37,8 @@ class LLCoprocedurePool;
class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager >
{
- friend class LLSingleton < LLCoprocedureManager > ;
+ LLSINGLETON(LLCoprocedureManager);
+ virtual ~LLCoprocedureManager();
public:
typedef boost::function<U32(const std::string &)> SettingQuery_t;
@@ -45,9 +46,6 @@ public:
typedef boost::function<void(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t;
- LLCoprocedureManager();
- virtual ~LLCoprocedureManager();
-
/// Places the coprocedure on the queue for processing.
///
/// @param name Is used for debugging and should identify this coroutine.
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/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index 1002b33f80..8ee7080d38 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -43,7 +43,7 @@ class LLUUID;
class LLExperienceCache: public LLSingleton < LLExperienceCache >
{
- friend class LLSingleton < LLExperienceCache > ;
+ LLSINGLETON(LLExperienceCache);
public:
typedef boost::function<std::string(const std::string &)> CapabilityQuery_t;
@@ -103,7 +103,6 @@ public:
static const int PROPERTY_SUSPENDED; // 1 << 7
private:
- LLExperienceCache();
virtual ~LLExperienceCache();
virtual void initSingleton();
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index bd23dd39de..688dff7c83 100644
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -218,14 +218,14 @@ enum LLSocks5AuthType
*/
class LLProxy: public LLSingleton<LLProxy>
{
- LOG_CLASS(LLProxy);
-public:
/*###########################################################################################
METHODS THAT DO NOT LOCK mProxyMutex!
###########################################################################################*/
// Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
- LLProxy();
+ LLSINGLETON(LLProxy);
+ LOG_CLASS(LLProxy);
+public:
// Static check for enabled status for UDP packets. Call from main thread only.
static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
@@ -239,9 +239,11 @@ public:
/*###########################################################################################
METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
###########################################################################################*/
+private:
// Destructor, closes open connections. Do not call directly, use cleanupClass().
~LLProxy();
+public:
// Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be
// destroyed before the call to apr_terminate. Call from main thread only.
static void cleanupClass();
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/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp
index 257a13f277..8e2ed890e7 100644
--- a/indra/llmessage/llxfer_file.cpp
+++ b/indra/llmessage/llxfer_file.cpp
@@ -98,12 +98,12 @@ void LLXfer_File::cleanup ()
mFp = NULL;
}
- LLFile::remove(mTempFilename);
+ LLFile::remove(mTempFilename, ENOENT);
if (mDeleteLocalOnCompletion)
{
LL_DEBUGS() << "Removing file: " << mLocalFilename << LL_ENDL;
- LLFile::remove(mLocalFilename);
+ LLFile::remove(mLocalFilename, ENOENT);
}
else
{
@@ -321,7 +321,7 @@ S32 LLXfer_File::processEOF()
mCallbackResult = flushval;
}
- LLFile::remove(mLocalFilename);
+ LLFile::remove(mLocalFilename, ENOENT);
if (!mCallbackResult)
{
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 0ab67b8dda..2ceb64ce8f 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);
+ LLFile::remove(local_filename, ENOENT);
}
+ 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..6ef4025ab1 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -76,6 +76,7 @@
#include "v4math.h"
#include "lltransfertargetvfile.h"
#include "llcorehttputil.h"
+#include "llpounceable.h"
// Constants
//const char* MESSAGE_LOG_FILENAME = "message.log";
@@ -1724,7 +1725,9 @@ std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)
return s;
}
-LLMessageSystem *gMessageSystem = NULL;
+// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.)
+// callback registrations for when gMessageSystem is first assigned
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
// update appropriate ping info
void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
@@ -2641,7 +2644,7 @@ void end_messaging_system(bool print_summary)
LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;
}
- delete gMessageSystem;
+ delete static_cast<LLMessageSystem*>(gMessageSystem);
gMessageSystem = NULL;
}
}
@@ -4007,7 +4010,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/message.h b/indra/llmessage/message.h
index 133db620e6..f6c5d9e228 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -60,6 +60,7 @@
#include "llstoredmessage.h"
#include "boost/function.hpp"
+#include "llpounceable.h"
const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
@@ -68,10 +69,10 @@ const S32 MESSAGE_MAX_PER_FRAME = 400;
class LLMessageStringTable : public LLSingleton<LLMessageStringTable>
{
-public:
- LLMessageStringTable();
+ LLSINGLETON(LLMessageStringTable);
~LLMessageStringTable();
+public:
char *getString(const char *str);
U32 mUsed;
@@ -832,7 +833,7 @@ private:
// external hook into messaging system
-extern LLMessageSystem *gMessageSystem;
+extern LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
// Must specific overall system version, which is used to determine
// if a patch is available in the message template checksum verification.
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index a32bfa59ce..9356a14f1f 100644
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -42,6 +42,7 @@
#include "lliosocket.h"
#include "stringize.h"
+#include "llcleanup.h"
namespace tut
{
@@ -66,7 +67,7 @@ namespace tut
~HTTPClientTestData()
{
delete mClientPump;
- LLProxy::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLProxy);
apr_pool_destroy(mPool);
}
diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
index 3b04530c1a..e20f61b73f 100644
--- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
+++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
@@ -31,11 +31,12 @@
#include "llhost.h"
#include "message.h"
#include "llsd.h"
+#include "llpounceable.h"
#include "llhost.cpp" // Needed for copy operator
#include "net.cpp" // Needed by LLHost.
-LLMessageSystem * gMessageSystem = NULL;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
// sensor test doubles
bool gClearRecvWasCalled = false;
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
index 55748ad27e..41f982a7e2 100644
--- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -33,8 +33,9 @@
#include "message.h"
#include "llmessageconfig.h"
#include "llhttpnode_stub.cpp"
+#include "llpounceable.h"
-LLMessageSystem* gMessageSystem = NULL;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
LLMessageConfig::SenderTrust
LLMessageConfig::getSenderTrustedness(const std::string& msg_name)
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 5eb739393f..5986524342 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -44,7 +44,7 @@
// init time. Use the lazy, on-demand initialization we get from LLSingleton.
class NetworkIO: public LLSingleton<NetworkIO>
{
-public:
+ LLSINGLETON(NetworkIO);
NetworkIO():
mServicePump(NULL),
mDone(false)
@@ -69,6 +69,7 @@ public:
boost::bind(&NetworkIO::done, this, _1));
}
+public:
bool pump(F32 timeout=10)
{
// Reset the done flag so we don't pop out prematurely
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/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index d672650658..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);
@@ -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..de02c5c188 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -851,6 +851,8 @@ struct ModelSort
bool LLDAELoader::OpenFile(const std::string& filename)
{
+ setLoadState( READING_FILE );
+
//no suitable slm exists, load from the .dae file
DAE dae;
domCOLLADA* dom;
@@ -997,6 +999,11 @@ bool LLDAELoader::OpenFile(const std::string& filename)
std::sort(mModelList.begin(), mModelList.end(), ModelSort());
+ if (!mNoNormalize)
+ {
+ LLModel::normalizeModels(mModelList);
+ }
+
model_list::iterator model_iter = mModelList.begin();
while (model_iter != mModelList.end())
{
@@ -1071,7 +1078,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();
@@ -2406,8 +2413,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
//
ret->sortVolumeFacesByMaterialName();
- bool normalized = false;
-
int submodelID = 0;
// remove all faces that definitely won't fit into one model and submodel limit
@@ -2422,12 +2427,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
{
// Insure we do this once with the whole gang and not per-model
//
- if (!normalized && !mNoNormalize)
- {
- normalized = true;
- ret->normalizeVolumeFaces();
- }
-
ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);
if (!mNoOptimize)
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index e494c55250..39ee550844 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -174,6 +174,165 @@ void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remain
}
}
+// Shrink group of models to fit
+// on a 1x1x1 cube centered at the origin.
+void LLModel::normalizeModels(std::vector<LLPointer<LLModel > > model_list)
+{
+ std::vector<LLPointer<LLModel > >::iterator iter = model_list.begin();
+
+ LLVector4a min, max;
+ while (iter != model_list.end() && (*iter)->mVolumeFaces.empty())
+ {
+ iter++;
+ }
+ if (iter == model_list.end())
+ {
+ // no models with faces
+ return;
+ }
+
+ min = (*iter)->mVolumeFaces[0].mExtents[0];
+ max = (*iter)->mVolumeFaces[0].mExtents[1];
+
+ // Treat models as a group - each model out of 1x1x1 cube
+ // needs scaling and will affect whole group scale
+ while (iter != model_list.end())
+ {
+ LLPointer<LLModel> model = *iter++;
+
+ if (model.get() && model->mVolumeFaces.empty())
+ {
+ // For all of the volume faces
+ // in the model, loop over
+ // them and see what the extents
+ // of the volume along each axis.
+
+ for (U32 i = 0; i < model->mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = model->mVolumeFaces[i];
+
+ update_min_max(min, max, face.mExtents[0]);
+ update_min_max(min, max, face.mExtents[1]);
+
+ if (face.mTexCoords)
+ {
+ LLVector2& min_tc = face.mTexCoordExtents[0];
+ LLVector2& max_tc = face.mTexCoordExtents[1];
+
+ min_tc = face.mTexCoords[0];
+ max_tc = face.mTexCoords[0];
+
+ for (U32 j = 1; j < face.mNumVertices; ++j)
+ {
+ update_min_max(min_tc, max_tc, face.mTexCoords[j]);
+ }
+ }
+ else
+ {
+ face.mTexCoordExtents[0].set(0, 0);
+ face.mTexCoordExtents[1].set(1, 1);
+ }
+ }
+ }
+ }
+
+ // Now that we have the extents of the model
+ // we can compute the offset needed to center
+ // the model at the origin.
+
+ // Compute center of the model
+ // and make it negative to get translation
+ // needed to center at origin.
+ LLVector4a trans;
+ trans.setAdd(min, max);
+ trans.mul(-0.5f);
+
+ // Compute the total size along all
+ // axes of the model.
+ LLVector4a size;
+ size.setSub(max, min);
+
+ // Prevent division by zero.
+ F32 x = size[0];
+ F32 y = size[1];
+ F32 z = size[2];
+ F32 w = size[3];
+ if (fabs(x) < F_APPROXIMATELY_ZERO)
+ {
+ x = 1.0;
+ }
+ if (fabs(y) < F_APPROXIMATELY_ZERO)
+ {
+ y = 1.0;
+ }
+ if (fabs(z) < F_APPROXIMATELY_ZERO)
+ {
+ z = 1.0;
+ }
+ size.set(x, y, z, w);
+
+ // Compute scale as reciprocal of size
+ LLVector4a scale;
+ scale.splat(1.f);
+ scale.div(size);
+
+ LLVector4a inv_scale(1.f);
+ inv_scale.div(scale);
+
+ iter = model_list.begin();
+ // apply fixed scale and trans to all models as a single group
+ while (iter != model_list.end())
+ {
+ LLPointer<LLModel> model = *iter++;
+
+ if (model->mVolumeFaces.empty())
+ {
+ continue;
+ }
+
+ for (U32 i = 0; i < model->mVolumeFaces.size(); ++i)
+ {
+ LLVolumeFace& face = model->mVolumeFaces[i];
+
+ // We shrink the extents so
+ // that they fall within
+ // the unit cube.
+ face.mExtents[0].add(trans);
+ face.mExtents[0].mul(scale);
+
+ face.mExtents[1].add(trans);
+ face.mExtents[1].mul(scale);
+
+ // For all the positions, we scale
+ // the positions to fit within the unit cube.
+ LLVector4a* pos = (LLVector4a*)face.mPositions;
+ LLVector4a* norm = (LLVector4a*)face.mNormals;
+
+ for (U32 j = 0; j < face.mNumVertices; ++j)
+ {
+ pos[j].add(trans);
+ pos[j].mul(scale);
+ if (norm && !norm[j].equals3(LLVector4a::getZero()))
+ {
+ norm[j].mul(inv_scale);
+ norm[j].normalize3();
+ }
+ }
+ }
+
+ // mNormalizedScale is the scale at which
+ // we would need to multiply the model
+ // by to get the original size of the
+ // model instead of the normalized size.
+ LLVector4a normalized_scale;
+ normalized_scale.splat(1.f);
+ normalized_scale.div(scale);
+ model->mNormalizedScale.set(normalized_scale.getF32ptr());
+ model->mNormalizedTranslation.set(trans.getF32ptr());
+ model->mNormalizedTranslation *= -1.f;
+ }
+}
+
// Shrink the model to fit
// on a 1x1x1 cube centered at the origin.
// The positions and extents
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index ae602c09df..8f07058dbd 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -172,6 +172,7 @@ public:
void addFace(const LLVolumeFace& face);
void sortVolumeFacesByMaterialName();
+ static void normalizeModels(std::vector<LLPointer<LLModel > > model_list);
void normalizeVolumeFaces();
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void optimizeVolumeFaces();
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/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..3e7c69611d 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -267,7 +267,14 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
}
else
{
- LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
+ if (texture)
+ {
+ LL_DEBUGS() << "NULL LLTexUnit::bind GL image" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
+ }
return false;
}
}
@@ -286,7 +293,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
if(!texture)
{
- LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
+ LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
return false;
}
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 0fae600a90..31dffdd545 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -448,7 +448,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
else
{
- GLenum array[] =
+ static const GLenum array[] =
{
GL_VERTEX_ARRAY,
GL_NORMAL_ARRAY,
@@ -456,7 +456,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
GL_COLOR_ARRAY,
};
- GLenum mask[] =
+ static const GLenum mask[] =
{
MAP_VERTEX,
MAP_NORMAL,
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/llclipboard.h b/indra/llui/llclipboard.h
index 58d80e2687..a668ac1ac6 100644
--- a/indra/llui/llclipboard.h
+++ b/indra/llui/llclipboard.h
@@ -48,10 +48,10 @@
class LLClipboard : public LLSingleton<LLClipboard>
{
-public:
- LLClipboard();
+ LLSINGLETON(LLClipboard);
~LLClipboard();
+public:
// Clears the clipboard
void reset();
// Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state)
diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h
index f2f2145953..8cec5e2b24 100644
--- a/indra/llui/llcommandmanager.h
+++ b/indra/llui/llcommandmanager.h
@@ -173,6 +173,9 @@ private:
class LLCommandManager
: public LLSingleton<LLCommandManager>
{
+ LLSINGLETON(LLCommandManager);
+ ~LLCommandManager();
+
public:
struct Params : public LLInitParam::Block<Params>
{
@@ -184,9 +187,6 @@ public:
}
};
- LLCommandManager();
- ~LLCommandManager();
-
U32 commandCount() const;
LLCommand * getCommand(U32 commandIndex);
LLCommand * getCommand(const LLCommandId& commandId);
diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h
index ac92b19977..99267d978a 100644
--- a/indra/llui/llcontainerview.h
+++ b/indra/llui/llcontainerview.h
@@ -35,7 +35,9 @@
class LLScrollContainer;
struct ContainerViewRegistry : public LLChildRegistry<ContainerViewRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(ContainerViewRegistry);
+};
class LLContainerView : public LLView
{
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 299f5e42d4..5e00bf7f45 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -105,6 +105,81 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*
return true;
}
+bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= true*/)
+{
+ if (!mItemComparator)
+ {
+ LL_WARNS_ONCE() << "No comparator specified for inserting FlatListView items." << LL_ENDL;
+ return false;
+ }
+ if (panel_list.size() == 0)
+ {
+ return false;
+ }
+
+ // presort list so that it will be easier to sort elements into mItemPairs
+ panel_list.sort(ComparatorAdaptor(*mItemComparator));
+
+ pairs_const_iterator_t new_pair_it = panel_list.begin();
+ item_pair_t* new_pair = *new_pair_it;
+ pairs_iterator_t pair_it = mItemPairs.begin();
+ item_pair_t* item_pair = *pair_it;
+
+ // sort panel_list into mItemPars
+ while (new_pair_it != panel_list.end() && pair_it != mItemPairs.end())
+ {
+ if (!new_pair->first || new_pair->first->getParent() == mItemsPanel)
+ {
+ // iterator already used or we are reusing existing panel
+ new_pair_it++;
+ new_pair = *new_pair_it;
+ }
+ else if (mItemComparator->compare(new_pair->first, item_pair->first))
+ {
+ LLPanel* panel = new_pair->first;
+
+ mItemPairs.insert(pair_it, new_pair);
+ mItemsPanel->addChild(panel);
+
+ //_4 is for MASK
+ panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
+ // Children don't accept the focus
+ panel->setTabStop(false);
+ }
+ else
+ {
+ pair_it++;
+ item_pair = *pair_it;
+ }
+ }
+
+ // Add what is left of panel_list into the end of mItemPairs.
+ for (; new_pair_it != panel_list.end(); ++new_pair_it)
+ {
+ item_pair_t* item_pair = *new_pair_it;
+ LLPanel *panel = item_pair->first;
+ if (panel && panel->getParent() != mItemsPanel)
+ {
+ mItemPairs.push_back(item_pair);
+ mItemsPanel->addChild(panel);
+
+ //_4 is for MASK
+ panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, item_pair, _4));
+ panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, item_pair, _4));
+ // Children don't accept the focus
+ panel->setTabStop(false);
+ }
+ }
+
+ if (rearrange)
+ {
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ }
+ return true;
+}
+
bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/)
{
@@ -1289,6 +1364,28 @@ void LLFlatListViewEx::setFilterSubString(const std::string& filter_str)
}
}
+void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
+{
+ if (!item) return;
+
+ // 0 signifies that filter is matched,
+ // i.e. we don't hide items that don't support 'match_filter' action, separators etc.
+ if (0 == item->notify(action))
+ {
+ mHasMatchedItems = true;
+ item->setVisible(true);
+ }
+ else
+ {
+ // TODO: implement (re)storing of current selection.
+ if (!mForceShowingUnmatchedItems)
+ {
+ selectItem(item, false);
+ }
+ item->setVisible(mForceShowingUnmatchedItems);
+ }
+}
+
void LLFlatListViewEx::filterItems()
{
typedef std::vector <LLPanel*> item_panel_list_t;
@@ -1309,22 +1406,7 @@ void LLFlatListViewEx::filterItems()
iter != iter_end; ++iter)
{
LLPanel* pItem = (*iter);
- // 0 signifies that filter is matched,
- // i.e. we don't hide items that don't support 'match_filter' action, separators etc.
- if (0 == pItem->notify(action))
- {
- mHasMatchedItems = true;
- pItem->setVisible(true);
- }
- else
- {
- // TODO: implement (re)storing of current selection.
- if(!mForceShowingUnmatchedItems)
- {
- selectItem(pItem, false);
- }
- pItem->setVisible(mForceShowingUnmatchedItems);
- }
+ updateItemVisibility(pItem, action);
}
sort();
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 92bf429031..230ea200d8 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -351,6 +351,8 @@ protected:
virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange);
+ bool addItemPairs(pairs_list_t panel_list, bool rearrange = true);
+
/**
* Notify parent about changed size of internal controls with "size_changes" action
*
@@ -480,6 +482,7 @@ public:
* Sets up new filter string and filters the list.
*/
void setFilterSubString(const std::string& filter_str);
+ std::string getFilterSubString() { return mFilterSubString; }
/**
* Filters the list, rearranges and notifies parent about shape changes.
@@ -503,6 +506,14 @@ protected:
*/
void updateNoItemsMessage(const std::string& filter_string);
+ /**
+ * Applies visibility acording to action and LLFlatListView settings.
+ *
+ * @param item - item we are changing
+ * @param item - action - parameters to determin visibility from
+ */
+ void updateItemVisibility(LLPanel* item, const LLSD &action);
+
private:
std::string mNoFilteredItemsMsg;
std::string mNoItemsMsg;
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/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
index f5364f4863..e43974bc52 100644
--- a/indra/llui/llfunctorregistry.h
+++ b/indra/llui/llfunctorregistry.h
@@ -53,14 +53,8 @@
template <typename FUNCTOR_TYPE>
class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> >
{
- friend class LLSingleton<LLFunctorRegistry>;
+ LLSINGLETON(LLFunctorRegistry);
LOG_CLASS(LLFunctorRegistry);
-private:
- LLFunctorRegistry() : LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing")
- {
- mMap[LOGFUNCTOR] = log_functor;
- mMap[DONOTHING] = do_nothing;
- }
public:
typedef FUNCTOR_TYPE ResponseFunctor;
@@ -125,6 +119,14 @@ private:
};
template <typename FUNCTOR_TYPE>
+LLFunctorRegistry<FUNCTOR_TYPE>::LLFunctorRegistry() :
+ LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing")
+{
+ mMap[LOGFUNCTOR] = log_functor;
+ mMap[DONOTHING] = do_nothing;
+}
+
+template <typename FUNCTOR_TYPE>
class LLFunctorRegistration
{
public:
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index a245ebe1b9..f772dbc6b4 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -40,7 +40,9 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
public:
struct LayoutStackRegistry : public LLChildRegistry<LayoutStackRegistry>
- {};
+ {
+ LLSINGLETON_EMPTY_CTOR(LayoutStackRegistry);
+ };
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 492c9315d1..becb45fa79 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -163,6 +163,9 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
{
llassert( mMaxLengthBytes > 0 );
+ LLUICtrl::setEnabled(TRUE);
+ setEnabled(p.enabled);
+
mScrollTimer.reset();
mTripleClickTimer.reset();
setText(p.default_text());
@@ -218,6 +221,13 @@ LLLineEditor::~LLLineEditor()
gFocusMgr.releaseFocusIfNeeded( this );
}
+void LLLineEditor::initFromParams(const LLLineEditor::Params& params)
+{
+ LLUICtrl::initFromParams(params);
+ LLUICtrl::setEnabled(TRUE);
+ setEnabled(params.enabled);
+}
+
void LLLineEditor::onFocusReceived()
{
gEditMenuHandler = this;
@@ -2636,10 +2646,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..88468503df 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -108,6 +108,9 @@ public:
Params();
};
+
+ void initFromParams(const LLLineEditor::Params& params);
+
protected:
LLLineEditor(const Params&);
friend class LLUICtrlFactory;
@@ -272,7 +275,7 @@ public:
void setReplaceNewlinesWithSpaces(BOOL replace);
- void setContextMenu(LLContextMenu* new_context_menu);
+ void resetContextMenu() { setContextMenu(NULL); };
private:
// private helper methods
@@ -308,6 +311,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/llmenugl.h b/indra/llui/llmenugl.h
index 628dedb906..c7f7f6848c 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -347,7 +347,9 @@ private:
// child widget registry
struct MenuRegistry : public LLChildRegistry<MenuRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(MenuRegistry);
+};
class LLMenuGL
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 354add0b82..024332ee65 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -884,9 +884,9 @@ class LLNotifications :
public LLSingleton<LLNotifications>,
public LLNotificationChannelBase
{
+ LLSINGLETON(LLNotifications);
LOG_CLASS(LLNotifications);
- friend class LLSingleton<LLNotifications>;
public:
// Needed to clear up RefCounted things prior to actual destruction
@@ -966,8 +966,6 @@ public:
bool isVisibleByRules(LLNotificationPtr pNotification);
private:
- // we're a singleton, so we don't have a public constructor
- LLNotifications();
/*virtual*/ void initSingleton();
void loadPersistentNotifications();
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index c2185f24de..b8f47ef6ba 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -268,8 +268,9 @@ typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;
class LLRegisterPanelClass
: public LLSingleton< LLRegisterPanelClass >
{
+ LLSINGLETON_EMPTY_CTOR(LLRegisterPanelClass);
public:
- // reigister with either the provided builder, or the generic templated builder
+ // register with either the provided builder, or the generic templated builder
void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)
{
mPanelClassesNames[tag] = func;
diff --git a/indra/llui/llresmgr.h b/indra/llui/llresmgr.h
index a652dcd2c0..b19d8d40b8 100644
--- a/indra/llui/llresmgr.h
+++ b/indra/llui/llresmgr.h
@@ -42,9 +42,9 @@ enum LLLOCALE_ID
class LLResMgr : public LLSingleton<LLResMgr>
{
-public:
- LLResMgr();
+ LLSINGLETON(LLResMgr);
+public:
void setLocale( LLLOCALE_ID locale_id );
LLLOCALE_ID getLocale() const { return mLocale; }
diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h
index f64cf43a8e..c4c4d0a136 100644
--- a/indra/llui/llscrollcontainer.h
+++ b/indra/llui/llscrollcontainer.h
@@ -48,7 +48,9 @@ class LLUICtrlFactory;
*****************************************************************************/
struct ScrollContainerRegistry : public LLChildRegistry<ScrollContainerRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(ScrollContainerRegistry);
+};
class LLScrollContainer : public LLUICtrl
{
diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h
index 4ab80195ea..acac589e43 100644
--- a/indra/llui/llspellcheck.h
+++ b/indra/llui/llspellcheck.h
@@ -29,16 +29,15 @@
#include "llsingleton.h"
#include "llui.h"
+#include "llinitdestroyclass.h"
#include <boost/signals2.hpp>
class Hunspell;
class LLSpellChecker : public LLSingleton<LLSpellChecker>, public LLInitClass<LLSpellChecker>
{
- friend class LLSingleton<LLSpellChecker>;
+ LLSINGLETON(LLSpellChecker);
friend class LLInitClass<LLSpellChecker>;
-protected:
- LLSpellChecker();
~LLSpellChecker();
public:
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 8b1ba406c8..d49e216898 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -153,7 +153,7 @@ F32 clamp_precision(F32 value, S32 decimal_precision)
for (S32 i = 0; i < decimal_precision; i++)
clamped_value *= 10.0;
- clamped_value = ll_round((F32)clamped_value);
+ clamped_value = ll_round(clamped_value);
for (S32 i = 0; i < decimal_precision; i++)
clamped_value /= 10.0;
diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h
index bc78d3b5fd..af4db7d7ea 100644
--- a/indra/llui/llstatview.h
+++ b/indra/llui/llstatview.h
@@ -35,7 +35,9 @@ class LLStatBar;
// widget registrars
struct StatViewRegistry : public LLChildRegistry<StatViewRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(StatViewRegistry);
+};
class LLStatView : public LLContainerView
{
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/lltextparser.h b/indra/llui/lltextparser.h
index 400aeeb8be..3d71e40452 100644
--- a/indra/llui/lltextparser.h
+++ b/indra/llui/lltextparser.h
@@ -37,14 +37,14 @@ class LLColor4;
class LLTextParser : public LLSingleton<LLTextParser>
{
+ LLSINGLETON(LLTextParser);
+
public:
typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType;
typedef enum e_highlight_type { PART, ALL } EHighlightType;
typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition;
typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction;
- LLTextParser();
-
LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0);
bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
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/lltooltip.h b/indra/llui/lltooltip.h
index fad127fc4c..0b1fbe5367 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -129,9 +129,10 @@ public:
class LLToolTipMgr : public LLSingleton<LLToolTipMgr>
{
+ LLSINGLETON(LLToolTipMgr);
LOG_CLASS(LLToolTipMgr);
+
public:
- LLToolTipMgr();
void show(const LLToolTip::Params& params);
void show(const std::string& message);
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index aabc7ed2e4..770f13c1c3 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -60,6 +60,7 @@
#include "llflyoutbutton.h"
#include "llsearcheditor.h"
#include "lltoolbar.h"
+#include "llcleanup.h"
// for XUIParse
#include "llquaternion.h"
@@ -208,7 +209,7 @@ void LLUI::initClass(const settings_map_t& settings,
void LLUI::cleanupClass()
{
- LLRender2D::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLRender2D);
}
void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups)
@@ -522,7 +523,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/llui.h b/indra/llui/llui.h
index c727f75c4f..d7151dbee9 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -344,95 +344,6 @@ private:
// Moved LLLocalClipRect to lllocalcliprect.h
-class LLCallbackRegistry
-{
-public:
- typedef boost::signals2::signal<void()> callback_signal_t;
-
- void registerCallback(const callback_signal_t::slot_type& slot)
- {
- mCallbacks.connect(slot);
- }
-
- void fireCallbacks()
- {
- mCallbacks();
- }
-
-private:
- callback_signal_t mCallbacks;
-};
-
-class LLInitClassList :
- public LLCallbackRegistry,
- public LLSingleton<LLInitClassList>
-{
- friend class LLSingleton<LLInitClassList>;
-private:
- LLInitClassList() {}
-};
-
-class LLDestroyClassList :
- public LLCallbackRegistry,
- public LLSingleton<LLDestroyClassList>
-{
- friend class LLSingleton<LLDestroyClassList>;
-private:
- LLDestroyClassList() {}
-};
-
-template<typename T>
-class LLRegisterWith
-{
-public:
- LLRegisterWith(boost::function<void ()> func)
- {
- T::instance().registerCallback(func);
- }
-
- // this avoids a MSVC bug where non-referenced static members are "optimized" away
- // even if their constructors have side effects
- S32 reference()
- {
- S32 dummy;
- dummy = 0;
- return dummy;
- }
-};
-
-template<typename T>
-class LLInitClass
-{
-public:
- LLInitClass() { sRegister.reference(); }
-
- static LLRegisterWith<LLInitClassList> sRegister;
-private:
-
- static void initClass()
- {
- LL_ERRS() << "No static initClass() method defined for " << typeid(T).name() << LL_ENDL;
- }
-};
-
-template<typename T>
-class LLDestroyClass
-{
-public:
- LLDestroyClass() { sRegister.reference(); }
-
- static LLRegisterWith<LLDestroyClassList> sRegister;
-private:
-
- static void destroyClass()
- {
- LL_ERRS() << "No static destroyClass() method defined for " << typeid(T).name() << LL_ENDL;
- }
-};
-
-template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass);
-template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass);
-
// useful parameter blocks
struct TimeIntervalParam : public LLInitParam::ChoiceBlock<TimeIntervalParam>
{
diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h
index 6a7a681d57..44472070cc 100644
--- a/indra/llui/lluicolortable.h
+++ b/indra/llui/lluicolortable.h
@@ -38,7 +38,8 @@ class LLUIColor;
class LLUIColorTable : public LLSingleton<LLUIColorTable>
{
-LOG_CLASS(LLUIColorTable);
+ LLSINGLETON_EMPTY_CTOR(LLUIColorTable);
+ LOG_CLASS(LLUIColorTable);
// consider using sorted vector, can be much faster
typedef std::map<std::string, LLUIColor> string_color_map_t;
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 99553ee0d2..550bee5c70 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -258,18 +258,25 @@ public:
class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLTextInputFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
{
return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->acceptsTextInput(), TRUE);
}
};
-
+
template <typename F, typename DERIVED> class CallbackRegistry : public LLRegistrySingleton<std::string, F, DERIVED >
{};
- class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{};
+ class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>
+ {
+ LLSINGLETON_EMPTY_CTOR(CommitCallbackRegistry);
+ };
// the enable callback registry is also used for visiblity callbacks
- class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{};
+ class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>
+ {
+ LLSINGLETON_EMPTY_CTOR(EnableCallbackRegistry);
+ };
protected:
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 3ce39c947f..03d946f1b7 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -33,6 +33,8 @@
#include "llxuiparser.h"
#include "llstl.h"
#include "lldir.h"
+#include "llsingleton.h"
+#include "llheteromap.h"
class LLView;
@@ -57,22 +59,24 @@ protected:
class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>
{
-protected:
- LLDefaultChildRegistry(){}
- friend class LLSingleton<LLDefaultChildRegistry>;
+ LLSINGLETON_EMPTY_CTOR(LLDefaultChildRegistry);
};
// lookup widget name by type
class LLWidgetNameRegistry
: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(LLWidgetNameRegistry);
+};
// lookup function for generating empty param block by widget type
// this is used for schema generation
//typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
//class LLDefaultParamBlockRegistry
//: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>
-//{};
+//{
+// LLSINGLETON(LLDefaultParamBlockRegistry);
+//};
extern LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP;
extern LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION;
@@ -85,31 +89,15 @@ extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getIn
class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
{
-private:
- friend class LLSingleton<LLUICtrlFactory>;
- LLUICtrlFactory();
+ LLSINGLETON(LLUICtrlFactory);
~LLUICtrlFactory();
// only partial specialization allowed in inner classes, so use extra dummy parameter
template <typename PARAM_BLOCK, int DUMMY>
- class ParamDefaults : public LLSingleton<ParamDefaults<PARAM_BLOCK, DUMMY> >
+ class ParamDefaults
{
public:
- ParamDefaults()
- {
- // look up template file for this param block...
- const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK));
- if (param_block_tag)
- { // ...and if it exists, back fill values using the most specific template first
- PARAM_BLOCK params;
- LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params);
- mPrototype.fillFrom(params);
- }
- // recursively fill from base class param block
- ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get());
-
- }
-
+ ParamDefaults();
const PARAM_BLOCK& get() { return mPrototype; }
private:
@@ -118,9 +106,10 @@ private:
// base case for recursion, there are NO base classes of LLInitParam::BaseBlock
template<int DUMMY>
- class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> >
+ class ParamDefaults<LLInitParam::BaseBlock, DUMMY>
{
public:
+ ParamDefaults();
const LLInitParam::BaseBlock& get() { return mBaseBlock; }
private:
LLInitParam::BaseBlock mBaseBlock;
@@ -132,7 +121,7 @@ public:
template<typename T>
static const typename T::Params& getDefaultParams()
{
- return ParamDefaults<typename T::Params, 0>::instance().get();
+ return instance().mParamDefaultsMap.obtain< ParamDefaults<typename T::Params, 0> >().get();
}
// Does what you want for LLFloaters and LLPanels
@@ -147,7 +136,8 @@ public:
template<typename T>
static T* create(typename T::Params& params, LLView* parent = NULL)
{
- params.fillFrom(ParamDefaults<typename T::Params, 0>::instance().get());
+ params.fillFrom(instance().mParamDefaultsMap.obtain<
+ ParamDefaults<typename T::Params, 0> >().get());
T* widget = createWidgetImpl<T>(params, parent);
if (widget)
@@ -295,8 +285,40 @@ private:
class LLPanel* mDummyPanel;
std::vector<std::string> mFileNames;
+
+ // store ParamDefaults specializations
+ // Each ParamDefaults specialization used to be an LLSingleton in its own
+ // right. But the 2016 changes to the LLSingleton mechanism, making
+ // LLSingleton instances polymorphic, are incompatible with current
+ // LLInitParam::BaseBlock functionality. (Thanks NickyD for spotting
+ // that!) Moreover, instances of the private nested ParamDefaults template
+ // aren't global resources -- which is what LLSingleton is designed for.
+ // This is simply a cache looked up by type. Its lifespan is tied to
+ // LLUICtrlFactory. Use LLHeteroMap for this cache.
+ LLHeteroMap mParamDefaultsMap;
};
+template <typename PARAM_BLOCK, int DUMMY>
+LLUICtrlFactory::ParamDefaults<PARAM_BLOCK, DUMMY>::ParamDefaults()
+{
+ // look up template file for this param block...
+ const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK));
+ if (param_block_tag)
+ { // ...and if it exists, back fill values using the most specific template first
+ PARAM_BLOCK params;
+ LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params);
+ mPrototype.fillFrom(params);
+ }
+ // recursively fill from base class param block
+ ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(
+ LLUICtrlFactory::instance().mParamDefaultsMap.obtain<
+ ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY> >().get());
+
+}
+
+template <int DUMMY>
+LLUICtrlFactory::ParamDefaults<LLInitParam::BaseBlock, DUMMY>::ParamDefaults() {}
+
// this is here to make gcc happy with reference to LLUICtrlFactory
template<typename DERIVED>
template<typename T>
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e4848362a7..b5a31f5118 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);
}
@@ -1370,7 +1377,7 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)
LLUrlEntryEmail::LLUrlEntryEmail()
: LLUrlEntryBase()
{
- mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,6}",
+ mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,63}",
boost::regex::perl | boost::regex::icase);
mMenuName = "menu_url_email.xml";
mTooltip = LLTrans::getString("TooltipEmail");
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 24c3a2b513..efafe543ab 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -62,9 +62,9 @@ void LLUrlRegistryNullCallback(const std::string &url,
///
class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
{
-public:
+ LLSINGLETON(LLUrlRegistry);
~LLUrlRegistry();
-
+public:
/// add a new Url handler to the registry (will be freed on destruction)
/// optionally force it to the front of the list, making it take
/// priority over other regular expression matches for URLs
@@ -89,9 +89,6 @@ public:
bool isUrl(const LLWString &text);
private:
- LLUrlRegistry();
- friend class LLSingleton<LLUrlRegistry>;
-
std::vector<LLUrlEntryBase *> mUrlEntry;
LLUrlEntryBase* mUrlEntryTrusted;
LLUrlEntryBase* mUrlEntryIcon;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index fd7406b653..89ad8138d8 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
@@ -1892,6 +1912,7 @@ private:
class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder>
{
+ LLSINGLETON_EMPTY_CTOR(SortByTabOrder);
/*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const
{
children.sort(CompareByTabOrder(parent->getTabOrder(), parent->getDefaultTabGroup()));
@@ -1915,6 +1936,7 @@ const LLViewQuery & LLView::getTabOrderQuery()
// This class is only used internally by getFocusRootsQuery below.
class LLFocusRootsFilter : public LLQueryFilter, public LLSingleton<LLFocusRootsFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLFocusRootsFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
{
return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot());
diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h
index 375efcc3de..d1059d55de 100644
--- a/indra/llui/llviewereventrecorder.h
+++ b/indra/llui/llviewereventrecorder.h
@@ -44,13 +44,10 @@
class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder>
{
-
- public:
-
- LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton
+ LLSINGLETON(LLViewerEventRecorder);
~LLViewerEventRecorder();
-
+ public:
void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y, std::string mName);
void setMouseLocalCoords(S32 x,S32 y);
void setMouseGlobalCoords(S32 x,S32 y);
diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h
index 9044c4ff29..21bb1be26f 100644
--- a/indra/llui/llviewquery.h
+++ b/indra/llui/llviewquery.h
@@ -54,31 +54,37 @@ public:
class LLLeavesFilter : public LLQueryFilter, public LLSingleton<LLLeavesFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLLeavesFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
class LLRootsFilter : public LLQueryFilter, public LLSingleton<LLRootsFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLRootsFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLVisibleFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLEnabledFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLTabStopFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
class LLCtrlFilter : public LLQueryFilter, public LLSingleton<LLCtrlFilter>
{
+ LLSINGLETON_EMPTY_CTOR(LLCtrlFilter);
/*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
};
diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h
index ad2a39cab7..eb0eac8194 100644
--- a/indra/llui/llxuiparser.h
+++ b/indra/llui/llxuiparser.h
@@ -41,7 +41,9 @@ class LLView;
// lookup widget type by name
class LLWidgetTypeRegistry
: public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(LLWidgetTypeRegistry);
+};
// global static instance for registering all widget types
@@ -51,7 +53,9 @@ typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;
class LLChildRegistryRegistry
: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry>
-{};
+{
+ LLSINGLETON_EMPTY_CTOR(LLChildRegistryRegistry);
+};
class LLXSDWriter : public LLInitParam::Parser
{
@@ -60,7 +64,7 @@ public:
void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace);
/*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; }
-
+ /*virtual*/ std::string getCurrentFileName() { return LLStringUtil::null; }
LLXSDWriter();
~LLXSDWriter();
@@ -98,6 +102,7 @@ public:
typedef LLInitParam::Parser::name_stack_t name_stack_t;
/*virtual*/ std::string getCurrentElementName();
+ /*virtual*/ std::string getCurrentFileName() { return mCurFileName; }
/*virtual*/ void parserWarning(const std::string& message);
/*virtual*/ void parserError(const std::string& message);
@@ -200,6 +205,7 @@ public:
virtual ~LLSimpleXUIParser();
/*virtual*/ std::string getCurrentElementName();
+ /*virtual*/ std::string getCurrentFileName() { return mCurFileName; }
/*virtual*/ void parserWarning(const std::string& message);
/*virtual*/ void parserError(const std::string& message);
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index f01178c374..338be1808d 100644..100755
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -31,6 +31,7 @@
#include "llcachename.h"
#include "lluuid.h"
#include "message.h"
+#include "llpounceable.h"
#include <string>
@@ -165,7 +166,7 @@ LLFontGL* LLFontGL::getFontDefault()
char const* const _PREHASH_AgentData = (char *)"AgentData";
char const* const _PREHASH_AgentID = (char *)"AgentID";
-LLMessageSystem* gMessageSystem = NULL;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
//
// Stub implementation for LLMessageSystem
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/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp
index 1cc0e819db..db0eac7031 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -2114,6 +2114,17 @@ void LLVFS::dumpFiles()
LL_INFOS() << "Extracted " << files_extracted << " files out of " << mFileBlocks.size() << LL_ENDL;
}
+time_t LLVFS::creationTime()
+{
+ llstat data_file_stat;
+ int errors = LLFile::stat(mDataFilename, &data_file_stat);
+ if (0 == errors)
+ {
+ return data_file_stat.st_ctime;
+ }
+ return 0;
+}
+
//============================================================================
// protected
//============================================================================
diff --git a/indra/llvfs/llvfs.h b/indra/llvfs/llvfs.h
index 39f31a221b..dca5ff4ad5 100644
--- a/indra/llvfs/llvfs.h
+++ b/indra/llvfs/llvfs.h
@@ -127,6 +127,7 @@ public:
void dumpStatistics();
void listFiles();
void dumpFiles();
+ time_t creationTime();
protected:
void removeFileBlock(LLVFSFileBlock *fileblock);
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/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 875ffe4cd4..4086db8e52 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
//
@@ -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/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index 28a8a5886a..4eb29c98f9 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -501,6 +501,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
LLCEFLib::LLCEFLibSettings settings;
settings.initial_width = 1024;
settings.initial_height = 1024;
+ 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;
diff --git a/indra/media_plugins/cef/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp
index 0cfb810906..c9ea3ed597 100644
--- a/indra/media_plugins/cef/windows_volume_catcher.cpp
+++ b/indra/media_plugins/cef/windows_volume_catcher.cpp
@@ -31,17 +31,16 @@
#include "llsingleton.h"
class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl>
{
-friend LLSingleton<VolumeCatcherImpl>;
+ LLSINGLETON(VolumeCatcherImpl);
+ // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance.
+ ~VolumeCatcherImpl();
+
public:
void setVolume(F32 volume);
void setPan(F32 pan);
private:
- // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance.
- VolumeCatcherImpl();
- ~VolumeCatcherImpl();
-
typedef void (WINAPI *set_volume_func_t)(F32);
typedef void (WINAPI *set_mute_func_t)(bool);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c8051bc9af..919cd6a865 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -261,7 +261,8 @@ set(viewer_SOURCE_FILES
llfloatermodeluploadbase.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
- llfloaternotificationstabbed.cpp
+ llfloaternotificationstabbed.cpp
+ llfloateroutfitphotopreview.cpp
llfloateroutfitsnapshot.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
@@ -878,7 +879,8 @@ set(viewer_HEADER_FILES
llfloatermodeluploadbase.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
- llfloaternotificationstabbed.h
+ llfloaternotificationstabbed.h
+ llfloateroutfitphotopreview.h
llfloateroutfitsnapshot.h
llfloaterobjectweights.h
llfloateropenobject.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 4d0dcda01c..de197cc337 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-4.1.2
+4.1.3
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index a0d3dc0f99..9bc0a7c701 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -282,4 +282,14 @@
is_running_function="Floater.IsOpen"
is_running_parameters="camera"
/>
+ <command name="reporter"
+ available_in_toybox="true"
+ icon="Command_Report_Abuse_Icon"
+ label_ref="Command_Report_Abuse_Label"
+ tooltip_ref="Command_Report_Abuse_Tooltip"
+ execute_function="Floater.ToggleOrBringToFront"
+ execute_parameters="reporter"
+ is_running_function="Floater.IsOpen"
+ is_running_parameters="reporter"
+ />
</commands>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2d3c885522..399a4bf5ac 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4515,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>
@@ -4636,6 +4614,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>IgnoreFOVZoomForLODs</key>
+ <map>
+ <key>Comment</key>
+ <string>Ignore zoom effect(CTRL+0) when calculating lods.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>IgnoreAllNotifications</key>
<map>
<key>Comment</key>
@@ -4881,7 +4870,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>
@@ -5263,6 +5252,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>LastAppearanceTab</key>
+ <map>
+ <key>Comment</key>
+ <string>Last selected tab in appearance floater</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>LastMediaSettingsTab</key>
<map>
<key>Comment</key>
@@ -6629,6 +6629,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>MuteListLimit</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum number of entries in the mute list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1000</integer>
+ </map>
<key>MyOutfitsAutofill</key>
<map>
<key>Comment</key>
@@ -7951,6 +7962,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>
@@ -10103,6 +10125,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>
@@ -10115,6 +10148,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>
@@ -12803,6 +12880,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>
@@ -13298,6 +13386,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>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index fd6b1b5b3f..eee13fb28e 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -242,6 +242,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>PreviousScreenshotForReport</key>
+ <map>
+ <key>Comment</key>
+ <string>Use Previous Screenshot for Abuse report</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<!-- Settings below are for back compatibility only.
They are not used in current viewer anymore. But they can't be removed to avoid
influence on previous versions of the viewer in case of settings are not used or default value
@@ -251,7 +262,7 @@
<key>LogChat</key>
<map>
<key>Comment</key>
- <string>Log Chat</string>
+ <string>Obsolete - this setting is no longer used and has no effect.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -262,7 +273,7 @@
<key>LogChatIM</key>
<map>
<key>Comment</key>
- <string>Log Incoming Instant Messages with Chat</string>
+ <string>Obsolete - this setting is no longer used and has no effect.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -273,7 +284,7 @@
<key>LogChatTimestamp</key>
<map>
<key>Comment</key>
- <string>Log Timestamp of Chat</string>
+ <string>Obsolete - this setting is no longer used and has no effect.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -281,6 +292,7 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <!-- End of back compatibility settings -->
<key>TranslatingEnabled</key>
<map>
<key>Comment</key>
@@ -336,6 +348,5 @@
<key>Value</key>
<integer>1</integer>
</map>
- <!-- End of back compatibility settings -->
</map>
</llsd>
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index f251ceffd4..55e1d19f05 100644
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -58,9 +58,9 @@ protected:
//===============================================================================
class LLAccountingCostManager : public LLSingleton<LLAccountingCostManager>
{
+ LLSINGLETON(LLAccountingCostManager);
+
public:
- //Ctor
- LLAccountingCostManager();
//Store an object that will be eventually fetched
void addObject( const LLUUID& objectID );
//Request quotas for object list
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/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h
index abf7027ed2..f981e08ff7 100644
--- a/indra/newview/llagentpicksinfo.h
+++ b/indra/newview/llagentpicksinfo.h
@@ -36,14 +36,12 @@ struct LLAvatarPicks;
*/
class LLAgentPicksInfo : public LLSingleton<LLAgentPicksInfo>
{
+ LLSINGLETON(LLAgentPicksInfo);
+ virtual ~LLAgentPicksInfo();
+
class LLAgentPicksObserver;
public:
-
- LLAgentPicksInfo();
-
- virtual ~LLAgentPicksInfo();
-
/**
* Requests number of picks from server.
*
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..2710262910 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -38,6 +38,7 @@
#include "llviewerinventory.h"
#include "llavatarappearancedefines.h"
#include "llwearabledata.h"
+#include "llinitdestroyclass.h"
class LLInventoryItem;
class LLVOAvatarSelf;
@@ -185,6 +186,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/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index be8877328d..8188c6c3f9 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -58,7 +58,7 @@
frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self
selector:@selector(oneFrame) userInfo:nil repeats:YES];
} else {
- handleQuit();
+ exit(0);
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index ff5439d610..2d84251da0 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1875,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;
}
@@ -3477,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;
@@ -3503,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"))
@@ -3942,7 +3942,6 @@ LLAppearanceMgr::LLAppearanceMgr():
mAttachmentInvLinkEnabled(false),
mOutfitIsDirty(false),
mOutfitLocked(false),
- mInFlightCounter(0),
mInFlightTimer(),
mIsInUpdateAppearanceFromCOF(false),
mOutstandingAppearanceBakeRequest(false),
@@ -3969,6 +3968,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)
{
@@ -3995,6 +3998,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)
@@ -4015,6 +4020,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 2e570b9188..5948dd870c 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -42,9 +42,10 @@ class LLOutfitUnLockTimer;
class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
{
+ LLSINGLETON(LLAppearanceMgr);
+ ~LLAppearanceMgr();
LOG_CLASS(LLAppearanceMgr);
- friend class LLSingleton<LLAppearanceMgr>;
friend class LLOutfitUnLockTimer;
public:
@@ -229,6 +230,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:
@@ -237,10 +242,6 @@ private:
static void debugAppearanceUpdateCOF(const LLSD& content);
std::string mAppearanceServiceURL;
-
-protected:
- LLAppearanceMgr();
- ~LLAppearanceMgr();
private:
@@ -268,10 +269,11 @@ private:
* to avoid unsynchronized outfit state or performing duplicate operations.
*/
bool mOutfitLocked;
- S32 mInFlightCounter;
LLTimer mInFlightTimer;
static bool mActive;
+ attachments_changed_signal_t mAttachmentsChangeSignal;
+
LLUUID mCOFImageID;
std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f043155753..afe23aa6d8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -233,6 +233,7 @@
#include "llsecapi.h"
#include "llmachineid.h"
#include "llmainlooprepeater.h"
+#include "llcleanup.h"
#include "llcoproceduremanager.h"
#include "llviewereventrecorder.h"
@@ -387,6 +388,7 @@ const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
*/
class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList>
{
+ LLSINGLETON_EMPTY_CTOR(LLDeferredTaskList);
LOG_CLASS(LLDeferredTaskList);
friend class LLAppViewer;
@@ -701,7 +703,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)
{
@@ -736,7 +739,7 @@ LLAppViewer::LLAppViewer()
LLAppViewer::~LLAppViewer()
{
delete mSettingsLocationList;
- LLViewerEventRecorder::instance().~LLViewerEventRecorder();
+ LLViewerEventRecorder::deleteSingleton();
LLLoginInstance::instance().setUpdaterService(0);
@@ -1124,17 +1127,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
@@ -1222,6 +1231,8 @@ 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();
@@ -1734,7 +1745,7 @@ bool LLAppViewer::cleanup()
gTransferManager.cleanup();
#endif
- LLLocalBitmapMgr::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLLocalBitmapMgr);
// Note: this is where gWorldMap used to be deleted.
@@ -1843,11 +1854,11 @@ bool LLAppViewer::cleanup()
LLViewerObject::cleanupVOClasses();
- LLAvatarAppearance::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLAvatarAppearance);
- LLAvatarAppearance::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLAvatarAppearance);
- LLPostProcess::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLPostProcess);
LLTracker::cleanupInstance();
@@ -1873,12 +1884,12 @@ bool LLAppViewer::cleanup()
//end_messaging_system();
- LLFollowCamMgr::cleanupClass();
- //LLVolumeMgr::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLFollowCamMgr);
+ //SUBSYSTEM_CLEANUP(LLVolumeMgr);
LLPrimitive::cleanupVolumeManager();
- LLWorldMapView::cleanupClass();
- LLFolderViewItem::cleanupClass();
- LLUI::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLWorldMapView);
+ SUBSYSTEM_CLEANUP(LLFolderViewItem);
+ SUBSYSTEM_CLEANUP(LLUI);
//
// Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
@@ -1887,7 +1898,7 @@ bool LLAppViewer::cleanup()
//
LL_INFOS() << "Cleaning up VFS" << LL_ENDL;
- LLVFile::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLVFile);
LL_INFOS() << "Saving Data" << LL_ENDL;
@@ -1990,9 +2001,9 @@ bool LLAppViewer::cleanup()
// Non-LLCurl libcurl library
mAppCoreHttp.cleanup();
- LLFilePickerThread::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLFilePickerThread);
- //MUST happen AFTER LLCurl::cleanupClass
+ //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
delete sTextureCache;
sTextureCache = NULL;
delete sTextureFetch;
@@ -2016,22 +2027,22 @@ bool LLAppViewer::cleanup()
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
}
- LLMetricPerformanceTesterBasic::cleanClass() ;
+ SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ;
LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL;
//Note:
- //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
+ //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown()
//because some new image might be generated during cleaning up media. --bao
- LLViewerMedia::cleanupClass();
- LLViewerParcelMedia::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLViewerMedia);
+ SUBSYSTEM_CLEANUP(LLViewerParcelMedia);
gTextureList.shutdown(); // shutdown again in case a callback added something
LLUIImageList::getInstance()->cleanUp();
// This should eventually be done in LLAppViewer
- LLImage::cleanupClass();
- LLVFSThread::cleanupClass();
- LLLFSThread::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLImage);
+ SUBSYSTEM_CLEANUP(LLVFSThread);
+ SUBSYSTEM_CLEANUP(LLLFSThread);
#ifndef LL_RELEASE_FOR_DOWNLOAD
LL_INFOS() << "Auditing VFS" << LL_ENDL;
@@ -2074,10 +2085,10 @@ bool LLAppViewer::cleanup()
LL_INFOS() << "File launched." << LL_ENDL;
}
LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
- LLProxy::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLProxy);
LLCore::LLHttp::cleanup();
- LLWearableType::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLWearableType);
LLMainLoopRepeater::instance().stop();
@@ -2089,10 +2100,34 @@ bool LLAppViewer::cleanup()
LLError::LLCallStacks::cleanup();
removeMarkerFiles();
-
- LL_INFOS() << "Goodbye!" << LL_ENDL;
- removeDumpDir();
+ // It's not at first obvious where, in this long sequence, generic cleanup
+ // calls OUGHT to go. So let's say this: as we migrate cleanup from
+ // explicit hand-placed calls into the generic mechanism, eventually
+ // all cleanup will get subsumed into the generic calls. So the calls you
+ // still see above are calls that MUST happen before the generic cleanup
+ // kicks in.
+
+ // This calls every remaining LLSingleton's cleanupSingleton() method.
+ // This method should perform any cleanup that might take significant
+ // realtime, or might throw an exception.
+ LLSingletonBase::cleanupAll();
+
+ // This calls every remaining LLSingleton's deleteSingleton() method.
+ // No class destructor should perform any cleanup that might take
+ // significant realtime, or throw an exception.
+ // LLSingleton machinery includes a last-gasp implicit deleteAll() call,
+ // so this explicit call shouldn't strictly be necessary. However, by the
+ // time the runtime engages that implicit call, it may already have
+ // destroyed things like std::cerr -- so the implicit deleteAll() refrains
+ // from logging anything. Since both cleanupAll() and deleteAll() call
+ // their respective cleanup methods in computed dependency order, it's
+ // probably useful to be able to log that order.
+ LLSingletonBase::deleteAll();
+
+ LL_INFOS() << "Goodbye!" << LL_ENDL;
+
+ removeDumpDir();
// return 0;
return true;
@@ -2473,7 +2508,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);
}
@@ -3130,7 +3168,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);
@@ -3313,6 +3352,26 @@ LLSD LLAppViewer::getViewerInfo() const
info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
+ // Settings
+
+ LLRect window_rect = gViewerWindow->getWindowRectRaw();
+ info["WINDOW_WIDTH"] = window_rect.getWidth();
+ info["WINDOW_HEIGHT"] = window_rect.getHeight();
+ info["FONT_SIZE_ADJUSTMENT"] = gSavedSettings.getF32("FontScreenDPI");
+ info["UI_SCALE"] = gSavedSettings.getF32("UIScaleFactor");
+ info["DRAW_DISTANCE"] = gSavedSettings.getF32("RenderFarClip");
+ info["NET_BANDWITH"] = gSavedSettings.getF32("ThrottleBandwidthKBPS");
+ info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor");
+ info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance");
+ info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled";
+ info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory");
+
+ LLSD substitution;
+ substitution["datetime"] = (S32)(gVFS ? gVFS->creationTime() : 0);
+ info["VFS_TIME"] = LLTrans::getString("AboutTime", substitution);
+
+ // Libraries
+
info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
bool want_fullname = true;
info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
@@ -3432,7 +3491,9 @@ std::string LLAppViewer::getViewerInfoString() const
{
support << "\n" << LLTrans::getString("AboutDriver", args);
}
- support << "\n" << LLTrans::getString("AboutLibs", args);
+ support << "\n" << LLTrans::getString("AboutOGL", args);
+ support << "\n\n" << LLTrans::getString("AboutSettings", args);
+ support << "\n\n" << LLTrans::getString("AboutLibs", args);
if (info.has("COMPILER"))
{
support << "\n" << LLTrans::getString("AboutCompiler", args);
@@ -5483,9 +5544,12 @@ void LLAppViewer::disconnectViewer()
}
saveNameCache();
- LLExperienceCache *expCache = LLExperienceCache::getIfExists();
- if (expCache)
- expCache->cleanup();
+ if (LLExperienceCache::instanceExists())
+ {
+ // TODO: LLExperienceCache::cleanup() logic should be moved to
+ // cleanupSingleton().
+ LLExperienceCache::instance().cleanup();
+ }
// close inventory interface, close all windows
LLSidepanelInventory::cleanup();
@@ -5801,6 +5865,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 f7c1bb58b4..948d316009 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -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.
@@ -315,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/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index af0cd27fd5..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
@@ -567,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/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h
index bb7d35edbc..a4ef762e8b 100644
--- a/indra/newview/llattachmentsmgr.h
+++ b/indra/newview/llattachmentsmgr.h
@@ -62,6 +62,9 @@ class LLViewerInventoryItem;
//--------------------------------------------------------------------------------
class LLAttachmentsMgr: public LLSingleton<LLAttachmentsMgr>
{
+ LLSINGLETON(LLAttachmentsMgr);
+ virtual ~LLAttachmentsMgr();
+
public:
// Stores info for attachments that will be requested during idle.
struct AttachmentsInfo
@@ -72,9 +75,6 @@ public:
};
typedef std::deque<AttachmentsInfo> attachments_vec_t;
- LLAttachmentsMgr();
- virtual ~LLAttachmentsMgr();
-
void addAttachmentRequest(const LLUUID& item_id,
const U8 attachment_pt,
const BOOL add);
diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h
index 9eecc2d981..23cc313646 100644
--- a/indra/newview/llautoreplace.h
+++ b/indra/newview/llautoreplace.h
@@ -191,6 +191,7 @@ class LLAutoReplaceSettings
*/
class LLAutoReplace : public LLSingleton<LLAutoReplace>
{
+ LLSINGLETON(LLAutoReplace);
public:
/// Callback that provides the hook for use in text entry methods
void autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text);
@@ -202,8 +203,6 @@ public:
void setSettings(const LLAutoReplaceSettings& settings);
private:
- friend class LLSingleton<LLAutoReplace>;
- LLAutoReplace();
/*virtual*/ void initSingleton();
LLAutoReplaceSettings mSettings; ///< configuration information
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index a6e745448a..36e95c07f4 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -689,6 +689,8 @@ namespace action_give_inventory
struct LLShareInfo : public LLSingleton<LLShareInfo>
{
+ LLSINGLETON_EMPTY_CTOR(LLShareInfo);
+ public:
std::vector<LLAvatarName> mAvatarNames;
uuid_vec_t mAvatarUuids;
};
@@ -950,15 +952,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/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 5b5720f4ac..a1dacd1a27 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -37,6 +37,8 @@ class LLAvatarName;
class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
{
+ LLSINGLETON(LLAvatarIconIDCache);
+
public:
struct LLAvatarIconIDCacheItem
{
@@ -46,10 +48,6 @@ public:
bool expired();
};
- LLAvatarIconIDCache()
- : mFilename("avatar_icons_cache.txt")
- {}
-
void load ();
void save ();
@@ -64,6 +62,11 @@ protected:
std::map<LLUUID,LLAvatarIconIDCacheItem> mCache;//we cache only LLUID and time
};
+inline
+LLAvatarIconIDCache::LLAvatarIconIDCache()
+ : mFilename("avatar_icons_cache.txt")
+{}
+
namespace LLAvatarIconCtrlEnums
{
enum ESymbolPos
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index 1dcd2c9b90..d5c5c75c69 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -187,13 +187,12 @@ public:
class LLAvatarPropertiesProcessor
: public LLSingleton<LLAvatarPropertiesProcessor>
{
-public:
-
- LLAvatarPropertiesProcessor();
+ LLSINGLETON(LLAvatarPropertiesProcessor);
virtual ~LLAvatarPropertiesProcessor();
+public:
void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
-
+
void removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
// Request various types of avatar data. Duplicate requests will be
diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h
index 870ef4f394..6b5fa7bc35 100644
--- a/indra/newview/llavatarrenderinfoaccountant.h
+++ b/indra/newview/llavatarrenderinfoaccountant.h
@@ -38,13 +38,13 @@ class LLViewerRegion;
// that is sent to or fetched from regions.
class LLAvatarRenderInfoAccountant : public LLSingleton<LLAvatarRenderInfoAccountant>
{
+ LLSINGLETON(LLAvatarRenderInfoAccountant);
+ ~LLAvatarRenderInfoAccountant();
+
private:
LOG_CLASS(LLAvatarRenderInfoAccountant);
public:
- LLAvatarRenderInfoAccountant();
- ~LLAvatarRenderInfoAccountant();
-
void sendRenderInfoToRegion(LLViewerRegion * regionp);
void getRenderInfoFromRegion(LLViewerRegion * regionp);
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..ec17b3d9e6 100644
--- a/indra/newview/llavatarrendernotifier.h
+++ b/indra/newview/llavatarrendernotifier.h
@@ -33,13 +33,43 @@
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>
{
-public:
- LLAvatarRenderNotifier();
+ LLSINGLETON(LLAvatarRenderNotifier);
+public:
void displayNotification(bool show_over_limit);
bool isNotificationVisible();
@@ -81,4 +111,36 @@ private:
S32 mLastOutfitRezStatus;
};
+// Class to notify user about heavy set of HUD
+class LLHUDRenderNotifier : public LLSingleton<LLHUDRenderNotifier>
+{
+ LLSINGLETON(LLHUDRenderNotifier);
+ ~LLHUDRenderNotifier();
+
+public:
+ 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/llchannelmanager.h b/indra/newview/llchannelmanager.h
index a5de8a5327..8b9d0dda8b 100644
--- a/indra/newview/llchannelmanager.h
+++ b/indra/newview/llchannelmanager.h
@@ -43,6 +43,9 @@ namespace LLNotificationsUI
*/
class LLChannelManager : public LLSingleton<LLChannelManager>
{
+ LLSINGLETON(LLChannelManager);
+ virtual ~LLChannelManager();
+
public:
@@ -65,9 +68,6 @@ public:
}
};
- LLChannelManager();
- virtual ~LLChannelManager();
-
// On LoginCompleted - show StartUp toast
void onLoginCompleted();
// removes a channel intended for the startup toast and allows other channels to show their toasts
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/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index cfc62c07b6..f5721fb348 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -240,6 +240,32 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
}
}
+ S32 chars_in_line = mMsgText->getRect().getWidth() / messageFont->getWidth("c");
+ S32 max_lines = notification["available_height"].asInteger() / (mMsgText->getTextPixelHeight() + 4);
+ S32 new_line_chars = std::count(messageText.begin(), messageText.end(), '\n');
+ S32 lines_count = (messageText.size() - new_line_chars) / chars_in_line + new_line_chars + 1;
+
+ //Remove excessive chars if message is not fit in available height. MAINT-6891
+ if(lines_count > max_lines)
+ {
+ while(lines_count > max_lines)
+ {
+ std::size_t nl_pos = messageText.rfind('\n');
+ if (nl_pos != std::string::npos)
+ {
+ nl_pos = nl_pos > messageText.length() - chars_in_line? nl_pos : messageText.length() - chars_in_line;
+ messageText.erase(messageText.begin() + nl_pos, messageText.end());
+ }
+ else
+ {
+ messageText.erase(messageText.end() - chars_in_line, messageText.end());
+ }
+ new_line_chars = std::count(messageText.begin(), messageText.end(), '\n');
+ lines_count = (messageText.size() - new_line_chars) / chars_in_line + new_line_chars;
+ }
+ messageText += " ...";
+ }
+
//append text
{
LLStyle::Params style_params;
diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp
index 254e3f61a8..c4f959bfa9 100644
--- a/indra/newview/llchicletbar.cpp
+++ b/indra/newview/llchicletbar.cpp
@@ -38,7 +38,7 @@ namespace
const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel";
}
-LLChicletBar::LLChicletBar(const LLSD&)
+LLChicletBar::LLChicletBar()
: mChicletPanel(NULL),
mToolbarStack(NULL)
{
diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h
index 956c82cb77..6c521dc1d5 100644
--- a/indra/newview/llchicletbar.h
+++ b/indra/newview/llchicletbar.h
@@ -38,8 +38,9 @@ class LLChicletBar
: public LLSingleton<LLChicletBar>
, public LLPanel
{
+ LLSINGLETON(LLChicletBar);
LOG_CLASS(LLChicletBar);
- friend class LLSingleton<LLChicletBar>;
+
public:
BOOL postBuild();
@@ -82,8 +83,6 @@ private:
void fitWithTopInfoBar();
protected:
- LLChicletBar(const LLSD& key = LLSD());
-
LLChicletPanel* mChicletPanel;
LLLayoutStack* mToolbarStack;
};
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/llconversationlog.h b/indra/newview/llconversationlog.h
index 62f08144b9..035cbcb945 100644
--- a/indra/newview/llconversationlog.h
+++ b/indra/newview/llconversationlog.h
@@ -109,7 +109,7 @@ private:
class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver
{
- friend class LLSingleton<LLConversationLog>;
+ LLSINGLETON(LLConversationLog);
public:
void removeConversation(const LLConversation& conversation);
@@ -157,7 +157,6 @@ public:
private:
- LLConversationLog();
virtual ~LLConversationLog()
{
if (mAvatarNameCacheConnection.connected())
diff --git a/indra/newview/lldaycyclemanager.h b/indra/newview/lldaycyclemanager.h
index 3d2144960d..04db9d5dac 100644
--- a/indra/newview/lldaycyclemanager.h
+++ b/indra/newview/lldaycyclemanager.h
@@ -40,6 +40,7 @@
*/
class LLDayCycleManager : public LLSingleton<LLDayCycleManager>
{
+ LLSINGLETON_EMPTY_CTOR(LLDayCycleManager);
LOG_CLASS(LLDayCycleManager);
public:
@@ -66,7 +67,6 @@ public:
boost::signals2::connection setModifyCallback(const modify_signal_t::slot_type& cb);
private:
- friend class LLSingleton<LLDayCycleManager>;
/*virtual*/ void initSingleton();
void loadAllPresets();
diff --git a/indra/newview/lldeferredsounds.h b/indra/newview/lldeferredsounds.h
index bf1eb62957..33f02b3521 100644
--- a/indra/newview/lldeferredsounds.h
+++ b/indra/newview/lldeferredsounds.h
@@ -33,7 +33,7 @@ struct SoundData;
class LLDeferredSounds : public LLSingleton<LLDeferredSounds>
{
-private:
+ LLSINGLETON_EMPTY_CTOR(LLDeferredSounds);
std::vector<SoundData> soundVector;
public:
//Add sounds to be played once progress bar is hidden (such as after teleport or loading screen)
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 7836e2cb94..7d2712eec7 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.cpp
+++ b/indra/newview/lldonotdisturbnotificationstorage.cpp
@@ -69,8 +69,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick()
}
LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
- : LLSingleton<LLDoNotDisturbNotificationStorage>()
- , LLNotificationStorage("")
+ : LLNotificationStorage("")
, mDirty(false)
{
nameToPayloadParameterMap[toastName] = "SESSION_ID";
diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h
index 6e68b0d1be..e6cb7835e3 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.h
+++ b/indra/newview/lldonotdisturbnotificationstorage.h
@@ -47,14 +47,14 @@ public:
class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage
{
+ LLSINGLETON(LLDoNotDisturbNotificationStorage);
+ ~LLDoNotDisturbNotificationStorage();
+
LOG_CLASS(LLDoNotDisturbNotificationStorage);
public:
static const char * toastName;
static const char * offerName;
- LLDoNotDisturbNotificationStorage();
- ~LLDoNotDisturbNotificationStorage();
-
void initialize();
bool getDirty();
void resetDirty();
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 84ead0bdde..60056ac21d 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -401,7 +401,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
if ((params.mVertexBuffer->getTypeMask() & mask) != mask)
{ //FIXME!
- LL_WARNS() << "Missing required components, skipping render batch." << LL_ENDL;
+ LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask
+ << " present: " << (params.mVertexBuffer->getTypeMask() & mask)
+ << ". Skipping render batch." << LL_ENDL;
continue;
}
diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp
index a626ad1bff..b97e483fd9 100644
--- a/indra/newview/llenvmanager.cpp
+++ b/indra/newview/llenvmanager.cpp
@@ -609,10 +609,15 @@ bool LLEnvManagerNew::useRegionSky()
return true;
}
- // *TODO: Support fixed sky from region.
-
- // Otherwise apply region day cycle.
+ // Otherwise apply region day cycle/skies.
LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
+
+ // *TODO: Support fixed sky from region. Just do sky reset for now.
+ if (region_settings.getSkyMap().size() == 1)
+ {
+ // Region is set to fixed sky. Reset.
+ useSkyParams(region_settings.getSkyMap().beginMap()->second);
+ }
return useDayCycleParams(
region_settings.getWLDayCycle(),
LLEnvKey::SCOPE_REGION,
diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h
index c7877303fc..6a0a267f4e 100644
--- a/indra/newview/llenvmanager.h
+++ b/indra/newview/llenvmanager.h
@@ -162,14 +162,13 @@ public:
*/
class LLEnvManagerNew : public LLSingleton<LLEnvManagerNew>
{
+ LLSINGLETON(LLEnvManagerNew);
LOG_CLASS(LLEnvManagerNew);
public:
typedef boost::signals2::signal<void()> prefs_change_signal_t;
typedef boost::signals2::signal<void()> region_settings_change_signal_t;
typedef boost::signals2::signal<void(bool)> region_settings_applied_signal_t;
- LLEnvManagerNew();
-
// getters to access user env. preferences
bool getUseRegionSettings() const;
bool getUseDayCycle() const;
@@ -231,7 +230,6 @@ public:
void onRegionSettingsApplyResponse(bool ok);
private:
- friend class LLSingleton<LLEnvManagerNew>;
/*virtual*/ void initSingleton();
void loadUserPrefs();
diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h
index fcfbd1ce7d..e7a6a2a725 100644
--- a/indra/newview/llestateinfomodel.h
+++ b/indra/newview/llestateinfomodel.h
@@ -38,6 +38,7 @@ class LLMessageSystem;
*/
class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>
{
+ LLSINGLETON(LLEstateInfoModel);
LOG_CLASS(LLEstateInfoModel);
public:
@@ -73,11 +74,8 @@ public:
protected:
typedef std::vector<std::string> strings_t;
- friend class LLSingleton<LLEstateInfoModel>;
friend class LLDispatchEstateUpdateInfo;
- LLEstateInfoModel();
-
/// refresh model with data from the incoming server message
void update(const strings_t& strings);
diff --git a/indra/newview/llexperiencelog.h b/indra/newview/llexperiencelog.h
index ac227db336..09e0cd8821 100644
--- a/indra/newview/llexperiencelog.h
+++ b/indra/newview/llexperiencelog.h
@@ -33,6 +33,7 @@
class LLExperienceLog : public LLSingleton<LLExperienceLog>
{
+ LLSINGLETON(LLExperienceLog);
public:
typedef boost::signals2::signal<void(LLSD&)>
callback_signal_t;
@@ -62,7 +63,6 @@ public:
void setEventsToSave(LLSD new_events){mEventsToSave = new_events; }
bool isNotExpired(std::string& date);
protected:
- LLExperienceLog();
void handleExperienceMessage(LLSD& message);
@@ -81,7 +81,6 @@ protected:
bool mNotifyNewEvent;
friend class LLExperienceLogDispatchHandler;
- friend class LLSingleton<LLExperienceLog>;
};
diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h
index 2a2cdb5499..7fd4070f54 100644
--- a/indra/newview/llfacebookconnect.h
+++ b/indra/newview/llfacebookconnect.h
@@ -43,6 +43,8 @@ class LLEventPump;
*/
class LLFacebookConnect : public LLSingleton<LLFacebookConnect>
{
+ LLSINGLETON(LLFacebookConnect);
+ ~LLFacebookConnect() {};
LOG_CLASS(LLFacebookConnect);
public:
enum EConnectionState
@@ -86,10 +88,7 @@ public:
void openFacebookWeb(std::string url);
private:
- friend class LLSingleton<LLFacebookConnect>;
- LLFacebookConnect();
- ~LLFacebookConnect() {};
std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);
EConnectionState mConnectionState;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 4a059fdc67..fabf5f09f7 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -238,7 +238,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
{
return TRUE;
}
- else if (mHoverBarIndex == -1)
+ else if (mHoverBarIndex < 0)
{
mHoverBarIndex = 0;
}
@@ -260,7 +260,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
{
hover_bar = &bar;
if (bar.mTimeBlock->getTreeNode().mCollapsed)
- {
+ {
// stop on first collapsed BlockTimerStatHandle, since we can't select any children
break;
}
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 2115f77cf3..cac32c7f2a 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -34,6 +34,7 @@
#include "llinventoryobserver.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
+#include "llinitdestroyclass.h"
class LLMenuItemCallGL;
class LLToggleableMenu;
@@ -173,6 +174,7 @@ private:
class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
, public LLDestroyClass<LLFavoritesOrderStorage>
{
+ LLSINGLETON(LLFavoritesOrderStorage);
LOG_CLASS(LLFavoritesOrderStorage);
public:
/**
@@ -221,10 +223,6 @@ public:
std::map<LLUUID,std::string> mFavoriteNames;
private:
- friend class LLSingleton<LLFavoritesOrderStorage>;
- LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); }
- ~LLFavoritesOrderStorage() {}
-
/**
* Removes sort indexes for items which are not in Favorites bar for now.
*/
@@ -274,4 +272,10 @@ private:
};
};
+
+inline
+LLFavoritesOrderStorage::LLFavoritesOrderStorage() :
+ mIsDirty(false), mUpdateRequired(false)
+{ load(); }
+
#endif // LL_LLFAVORITESBARCTRL_H
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index c3d87cea0b..54bd07329a 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -97,20 +97,10 @@ protected:
class LLFeatureManager : public LLFeatureList, public LLSingleton<LLFeatureManager>
{
-public:
- LLFeatureManager()
- : LLFeatureList("default"),
-
- mInited(FALSE),
- mTableVersion(0),
- mSafe(FALSE),
- mGPUClass(GPU_CLASS_UNKNOWN),
- mExpectedGLVersion(0.f),
- mGPUSupported(FALSE)
- {
- }
+ LLSINGLETON(LLFeatureManager);
~LLFeatureManager() {cleanupFeatureTables();}
+public:
// initialize this by loading feature table and gpu table
void init();
@@ -181,5 +171,17 @@ protected:
BOOL mGPUSupported;
};
+inline
+LLFeatureManager::LLFeatureManager()
+: LLFeatureList("default"),
+
+ mInited(FALSE),
+ mTableVersion(0),
+ mSafe(FALSE),
+ mGPUClass(GPU_CLASS_UNKNOWN),
+ mExpectedGLVersion(0.f),
+ mGPUSupported(FALSE)
+{
+}
#endif // LL_LLFEATUREMANAGER_H
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
index a29ccf2b6d..f2af9b5300 100644
--- a/indra/newview/llfilteredwearablelist.cpp
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -93,4 +93,9 @@ void LLFilteredWearableListManager::populateList()
mWearableList->refreshList(item_array);
}
+void LLFilteredWearableListManager::holdProgress()
+{
+ mWearableList->setForceRefresh(false);
+}
+
// EOF
diff --git a/indra/newview/llfilteredwearablelist.h b/indra/newview/llfilteredwearablelist.h
index c21458ca98..f44ab1466f 100644
--- a/indra/newview/llfilteredwearablelist.h
+++ b/indra/newview/llfilteredwearablelist.h
@@ -56,6 +56,11 @@ public:
*/
void populateList();
+ /**
+ * Drop operation
+ */
+ void holdProgress();
+
private:
LLInventoryItemsList* mWearableList;
LLInventoryCollectFunctor* mCollector;
diff --git a/indra/newview/llflickrconnect.h b/indra/newview/llflickrconnect.h
index 0155804da0..43cadca708 100644
--- a/indra/newview/llflickrconnect.h
+++ b/indra/newview/llflickrconnect.h
@@ -43,6 +43,8 @@ class LLEventPump;
*/
class LLFlickrConnect : public LLSingleton<LLFlickrConnect>
{
+ LLSINGLETON(LLFlickrConnect);
+ ~LLFlickrConnect() {};
LOG_CLASS(LLFlickrConnect);
public:
enum EConnectionState
@@ -80,10 +82,7 @@ public:
void openFlickrWeb(std::string url);
private:
- friend class LLSingleton<LLFlickrConnect>;
- LLFlickrConnect();
- ~LLFlickrConnect() {};
std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);
EConnectionState mConnectionState;
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/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index e5df417ca9..602d2dce73 100644
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -992,7 +992,7 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata)
{
std::string name = floaterp->getChild<LLUICtrl>("name_form")->getValue().asString();
std::string desc = floaterp->getChild<LLUICtrl>("description_form")->getValue().asString();
- S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
LLResourceUploadInfo::ptr_t assetUpdloadInfo(new LLResourceUploadInfo(
floaterp->mTransactionID, LLAssetType::AT_ANIMATION,
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/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 15b67b905d..7039e48e74 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -101,7 +101,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer()
gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed());
gSavedPerAccountSettings.setBOOL("ConversationsParticipantListCollapsed", !isParticipantListExpanded());
- if (!LLSingleton<LLIMMgr>::destroyed())
+ if (LLIMMgr::instanceExists())
{
LLIMMgr::getInstance()->removeSessionObserver(this);
}
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/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp
index 9fd731ed56..4cd91c53d8 100644
--- a/indra/newview/llfloaterimnearbychathandler.cpp
+++ b/indra/newview/llfloaterimnearbychathandler.cpp
@@ -285,6 +285,14 @@ void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat)
if(mStopProcessing)
return;
+ if (mFloaterSnapRegion == NULL)
+ {
+ mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region");
+ }
+ LLRect channel_rect;
+ mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &channel_rect, gFloaterView);
+ chat["available_height"] = channel_rect.getHeight() - channel_rect.mBottom - gSavedSettings.getS32("ToastGap") - 110;;
+
/*
find last toast and check ID
*/
@@ -380,7 +388,7 @@ void LLFloaterIMNearbyChatScreenChannel::arrangeToasts()
setFollows(FOLLOWS_ALL);
}
- LLRect toast_rect;
+ LLRect toast_rect;
updateRect();
LLRect channel_rect;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index ffeebfd256..d29b96d245 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1184,6 +1184,7 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
, mLodsQuery()
+, mLodsWithParsingError()
, mPelvisZOffset( 0.0f )
, mLegacyRigValid( false )
, mRigValidJointUpload( false )
@@ -1755,8 +1756,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
// this is the initial file picking. Close the whole floater
// if we don't have a base model to show for high LOD.
mFMP->closeFloater(false);
- mLoading = false;
}
+ mLoading = false;
return;
}
@@ -1902,9 +1903,16 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
{
mLoading = false ;
mModelLoader = NULL;
+ mLodsWithParsingError.push_back(loaded_lod);
return ;
}
+ mLodsWithParsingError.erase(std::remove(mLodsWithParsingError.begin(), mLodsWithParsingError.end(), loaded_lod), mLodsWithParsingError.end());
+ if(mLodsWithParsingError.empty())
+ {
+ mFMP->childEnable( "calculate_btn" );
+ }
+
// Copy determinations about rig so UI will reflect them
//
setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
@@ -2114,7 +2122,11 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
if (!mBaseModel.empty())
{
const std::string& model_name = mBaseModel[0]->getName();
- mFMP->getChild<LLUICtrl>("description_form")->setValue(model_name);
+ LLLineEditor* description_form = mFMP->getChild<LLLineEditor>("description_form");
+ if (description_form->getText().empty())
+ {
+ description_form->setText(model_name);
+ }
}
}
refresh();
@@ -2639,17 +2651,7 @@ void LLModelPreview::updateStatusMessages()
setLoadState( LLModelLoader::ERROR_MATERIALS );
mFMP->childDisable( "calculate_btn" );
}
-
- int refFaceCnt = 0;
- int modelFaceCnt = 0;
-
- if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) )
- {
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- }
-
- if (lod_model)
+ else
{
//for each model in the lod
S32 cur_tris = 0;
@@ -3591,7 +3593,7 @@ BOOL LLModelPreview::render()
}
}
- if (has_skin_weights)
+ if (has_skin_weights && lodsReady())
{ //model has skin weights, enable view options for skin weights and joint positions
if (fmp && isLegacyRigValid() )
{
@@ -4517,4 +4519,12 @@ void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status, const std::stri
LLNotificationsUtil::add("MeshUploadPermError");
}
+bool LLFloaterModelPreview::isModelLoading()
+{
+ if(mModelPreview)
+ {
+ return mModelPreview->mLoading;
+ }
+ return false;
+}
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index a73ca50260..df58b843cb 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -115,6 +115,8 @@ public:
void enableViewOption(const std::string& option);
void disableViewOption(const std::string& option);
+ bool isModelLoading();
+
// shows warning message if agent has no permissions to upload model
/*virtual*/ void onPermissionsReceived(const LLSD& result);
@@ -307,6 +309,7 @@ public:
static bool sIgnoreLoadedCallback;
std::vector<S32> mLodsQuery;
+ std::vector<S32> mLodsWithParsingError;
protected:
diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp
index 0fe97fd610..7cdfd56d9a 100644
--- a/indra/newview/llfloatermodeluploadbase.cpp
+++ b/indra/newview/llfloatermodeluploadbase.cpp
@@ -80,6 +80,7 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissionsCoro(std::string url
if (!observer)
{
LL_WARNS("MeshUploadFlag") << "Unable to get observer after call to '" << url << "' aborting." << LL_ENDL;
+ return;
}
if (!status)
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 4a5732aecf..c9a689281e 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -123,7 +123,7 @@ BOOL LLFloaterNameDesc::postBuild()
// Cancel button
getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnCancel, this));
- getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() ));
+ getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload() ));
setDefaultBtn("ok_btn");
@@ -162,7 +162,7 @@ void LLFloaterNameDesc::onBtnOK( )
getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads
LLAssetStorage::LLStoreAssetCallback callback = NULL;
- 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).
+ S32 expected_upload_cost = LLGlobalEconomy::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).
if (can_afford_transaction(expected_upload_cost))
{
diff --git a/indra/newview/llfloateroutfitphotopreview.cpp b/indra/newview/llfloateroutfitphotopreview.cpp
new file mode 100644
index 0000000000..6c39db730c
--- /dev/null
+++ b/indra/newview/llfloateroutfitphotopreview.cpp
@@ -0,0 +1,289 @@
+/**
+ * @file llfloateroutfitphotopreview.cpp
+ * @brief LLFloaterOutfitPhotoPreview class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llwindow.h"
+
+#include "llfloateroutfitphotopreview.h"
+
+#include "llagent.h"
+#include "llappearancemgr.h"
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "llfilepicker.h"
+#include "llfloaterreg.h"
+#include "llimagetga.h"
+#include "llimagepng.h"
+#include "llinventory.h"
+#include "llinventorymodel.h"
+#include "llnotificationsutil.h"
+#include "llresmgr.h"
+#include "lltrans.h"
+#include "lltextbox.h"
+#include "lltextureview.h"
+#include "llui.h"
+#include "llviewerinventory.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+#include "lllineeditor.h"
+
+const S32 MAX_OUTFIT_PHOTO_WIDTH = 256;
+const S32 MAX_OUTFIT_PHOTO_HEIGHT = 256;
+
+const S32 CLIENT_RECT_VPAD = 4;
+
+LLFloaterOutfitPhotoPreview::LLFloaterOutfitPhotoPreview(const LLSD& key)
+ : LLPreview(key),
+ mUpdateDimensions(TRUE),
+ mImage(NULL),
+ mOutfitID(LLUUID()),
+ mImageOldBoostLevel(LLGLTexture::BOOST_NONE),
+ mExceedLimits(FALSE)
+{
+ updateImageID();
+}
+
+LLFloaterOutfitPhotoPreview::~LLFloaterOutfitPhotoPreview()
+{
+ LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
+
+ if (mImage.notNull())
+ {
+ mImage->setBoostLevel(mImageOldBoostLevel);
+ mImage = NULL;
+ }
+}
+
+// virtual
+BOOL LLFloaterOutfitPhotoPreview::postBuild()
+{
+ getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterOutfitPhotoPreview::onOkBtn, this));
+ getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterOutfitPhotoPreview::onCancelBtn, this));
+
+ return LLPreview::postBuild();
+}
+
+void LLFloaterOutfitPhotoPreview::draw()
+{
+ updateDimensions();
+
+ LLPreview::draw();
+
+ if (!isMinimized())
+ {
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ const LLRect& border = mClientRect;
+ LLRect interior = mClientRect;
+ interior.stretch( -PREVIEW_BORDER_WIDTH );
+
+ // ...border
+ gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
+ gl_rect_2d_checkerboard( interior );
+
+ if ( mImage.notNull() )
+ {
+ // Draw the texture
+ gGL.diffuseColor3f( 1.f, 1.f, 1.f );
+ gl_draw_scaled_image(interior.mLeft,
+ interior.mBottom,
+ interior.getWidth(),
+ interior.getHeight(),
+ mImage);
+
+ // Pump the texture priority
+ F32 pixel_area = (F32)(interior.getWidth() * interior.getHeight() );
+ mImage->addTextureStats( pixel_area );
+
+ S32 int_width = interior.getWidth();
+ S32 int_height = interior.getHeight();
+ mImage->setKnownDrawSize(int_width, int_height);
+ }
+ }
+
+}
+
+// virtual
+void LLFloaterOutfitPhotoPreview::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLPreview::reshape(width, height, called_from_parent);
+
+ LLRect dim_rect(getChildView("dimensions")->getRect());
+
+ S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
+
+ S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD;
+
+ LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0);
+ client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
+ client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ;
+
+ S32 client_width = client_rect.getWidth();
+ S32 client_height = client_width;
+
+ if(client_height > client_rect.getHeight())
+ {
+ client_height = client_rect.getHeight();
+ client_width = client_height;
+ }
+ mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
+
+}
+
+
+void LLFloaterOutfitPhotoPreview::updateDimensions()
+{
+ if (!mImage)
+ {
+ return;
+ }
+ if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0)
+ {
+ return;
+ }
+
+ if (mAssetStatus != PREVIEW_ASSET_LOADED)
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ mUpdateDimensions = TRUE;
+ }
+
+ getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", mImage->getFullWidth()));
+ getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", mImage->getFullHeight()));
+
+ if ((mImage->getFullWidth() <= MAX_OUTFIT_PHOTO_WIDTH) && (mImage->getFullHeight() <= MAX_OUTFIT_PHOTO_HEIGHT))
+ {
+ getChild<LLButton>("ok_btn")->setEnabled(TRUE);
+ mExceedLimits = FALSE;
+ }
+ else
+ {
+ mExceedLimits = TRUE;
+ LLStringUtil::format_map_t args;
+ args["MAX_WIDTH"] = llformat("%d", MAX_OUTFIT_PHOTO_WIDTH);
+ args["MAX_HEIGHT"] = llformat("%d", MAX_OUTFIT_PHOTO_HEIGHT);
+ std::string label = getString("exceed_limits", args);
+ getChild<LLUICtrl>("notification")->setValue(label);
+ getChild<LLUICtrl>("notification")->setColor(LLColor4::yellow);
+ getChild<LLButton>("ok_btn")->setEnabled(FALSE);
+ }
+
+ if (mUpdateDimensions)
+ {
+ mUpdateDimensions = FALSE;
+
+ reshape(getRect().getWidth(), getRect().getHeight());
+ gFloaterView->adjustToFitScreen(this, FALSE);
+ }
+}
+
+void LLFloaterOutfitPhotoPreview::loadAsset()
+{
+ if (mImage.notNull())
+ {
+ mImage->setBoostLevel(mImageOldBoostLevel);
+ }
+ mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ mImageOldBoostLevel = mImage->getBoostLevel();
+ mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ mImage->forceToSaveRawImage(0) ;
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ mUpdateDimensions = TRUE;
+ updateDimensions();
+}
+
+LLPreview::EAssetStatus LLFloaterOutfitPhotoPreview::getAssetStatus()
+{
+ if (mImage.notNull() && (mImage->getFullWidth() * mImage->getFullHeight() > 0))
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+ return mAssetStatus;
+}
+
+void LLFloaterOutfitPhotoPreview::updateImageID()
+{
+ const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem());
+ if(item)
+ {
+ mImageID = item->getAssetUUID();
+ LLPermissions perm(item->getPermissions());
+ }
+ else
+ {
+ mImageID = mItemUUID;
+ }
+
+}
+
+/* virtual */
+void LLFloaterOutfitPhotoPreview::setObjectID(const LLUUID& object_id)
+{
+ mObjectUUID = object_id;
+
+ const LLUUID old_image_id = mImageID;
+
+ updateImageID();
+ if (mImageID != old_image_id)
+ {
+ mAssetStatus = PREVIEW_ASSET_UNLOADED;
+ loadAsset();
+ }
+ refreshFromItem();
+}
+
+void LLFloaterOutfitPhotoPreview::setOutfitID(const LLUUID& outfit_id)
+{
+ mOutfitID = outfit_id;
+ LLViewerInventoryCategory* outfit_folder = gInventory.getCategory(mOutfitID);
+ if(outfit_folder && !mExceedLimits)
+ {
+ getChild<LLUICtrl>("notification")->setValue( getString("photo_confirmation"));
+ getChild<LLUICtrl>("notification")->setTextArg("[OUTFIT]", outfit_folder->getName());
+ getChild<LLUICtrl>("notification")->setColor(LLColor4::white);
+ }
+
+}
+
+void LLFloaterOutfitPhotoPreview::onOkBtn()
+{
+ if(mOutfitID.notNull() && getItem())
+ {
+ LLAppearanceMgr::instance().removeOutfitPhoto(mOutfitID);
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_object(mOutfitID, LLConstPointer<LLInventoryObject>(getItem()), cb);
+ }
+ closeFloater();
+}
+
+void LLFloaterOutfitPhotoPreview::onCancelBtn()
+{
+ closeFloater();
+}
diff --git a/indra/newview/llfloateroutfitphotopreview.h b/indra/newview/llfloateroutfitphotopreview.h
new file mode 100644
index 0000000000..a1e7b58abe
--- /dev/null
+++ b/indra/newview/llfloateroutfitphotopreview.h
@@ -0,0 +1,77 @@
+/**
+ * @file llfloateroutfitphotopreview.h
+ * @brief LLFloaterOutfitPhotoPreview class definition
+ *
+ * $LicenseInfo:firstyear=2002&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$
+ */
+
+#ifndef LL_LLFLOATEROUTFITPHOTOPREVIEW_H
+#define LL_LLFLOATEROUTFITPHOTOPREVIEW_H
+
+#include "llpreview.h"
+#include "llbutton.h"
+#include "llframetimer.h"
+#include "llviewertexture.h"
+
+class LLComboBox;
+class LLImageRaw;
+
+class LLFloaterOutfitPhotoPreview : public LLPreview
+{
+public:
+ LLFloaterOutfitPhotoPreview(const LLSD& key);
+ ~LLFloaterOutfitPhotoPreview();
+
+ virtual void draw();
+
+ virtual void loadAsset();
+ virtual EAssetStatus getAssetStatus();
+
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ /*virtual*/ void setObjectID(const LLUUID& object_id);
+
+ void setOutfitID(const LLUUID& outfit_id);
+ void onOkBtn();
+ void onCancelBtn();
+
+protected:
+ void init();
+ /* virtual */ BOOL postBuild();
+
+private:
+ void updateImageID(); // set what image is being uploaded.
+ void updateDimensions();
+ LLUUID mImageID;
+ LLUUID mOutfitID;
+ LLPointer<LLViewerFetchedTexture> mImage;
+ S32 mImageOldBoostLevel;
+
+ // This is stored off in a member variable, because the save-as
+ // button and drag and drop functionality need to know.
+ BOOL mUpdateDimensions;
+
+ BOOL mExceedLimits;
+
+ LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ;
+};
+#endif // LL_LLFLOATEROUTFITPHOTOPREVIEW_H
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index 31245db344..87973c2286 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);
@@ -278,7 +284,6 @@ void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata)
self->mQuickPayButton[i]->setLabelUnselected(button_str);
self->mQuickPayButton[i]->setVisible(TRUE);
self->mQuickPayInfo[i]->mAmount = pay_button;
- self->getChildView("fastpay text")->setVisible(TRUE);
if ( pay_button > max_pay_amount )
{
@@ -406,7 +411,6 @@ void LLFloaterPay::payDirectly(money_callback callback,
floater->getChildView("pay btn")->setVisible(TRUE);
floater->getChildView("amount text")->setVisible(TRUE);
- floater->getChildView("fastpay text")->setVisible(TRUE);
for(S32 i=0;i<MAX_PAY_BUTTONS;++i)
{
floater->mQuickPayButton[i]->setVisible(TRUE);
@@ -415,9 +419,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 +483,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)
@@ -581,7 +592,8 @@ void LLFloaterPay::give(S32 amount)
else
{
// just transfer the L$
- mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, LLStringUtil::null);
+ std::string paymentMessage(getChild<LLLineEditor>("payment_message")->getValue().asString());
+ mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, (paymentMessage.empty() ? LLStringUtil::null : paymentMessage));
// check if the payee needs to be unmuted
LLMuteList::getInstance()->autoRemove(mTargetUUID, LLMuteList::AR_MONEY);
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..790e2b3ad1 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -37,6 +37,7 @@
#include "llcachename.h"
#include "llcheckboxctrl.h"
#include "llfontgl.h"
+#include "llimagebmp.h"
#include "llimagej2c.h"
#include "llinventory.h"
#include "llnotificationsutil.h"
@@ -76,6 +77,7 @@
#include "llselectmgr.h"
#include "llversioninfo.h"
#include "lluictrlfactory.h"
+#include "llviewercontrol.h"
#include "llviewernetwork.h"
#include "llagentui.h"
@@ -86,6 +88,7 @@
#include "llcorehttputil.h"
#include "llviewerassetupload.h"
+const std::string SCREEN_PREV_FILENAME = "screen_report_last.bmp";
//=========================================================================
//-----------------------------------------------------------------------------
@@ -181,18 +184,12 @@ BOOL LLFloaterReporter::postBuild()
}
setPosBox(pos);
- // Take a screenshot, but don't draw this floater.
- setVisible(FALSE);
- takeScreenshot();
- setVisible(TRUE);
-
// Default text to be blank
getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
mOwnerName = LLStringUtil::null;
getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
- getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE);
mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
@@ -246,8 +243,6 @@ LLFloaterReporter::~LLFloaterReporter()
// virtual
void LLFloaterReporter::draw()
{
- getChildView("screen_check")->setEnabled(TRUE );
-
LLFloater::draw();
}
@@ -255,7 +250,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 +442,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 +699,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 +753,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));
@@ -784,18 +767,24 @@ void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url
}
}
-void LLFloaterReporter::takeScreenshot()
+void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot)
{
- const S32 IMAGE_WIDTH = 1024;
- const S32 IMAGE_HEIGHT = 768;
-
- LLPointer<LLImageRaw> raw = new LLImageRaw;
- if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE))
+ gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", TRUE);
+ if(!use_prev_screenshot)
{
- LL_WARNS() << "Unable to take screenshot" << LL_ENDL;
- return;
+ std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME);
+ LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
+ if(bmp_image->encode(mImageRaw, 0.0f))
+ {
+ bmp_image->save(screenshot_filename);
+ }
+ }
+ else
+ {
+ mImageRaw = mPrevImageRaw;
}
- LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(raw);
+
+ LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(mImageRaw);
// create a resource data
mResourceDatap->mInventoryType = LLInventoryType::IT_NONE;
@@ -827,7 +816,7 @@ void LLFloaterReporter::takeScreenshot()
// store in the image list so it doesn't try to fetch from the server
LLPointer<LLViewerFetchedTexture> image_in_list =
LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid);
- image_in_list->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER);
+ image_in_list->createGLTexture(0, mImageRaw, 0, TRUE, LLGLTexture::OTHER);
// the texture picker then uses that texture
LLTextureCtrl* texture = getChild<LLTextureCtrl>("screenshot");
@@ -837,7 +826,46 @@ void LLFloaterReporter::takeScreenshot()
texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid);
texture->setCaption(getString("Screenshot"));
}
+}
+
+void LLFloaterReporter::onOpen(const LLSD& key)
+{
+ mImageRaw = new LLImageRaw;
+ const S32 IMAGE_WIDTH = 1024;
+ const S32 IMAGE_HEIGHT = 768;
+
+ // Take a screenshot, but don't draw this floater.
+ setVisible(FALSE);
+ if( !gViewerWindow->rawSnapshot(mImageRaw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE))
+ {
+ LL_WARNS() << "Unable to take screenshot" << LL_ENDL;
+ setVisible(TRUE);
+ return;
+ }
+ setVisible(TRUE);
+
+ if(gSavedPerAccountSettings.getBOOL("PreviousScreenshotForReport"))
+ {
+ std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME);
+ mPrevImageRaw = new LLImageRaw;
+ LLPointer<LLImageBMP> start_image_bmp = new LLImageBMP;
+ if(start_image_bmp->load(screenshot_filename))
+ {
+ if (start_image_bmp->decode(mPrevImageRaw, 0.0f))
+ {
+ LLNotificationsUtil::add("LoadPreviousReportScreenshot", LLSD(), LLSD(), boost::bind(&LLFloaterReporter::onLoadScreenshotDialog,this, _1, _2));
+ return;
+ }
+ }
+ }
+ takeScreenshot();
+}
+
+void LLFloaterReporter::onLoadScreenshotDialog(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ takeScreenshot(option == 0);
}
void LLFloaterReporter::uploadImage()
@@ -885,6 +913,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();
}
}
@@ -900,6 +929,11 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos)
getChild<LLUICtrl>("pos_field")->setValue(pos_string);
}
+void LLFloaterReporter::onClose(bool app_quitting)
+{
+ gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", app_quitting);
+}
+
// void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
// {
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index 1aff07bd37..e5232268c0 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -81,6 +81,8 @@ public:
LLFloaterReporter(const LLSD& key);
/*virtual*/ ~LLFloaterReporter();
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
virtual void draw();
void setReportType(EReportType type) { mReportType = type; }
@@ -103,10 +105,12 @@ public:
void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id);
+ void onLoadScreenshotDialog(const LLSD& notification, const LLSD& response);
+
private:
static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null, const LLUUID& experience_id = LLUUID::null);
- void takeScreenshot();
+ void takeScreenshot(bool use_prev_screenshot = false);
void sendReportViaCaps(std::string url);
void uploadImage();
bool validateReport();
@@ -140,6 +144,9 @@ private:
std::string mDefaultSummary;
LLResourceData* mResourceDatap;
boost::signals2::connection mAvatarNameCacheConnection;
+
+ LLPointer<LLImageRaw> mImageRaw;
+ LLPointer<LLImageRaw> mPrevImageRaw;
};
#endif
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 ff7594a531..c0980719bb 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -762,7 +762,8 @@ 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()->updateSnapshot(TRUE);
+ // Don't update immediately, give window chance to redraw
+ getPreviewView()->updateSnapshot(TRUE, FALSE, 1.f);
if(do_update)
{
LL_DEBUGS() << "Will update controls" << LL_ENDL;
@@ -1375,7 +1376,7 @@ const LLVector3d& LLFloaterSnapshotBase::getPosTakenGlobal()
// static
void LLFloaterSnapshot::setAgentEmail(const std::string& email)
{
- LLFloaterSnapshot* instance = getInstance();
+ LLFloaterSnapshot* instance = findInstance();
if (instance)
{
LLSideTrayPanelContainer* panel_container = instance->getChild<LLSideTrayPanelContainer>("panel_container");
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index ae3800e17b..2fb912a930 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -37,9 +37,10 @@ class LLFriendCardsManager
: public LLSingleton<LLFriendCardsManager>
, public LLFriendObserver
{
+ LLSINGLETON(LLFriendCardsManager);
+ ~LLFriendCardsManager();
LOG_CLASS(LLFriendCardsManager);
- friend class LLSingleton<LLFriendCardsManager>;
friend class CreateFriendCardCallback;
public:
@@ -97,8 +98,6 @@ public:
private:
typedef boost::function<void()> callback_t;
- LLFriendCardsManager();
- ~LLFriendCardsManager();
/**
diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h
index 26a5924ec3..402bdf6039 100644
--- a/indra/newview/llgesturemgr.h
+++ b/indra/newview/llgesturemgr.h
@@ -51,6 +51,8 @@ public:
class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchItemsObserver
{
+ LLSINGLETON(LLGestureMgr);
+ ~LLGestureMgr();
public:
typedef boost::function<void (LLMultiGesture* loaded_gesture)> gesture_loaded_callback_t;
@@ -58,8 +60,6 @@ public:
typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
typedef std::map<LLUUID, gesture_loaded_callback_t> callback_map_t;
- LLGestureMgr();
- ~LLGestureMgr();
void init();
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/llgroupmgr.h b/indra/newview/llgroupmgr.h
index e5ce768035..940ef6eea1 100644
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -348,6 +348,8 @@ struct LLRoleActionSet
class LLGroupMgr : public LLSingleton<LLGroupMgr>
{
+ LLSINGLETON(LLGroupMgr);
+ ~LLGroupMgr();
LOG_CLASS(LLGroupMgr);
public:
@@ -369,8 +371,6 @@ public:
public:
- LLGroupMgr();
- ~LLGroupMgr();
void addObserver(LLGroupMgrObserver* observer);
void addObserver(const LLUUID& group_id, LLParticularGroupObserver* observer);
diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h
index ebffe561b9..dd6195a9ce 100644
--- a/indra/newview/llhints.h
+++ b/indra/newview/llhints.h
@@ -29,6 +29,7 @@
#include "llpanel.h"
#include "llnotifications.h"
+#include "llinitdestroyclass.h"
class LLHints : public LLInitClass<LLHints>
diff --git a/indra/newview/llhudmanager.h b/indra/newview/llhudmanager.h
index 9c5d49decd..7782739690 100644
--- a/indra/newview/llhudmanager.h
+++ b/indra/newview/llhudmanager.h
@@ -36,10 +36,10 @@ class LLMessageSystem;
class LLHUDManager : public LLSingleton<LLHUDManager>
{
-public:
- LLHUDManager();
+ LLSINGLETON(LLHUDManager);
~LLHUDManager();
+public:
LLHUDEffect *createViewerEffect(const U8 type, BOOL send_to_sim = TRUE, BOOL originated_here = TRUE);
void updateEffects();
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/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h
index 4751933065..f1ed3cf1c3 100644
--- a/indra/newview/llimagefiltersmanager.h
+++ b/indra/newview/llimagefiltersmanager.h
@@ -34,6 +34,8 @@
class LLImageFiltersManager : public LLSingleton<LLImageFiltersManager>
{
+ LLSINGLETON(LLImageFiltersManager);
+ ~LLImageFiltersManager();
LOG_CLASS(LLImageFiltersManager);
public:
const std::vector<std::string> getFiltersList() const;
@@ -43,10 +45,7 @@ private:
void loadAllFilters();
void loadFiltersFromDir(const std::string& dir);
- friend class LLSingleton<LLImageFiltersManager>;
/*virtual*/ void initSingleton();
- LLImageFiltersManager();
- ~LLImageFiltersManager();
// List of filters : first is the user friendly localized name, second is the xml file name
std::map<std::string,std::string> mFiltersList;
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 41a8813acb..da40ac8393 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -33,6 +33,7 @@
#include "lllogchat.h"
#include "llvoicechannel.h"
+#include "llinitdestroyclass.h"
#include "llcoros.h"
#include "lleventcoro.h"
@@ -61,6 +62,7 @@ private:
*/
class LLIMModel : public LLSingleton<LLIMModel>
{
+ LLSINGLETON(LLIMModel);
public:
struct LLIMSession : public boost::signals2::trackable
@@ -151,7 +153,6 @@ public:
};
- LLIMModel();
/** Session id to session object */
std::map<LLUUID, LLIMSession*> mId2SessionMap;
@@ -312,6 +313,7 @@ public:
class LLIMMgr : public LLSingleton<LLIMMgr>
{
+ LLSINGLETON(LLIMMgr);
friend class LLIMModel;
public:
@@ -322,8 +324,6 @@ public:
INVITATION_TYPE_IMMEDIATE = 2
};
- LLIMMgr();
- virtual ~LLIMMgr() {};
// Add a message to a session. The session can keyed to sesion id
// or agent id.
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 9f0b35fc8c..02fa81d5be 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -41,6 +41,7 @@
#include "llfloateropenobject.h"
#include "llfloaterreg.h"
#include "llfloatermarketplacelistings.h"
+#include "llfloateroutfitphotopreview.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
#include "llfolderview.h"
@@ -286,6 +287,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 +318,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 +1399,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 +1940,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;
@@ -4377,7 +4394,7 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr
if((inv_type == LLInventoryType::IT_TEXTURE) || (inv_type == LLInventoryType::IT_SNAPSHOT))
{
- return TRUE;
+ return !move_is_into_current_outfit;
}
if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID()))
@@ -4432,9 +4449,15 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
{
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);
+ const LLUUID &my_outifts_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
+ if(mUUID != my_outifts_id)
+ {
+ LLFloaterOutfitPhotoPreview* photo_preview = LLFloaterReg::showTypedInstance<LLFloaterOutfitPhotoPreview>("outfit_photo_preview", inv_item->getUUID());
+ if(photo_preview)
+ {
+ photo_preview->setOutfitID(mUUID);
+ }
+ }
return;
}
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/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 013a5a7629..495180f087 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -46,8 +46,7 @@ struct IconEntry : public LLDictionaryEntry
class LLIconDictionary : public LLSingleton<LLIconDictionary>,
public LLDictionary<LLInventoryType::EIconName, IconEntry>
{
-public:
- LLIconDictionary();
+ LLSINGLETON(LLIconDictionary);
};
typedef LLPointer<LLUIImage> LLUIImagePtr;
diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp
index 36e1cc97d1..1dc1aa395e 100644
--- a/indra/newview/llinventoryitemslist.cpp
+++ b/indra/newview/llinventoryitemslist.cpp
@@ -45,7 +45,7 @@ LLInventoryItemsList::Params::Params()
LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p)
: LLFlatListViewEx(p)
-, mNeedsRefresh(false)
+, mRefreshState(REFRESH_COMPLETE)
, mForceRefresh(false)
{
// TODO: mCommitOnSelectionChange is set to "false" in LLFlatListView
@@ -66,13 +66,13 @@ LLInventoryItemsList::~LLInventoryItemsList()
void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item_array)
{
- getIDs().clear();
+ getIDs().clear();
LLInventoryModel::item_array_t::const_iterator it = item_array.begin();
for( ; item_array.end() != it; ++it)
{
getIDs().push_back((*it)->getUUID());
}
- mNeedsRefresh = true;
+ mRefreshState = REFRESH_ALL;
}
boost::signals2::connection LLInventoryItemsList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb)
@@ -113,9 +113,9 @@ void LLInventoryItemsList::updateSelection()
void LLInventoryItemsList::doIdle()
{
- if (!mNeedsRefresh) return;
+ if (mRefreshState == REFRESH_COMPLETE) return;
- if (isInVisibleChain() || mForceRefresh)
+ if (isInVisibleChain() || mForceRefresh )
{
refresh();
@@ -137,54 +137,130 @@ LLTrace::BlockTimerStatHandle FTM_INVENTORY_ITEMS_REFRESH("Inventory List Refres
void LLInventoryItemsList::refresh()
{
- LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH);
- static const unsigned ADD_LIMIT = 20;
-
- uuid_vec_t added_items;
- uuid_vec_t removed_items;
-
- computeDifference(getIDs(), added_items, removed_items);
-
- bool add_limit_exceeded = false;
- unsigned int nadded = 0;
-
- uuid_vec_t::const_iterator it = added_items.begin();
- for( ; added_items.end() != it; ++it)
- {
- if(nadded >= ADD_LIMIT)
- {
- add_limit_exceeded = true;
- break;
- }
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- // Do not rearrange items on each adding, let's do that on filter call
- llassert(item);
- if (item)
- {
- addNewItem(item, false);
- ++nadded;
- }
- }
-
- it = removed_items.begin();
- for( ; removed_items.end() != it; ++it)
- {
- // don't filter items right away
- removeItemByUUID(*it, false);
- }
-
- // Filter, rearrange and notify parent about shape changes
- filterItems();
-
- bool needs_refresh = add_limit_exceeded;
- setNeedsRefresh(needs_refresh);
- setForceRefresh(needs_refresh);
-
- // After list building completed, select items that had been requested to select before list was build
- if(!needs_refresh)
- {
- updateSelection();
- }
+ LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH);
+
+ switch (mRefreshState)
+ {
+ case REFRESH_ALL:
+ {
+ mAddedItems.clear();
+ mRemovedItems.clear();
+ computeDifference(getIDs(), mAddedItems, mRemovedItems);
+ if (mRemovedItems.size() > 0)
+ {
+ mRefreshState = REFRESH_LIST_ERASE;
+ }
+ else if (mAddedItems.size() > 0)
+ {
+ mRefreshState = REFRESH_LIST_APPEND;
+ }
+ else
+ {
+ mRefreshState = REFRESH_LIST_SORT;
+ }
+
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ break;
+ }
+ case REFRESH_LIST_ERASE:
+ {
+ uuid_vec_t::const_iterator it = mRemovedItems.begin();
+ for (; mRemovedItems.end() != it; ++it)
+ {
+ // don't filter items right away
+ removeItemByUUID(*it, false);
+ }
+ mRemovedItems.clear();
+ mRefreshState = REFRESH_LIST_SORT; // fix visibility and arrange
+ break;
+ }
+ case REFRESH_LIST_APPEND:
+ {
+ static const unsigned ADD_LIMIT = 25; // Note: affects perfomance
+
+ unsigned int nadded = 0;
+
+ // form a list to add
+ uuid_vec_t::iterator it = mAddedItems.begin();
+ pairs_list_t panel_list;
+ while(mAddedItems.size() > 0 && nadded < ADD_LIMIT)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ llassert(item);
+ if (item)
+ {
+ LLPanel *list_item = createNewItem(item);
+ if (list_item)
+ {
+ item_pair_t* new_pair = new item_pair_t(list_item, item->getUUID());
+ panel_list.push_back(new_pair);
+ ++nadded;
+ }
+ }
+
+ it = mAddedItems.erase(it);
+ }
+
+ // add the list
+ // Note: usually item pairs are sorted with std::sort, but we are calling
+ // this function on idle and pairs' list can take a lot of time to sort
+ // through, so we are sorting items into list while adding them
+ addItemPairs(panel_list, false);
+
+ // update visibility of items in the list
+ std::string cur_filter = getFilterSubString();
+ LLStringUtil::toUpper(cur_filter);
+ LLSD action;
+ action.with("match_filter", cur_filter);
+
+ pairs_const_iterator_t pair_it = panel_list.begin();
+ for (; pair_it != panel_list.end(); ++pair_it)
+ {
+ item_pair_t* item_pair = *pair_it;
+ if (item_pair->first->getParent() != NULL)
+ {
+ updateItemVisibility(item_pair->first, action);
+ }
+ }
+
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+
+ if (mAddedItems.size() > 0)
+ {
+ mRefreshState = REFRESH_LIST_APPEND;
+ }
+ else
+ {
+ // Note: while we do sort and check visibility at REFRESH_LIST_APPEND, update
+ // could have changed something about existing items so redo checks for all items.
+ mRefreshState = REFRESH_LIST_SORT;
+ }
+ break;
+ }
+ case REFRESH_LIST_SORT:
+ {
+ // Filter, sort, rearrange and notify parent about shape changes
+ filterItems();
+
+ if (mAddedItems.size() == 0)
+ {
+ // After list building completed, select items that had been requested to select before list was build
+ updateSelection();
+ mRefreshState = REFRESH_COMPLETE;
+ }
+ else
+ {
+ mRefreshState = REFRESH_LIST_APPEND;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ setForceRefresh(mRefreshState != REFRESH_COMPLETE);
}
void LLInventoryItemsList::computeDifference(
@@ -204,24 +280,15 @@ void LLInventoryItemsList::computeDifference(
LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
}
-void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange /*= true*/)
+LLPanel* LLInventoryItemsList::createNewItem(LLViewerInventoryItem* item)
{
- if (!item)
- {
- LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
- llassert(item != NULL);
- }
-
- LLPanelInventoryListItemBase *list_item = LLPanelInventoryListItemBase::create(item);
- if (!list_item)
- return;
-
- bool is_item_added = addItem(list_item, item->getUUID(), ADD_BOTTOM, rearrange);
- if (!is_item_added)
- {
- LL_WARNS() << "Couldn't add flat list item." << LL_ENDL;
- llassert(is_item_added);
- }
+ if (!item)
+ {
+ LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
+ llassert(item != NULL);
+ return NULL;
+ }
+ return LLPanelInventoryListItemBase::create(item);
}
// EOF
diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h
index 1aa230df99..fe05c2ed7c 100644
--- a/indra/newview/llinventoryitemslist.h
+++ b/indra/newview/llinventoryitemslist.h
@@ -51,9 +51,9 @@ public:
/**
* Let list know items need to be refreshed in next doIdle()
*/
- void setNeedsRefresh(bool needs_refresh){ mNeedsRefresh = needs_refresh; }
+ void setNeedsRefresh(bool needs_refresh){ mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; }
- bool getNeedsRefresh(){ return mNeedsRefresh; }
+ U32 getNeedsRefresh(){ return mRefreshState; }
/**
* Sets the flag indicating that the list needs to be refreshed even if it is
@@ -71,7 +71,7 @@ public:
* This is needed for example to filter items of the list hidden by closed
* accordion tab.
*/
- void doIdle(); // Real idle routine
+ virtual void doIdle(); // Real idle routine
static void idle(void* user_data); // static glue to doIdle()
protected:
@@ -94,17 +94,29 @@ protected:
void computeDifference(const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved);
/**
- * Add an item to the list
- */
- virtual void addNewItem(LLViewerInventoryItem* item, bool rearrange = true);
+ * Create panel(item) from inventory item
+ */
+ virtual LLPanel* createNewItem(LLViewerInventoryItem* item);
+
+protected:
+ enum ERefreshStates
+ {
+ REFRESH_COMPLETE = 0,
+ REFRESH_LIST_SORT,
+ REFRESH_LIST_APPEND,
+ REFRESH_LIST_ERASE,
+ REFRESH_ALL
+ };
+
+ ERefreshStates mRefreshState;
private:
uuid_vec_t mIDs; // IDs of items that were added in refreshList().
// Will be used in refresh() to determine added and removed ids
uuid_vec_t mSelectTheseIDs; // IDs that will be selected if list is not loaded till now
-
- bool mNeedsRefresh;
+ uuid_vec_t mAddedItems;
+ uuid_vec_t mRemovedItems;
bool mForceRefresh;
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/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h
index 19fbfc2ed3..00d2908c1b 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.h
+++ b/indra/newview/llinventorymodelbackgroundfetch.h
@@ -43,9 +43,9 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch>
{
-public:
- LLInventoryModelBackgroundFetch();
+ LLSINGLETON(LLInventoryModelBackgroundFetch);
~LLInventoryModelBackgroundFetch();
+public:
// Start and stop background breadth-first fetching of inventory contents.
// This gets triggered when performing a filter-search.
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index ce8705b7ac..4427f32de9 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -656,7 +656,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
}
}
-bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb)
+bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb, bool init_name_hash)
{
S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN;
S32 current_num_known_descendents = LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN;
@@ -694,8 +694,15 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t
if (can_be_added)
{
- mCategoryMap.insert(category_map_value_t(
- cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents)));
+ if(init_name_hash)
+ {
+ LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
+ mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents,item_name_hash)));
+ }
+ else
+ {
+ mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents)));
+ }
}
return can_be_added;
@@ -718,6 +725,18 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
mItemNameHash.finalize();
}
+LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
+ const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash)
+
+ : mCatID(cat_id)
+ , mCallback(cb)
+ , mVersion(version)
+ , mDescendentsCount(num_descendents)
+ , mIsNameHashInitialized(true)
+ , mItemNameHash(name_hash)
+{
+}
+
void LLScrollOnRenameObserver::changed(U32 mask)
{
if (mask & LLInventoryObserver::LABEL)
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index 8cf6a6bdab..36d8ee3f59 100644
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -267,14 +267,14 @@ public:
* @return "true" if category was added, "false" if it could
* not be found.
*/
- bool addCategory(const LLUUID& cat_id, callback_t cb);
+ bool addCategory(const LLUUID& cat_id, callback_t cb, bool init_name_hash = false);
void removeCategory(const LLUUID& cat_id);
protected:
struct LLCategoryData
{
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents);
-
+ LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash);
callback_t mCallback;
S32 mVersion;
S32 mDescendentsCount;
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/lllocationhistory.h b/indra/newview/lllocationhistory.h
index 9fef42c5df..1cecbabd3b 100644
--- a/indra/newview/lllocationhistory.h
+++ b/indra/newview/lllocationhistory.h
@@ -103,6 +103,7 @@ public:
class LLLocationHistory: public LLSingleton<LLLocationHistory>
{
+ LLSINGLETON(LLLocationHistory);
LOG_CLASS(LLLocationHistory);
public:
@@ -117,7 +118,6 @@ public:
typedef boost::function<void(EChangeType event)> history_changed_callback_t;
typedef boost::signals2::signal<void(EChangeType event)> history_changed_signal_t;
- LLLocationHistory();
void addItem(const LLLocationHistoryItem& item);
bool touchItem(const LLLocationHistoryItem& item);
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..b9194c6c67 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -132,15 +132,9 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner>
{
-public:
- LLLogChatTimeScanner()
- {
- // Note, date/time facets will be destroyed by string streams
- mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT)));
- mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT)));
- mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT)));
- }
+ LLSINGLETON(LLLogChatTimeScanner);
+public:
date getTodayPacificDate()
{
typedef boost::date_time::local_adjustor<ptime, -8, no_dst> pst;
@@ -205,6 +199,15 @@ private:
std::stringstream mTimeStream;
};
+inline
+LLLogChatTimeScanner::LLLogChatTimeScanner()
+{
+ // Note, date/time facets will be destroyed by string streams
+ mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT)));
+ mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT)));
+ mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT)));
+}
+
LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL;
std::map<LLUUID,LLLoadHistoryThread *> LLLogChat::sLoadHistoryThreads;
@@ -244,7 +247,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/lllogininstance.h b/indra/newview/lllogininstance.h
index c6773bbf68..282ddc1cea 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -40,12 +40,12 @@ class LLUpdaterService;
// negotiate user authentication attempts.
class LLLoginInstance : public LLSingleton<LLLoginInstance>
{
+ LLSINGLETON(LLLoginInstance);
+ ~LLLoginInstance();
+
public:
class Disposable;
- LLLoginInstance();
- ~LLLoginInstance();
-
void connect(LLPointer<LLCredential> credentials); // Connect to the current grid choice.
void connect(const std::string& uri, LLPointer<LLCredential> credentials); // Connect to the given uri.
void reconnect(); // reconnect using the current credentials.
diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h
index f84c0ca94c..2ec3a74e4a 100644
--- a/indra/newview/llmainlooprepeater.h
+++ b/indra/newview/llmainlooprepeater.h
@@ -43,9 +43,8 @@
class LLMainLoopRepeater:
public LLSingleton<LLMainLoopRepeater>
{
+ LLSINGLETON(LLMainLoopRepeater);
public:
- LLMainLoopRepeater(void);
-
// Start the repeater service.
void start(void);
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/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index 9d795c6ced..ec312baca3 100644
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -86,11 +86,10 @@ namespace MarketplaceFetchCodes
class LLMarketplaceInventoryImporter
: public LLSingleton<LLMarketplaceInventoryImporter>
{
+ LLSINGLETON(LLMarketplaceInventoryImporter);
public:
static void update();
-
- LLMarketplaceInventoryImporter();
-
+
typedef boost::signals2::signal<void (bool)> status_changed_signal_t;
typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t;
@@ -181,10 +180,11 @@ class LLSLMDeleteListingsResponder;
class LLMarketplaceData
: public LLSingleton<LLMarketplaceData>
{
- friend class LLSingleton < LLMarketplaceData > ;
+ LLSINGLETON(LLMarketplaceData);
+ virtual ~LLMarketplaceData();
public:
- friend class LLSLMGetMerchantResponder;
+ friend class LLSLMGetMerchantResponder;
friend class LLSLMGetListingsResponder;
friend class LLSLMCreateListingsResponder;
friend class LLSLMGetListingResponder;
@@ -242,9 +242,6 @@ public:
void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);
private:
- LLMarketplaceData();
- virtual ~LLMarketplaceData();
-
// Modify Marketplace data set : each method returns true if the function succeeds, false if error
// Used internally only by SLM Responders when data are received from the SLM Server
bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count);
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index 36dd0904b6..60b58d17de 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -38,9 +38,7 @@ class LLViewerRegion;
class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
{
- friend class LLSingleton<LLMaterialMgr>;
-protected:
- LLMaterialMgr();
+ LLSINGLETON(LLMaterialMgr);
virtual ~LLMaterialMgr();
public:
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/llmenuoptionpathfindingrebakenavmesh.cpp b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
index 8879cfd7fb..63d97f6ac2 100644
--- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
+++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
@@ -41,8 +41,7 @@
#include "llpathfindingnavmeshstatus.h"
#include "llviewerregion.h"
-LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh()
- : LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>(),
+LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh() :
mIsInitialized(false),
mCanRebakeRegion(false),
mRebakeNavMeshMode(kRebakeNavMesh_Default),
diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.h b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h
index 7b1d2873ba..649a387dd3 100644
--- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.h
+++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h
@@ -37,6 +37,8 @@ class LLPathfindingNavMeshStatus;
class LLMenuOptionPathfindingRebakeNavmesh : public LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>
{
+ LLSINGLETON(LLMenuOptionPathfindingRebakeNavmesh);
+ virtual ~LLMenuOptionPathfindingRebakeNavmesh();
LOG_CLASS(LLMenuOptionPathfindingRebakeNavmesh);
public:
@@ -49,8 +51,6 @@ public:
kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable
} ERebakeNavMeshMode;
- LLMenuOptionPathfindingRebakeNavmesh();
- virtual ~LLMenuOptionPathfindingRebakeNavmesh();
void initialize();
void quit();
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/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 01cf68bcda..0f70c9d13f 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -47,6 +47,7 @@
#include "pipeline.h"
#include <boost/tokenizer.hpp>
+#include <boost/bind.hpp>
#include "lldispatcher.h"
#include "llxfermanager.h"
@@ -56,6 +57,7 @@
#include "llworld.h" //for particle system banning
#include "llimview.h"
#include "llnotifications.h"
+#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
#include "lltrans.h"
@@ -146,22 +148,6 @@ std::string LLMute::getDisplayType() const
}
}
-
-/* static */
-LLMuteList* LLMuteList::getInstance()
-{
- // Register callbacks at the first time that we find that the message system has been created.
- static BOOL registered = FALSE;
- if( !registered && gMessageSystem != NULL)
- {
- registered = TRUE;
- // Register our various callbacks
- gMessageSystem->setHandlerFuncFast(_PREHASH_MuteListUpdate, processMuteListUpdate);
- gMessageSystem->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList);
- }
- return LLSingleton<LLMuteList>::getInstance(); // Call the "base" implementation.
-}
-
//-----------------------------------------------------------------------------
// LLMuteList()
//-----------------------------------------------------------------------------
@@ -169,6 +155,18 @@ LLMuteList::LLMuteList() :
mIsLoaded(FALSE)
{
gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
+
+ // Register our callbacks. We may be constructed before gMessageSystem, so
+ // use callWhenReady() to register them as soon as gMessageSystem becomes
+ // available.
+ // When using bind(), must be explicit about default arguments such as
+ // that last NULL.
+ gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1,
+ _PREHASH_MuteListUpdate, processMuteListUpdate,
+ static_cast<void**>(NULL)));
+ gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1,
+ _PREHASH_UseCachedMuteList, processUseCachedMuteList,
+ static_cast<void**>(NULL)));
}
//-----------------------------------------------------------------------------
@@ -231,6 +229,16 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags)
return FALSE;
}
+ S32 mute_list_limit = gSavedSettings.getS32("MuteListLimit");
+ if (getMutes().size() >= mute_list_limit)
+ {
+ LL_WARNS() << "Mute limit is reached; ignored" << LL_ENDL;
+ LLSD args;
+ args["MUTE_LIMIT"] = mute_list_limit;
+ LLNotifications::instance().add(LLNotification::Params("MuteLimitReached").substitutions(args));
+ return FALSE;
+ }
+
if (mute.mType == LLMute::BY_NAME)
{
// Can't mute empty string by name
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index 4e7b6ee880..4ceddc97fd 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -71,6 +71,8 @@ public:
class LLMuteList : public LLSingleton<LLMuteList>
{
+ LLSINGLETON(LLMuteList);
+ ~LLMuteList();
public:
// reasons for auto-unmuting a resident
enum EAutoReason
@@ -81,13 +83,6 @@ public:
AR_COUNT // enum count
};
- LLMuteList();
- ~LLMuteList();
-
- // Implemented locally so that we can perform some delayed initialization.
- // Callers should be careful to call this one and not LLSingleton<LLMuteList>::getInstance()
- // which would circumvent that mechanism. -MG
- static LLMuteList* getInstance();
void addObserver(LLMuteListObserver* observer);
void removeObserver(LLMuteListObserver* observer);
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 29dbaedf7a..a44c6dd699 100644..100755
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -30,6 +30,7 @@
#include "llpanel.h"
#include "llbutton.h"
#include "lllayoutstack.h"
+#include "llinitdestroyclass.h"
class LLLocationInputCtrl;
class LLMenuGL;
@@ -84,12 +85,12 @@ protected:
class LLNavigationBar
: public LLPanel, public LLSingleton<LLNavigationBar>, private LLDestroyClass<LLNavigationBar>
{
+ LLSINGLETON(LLNavigationBar);
+ virtual ~LLNavigationBar();
LOG_CLASS(LLNavigationBar);
friend class LLDestroyClass<LLNavigationBar>;
-
+
public:
- LLNavigationBar();
- virtual ~LLNavigationBar();
/*virtual*/ void draw();
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h
index f37c6b833c..52c79cc689 100644
--- a/indra/newview/llnotificationmanager.h
+++ b/indra/newview/llnotificationmanager.h
@@ -46,11 +46,11 @@ class LLToast;
*/
class LLNotificationManager : public LLSingleton<LLNotificationManager>
{
- typedef std::pair<std::string, LLEventHandler*> eventhandlers;
-public:
- LLNotificationManager();
+ LLSINGLETON(LLNotificationManager);
virtual ~LLNotificationManager();
+ typedef std::pair<std::string, LLEventHandler*> eventhandlers;
+public:
//TODO: make private
// this method initialize handlers' map for different types of notifications
void init(void);
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/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp
index 3418b33d37..35fdfa88bb 100644
--- a/indra/newview/llnotificationstorage.cpp
+++ b/indra/newview/llnotificationstorage.cpp
@@ -45,9 +45,10 @@ typedef boost::function<LLNotificationResponderInterface * (const LLSD& pParams)
class LLResponderRegistry : public LLRegistrySingleton<std::string, responder_constructor_t, LLResponderRegistry>
{
- public:
- template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams);
- LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams);
+ LLSINGLETON_EMPTY_CTOR(LLResponderRegistry);
+public:
+ template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams);
+ LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams);
};
template<typename RESPONDER_TYPE> LLNotificationResponderInterface * LLResponderRegistry::create(const LLSD& pParams)
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 65fd3f95ab..8887a61857 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -106,7 +106,8 @@ BOOL LLOutfitGallery::postBuild()
{
BOOL rv = LLOutfitListBase::postBuild();
mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel");
- mGalleryPanel = getChild<LLPanel>("gallery_panel");
+ LLPanel::Params params = LLPanel::getDefaultParams(); // Don't parse XML when creating dummy LLPanel
+ mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params);
mMessageTextBox = getChild<LLTextBox>("no_outfits_txt");
mOutfitGalleryMenu = new LLOutfitGalleryContextMenu(this);
return rv;
@@ -234,6 +235,7 @@ void LLOutfitGallery::removeLastRow()
{
mRowCount--;
mGalleryPanel->removeChild(mLastRowPanel);
+ mUnusedRowPanels.push_back(mLastRowPanel);
mRowPanels.pop_back();
mLastRowPanel = mRowPanels.back();
}
@@ -335,6 +337,7 @@ void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item)
{
mItemPanels.back()->removeChild(item);
mLastRowPanel->removeChild(mItemPanels.back());
+ mUnusedItemPanels.push_back(mItemPanels.back());
mItemPanels.pop_back();
}
@@ -374,7 +377,16 @@ LLPanel* LLOutfitGallery::buildItemPanel(int left)
{
LLPanel::Params lpparams;
int top = 0;
- LLPanel* lpanel = LLUICtrlFactory::create<LLPanel>(lpparams);
+ LLPanel* lpanel = NULL;
+ if(mUnusedItemPanels.empty())
+ {
+ lpanel = LLUICtrlFactory::create<LLPanel>(lpparams);
+ }
+ else
+ {
+ lpanel = mUnusedItemPanels.back();
+ mUnusedItemPanels.pop_back();
+ }
LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top);
lpanel->setRect(rect);
lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight);
@@ -387,7 +399,16 @@ LLPanel* LLOutfitGallery::buildItemPanel(int left)
LLPanel* LLOutfitGallery::buildRowPanel(int left, int bottom)
{
LLPanel::Params sparams;
- LLPanel* stack = LLUICtrlFactory::create<LLPanel>(sparams);
+ LLPanel* stack = NULL;
+ if(mUnusedRowPanels.empty())
+ {
+ stack = LLUICtrlFactory::create<LLPanel>(sparams);
+ }
+ else
+ {
+ stack = mUnusedRowPanels.back();
+ mUnusedRowPanels.pop_back();
+ }
moveRowPanel(stack, left, bottom);
return stack;
}
@@ -417,6 +438,19 @@ LLOutfitGallery::~LLOutfitGallery()
gInventory.removeObserver(mOutfitsObserver);
}
delete mOutfitsObserver;
+
+ while (!mUnusedRowPanels.empty())
+ {
+ LLPanel* panelp = mUnusedRowPanels.back();
+ mUnusedRowPanels.pop_back();
+ panelp->die();
+ }
+ while (!mUnusedItemPanels.empty())
+ {
+ LLPanel* panelp = mUnusedItemPanels.back();
+ mUnusedItemPanels.pop_back();
+ panelp->die();
+ }
}
void LLOutfitGallery::setFilterSubString(const std::string& string)
@@ -497,7 +531,7 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
// Start observing changes in "My Outfits" category.
mOutfitsObserver->addCategory(cat_id,
- boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id));
+ boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id), true);
outfit_category->fetch();
refreshOutfit(cat_id);
@@ -640,7 +674,6 @@ BOOL LLOutfitGalleryItem::postBuild()
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;
@@ -999,7 +1032,7 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
}
}
- if (mGalleryCreated)
+ if (mGalleryCreated && !LLApp::isQuitting())
{
reArrangeRows();
}
@@ -1093,7 +1126,7 @@ void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)
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).
+ S32 expected_upload_cost = LLGlobalEconomy::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;
diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h
index 6b13f264a4..b9fc10f015 100644
--- a/indra/newview/lloutfitgallery.h
+++ b/indra/newview/lloutfitgallery.h
@@ -158,6 +158,8 @@ private:
void moveRowPanel(LLPanel* stack, int left, int bottom);
std::vector<LLPanel*> mRowPanels;
std::vector<LLPanel*> mItemPanels;
+ std::vector<LLPanel*> mUnusedRowPanels;
+ std::vector<LLPanel*> mUnusedItemPanels;
std::vector<LLOutfitGalleryItem*> mItems;
std::vector<LLOutfitGalleryItem*> mHiddenItems;
LLScrollContainer* mScrollPanel;
@@ -273,7 +275,6 @@ private:
LLTextBox* mOutfitNameText;
LLTextBox* mOutfitWornText;
LLPanel* mTextBgPanel;
- LLPanel* mFotoBgPanel;
bool mSelected;
bool mWorn;
bool mDefaultImage;
diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h
index 87d4b0c998..77041db68d 100644
--- a/indra/newview/lloutfitobserver.h
+++ b/indra/newview/lloutfitobserver.h
@@ -36,10 +36,10 @@
*/
class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitObserver>
{
-public:
+ LLSINGLETON(LLOutfitObserver);
virtual ~LLOutfitObserver();
- friend class LLSingleton<LLOutfitObserver>;
+public:
virtual void changed(U32 mask);
@@ -58,7 +58,6 @@ public:
void addOutfitLockChangedCallback(const signal_t::slot_type& cb) { mOutfitLockChanged.connect(cb); }
protected:
- LLOutfitObserver();
/** Get a version of an inventory category specified by its UUID */
static S32 getCategoryVersion(const LLUUID& cat_id);
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index b7e1b2d3a4..f2d43a1037 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -117,8 +117,7 @@ class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary>
//--------------------------------------------------------------------
// Constructors and Destructors
//--------------------------------------------------------------------
-public:
- LLEditWearableDictionary();
+ LLSINGLETON(LLEditWearableDictionary);
virtual ~LLEditWearableDictionary();
//--------------------------------------------------------------------
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 7510002e98..c9fc1cc33e 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1249,6 +1249,18 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
return parent ? parent->canShare() : FALSE;
}
+ if (command_name == "empty_trash")
+ {
+ const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id);
+ return children != LLInventoryModel::CHILDREN_NO;
+ }
+ if (command_name == "empty_lostnfound")
+ {
+ const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id);
+ return children != LLInventoryModel::CHILDREN_NO;
+ }
return TRUE;
}
@@ -1307,7 +1319,7 @@ void LLPanelMainInventory::setUploadCostIfNeeded()
LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload");
if(upload_menu)
{
- S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
std::string cost_str;
// getPriceUpload() returns -1 if no data available yet.
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index b6fcca38e9..208ee77f2d 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -778,6 +778,10 @@ void LLPanelOutfitEdit::onVisibilityChanged(const LLSD &in_visible_chain)
{
update();
}
+ else
+ {
+ mWearableListManager->holdProgress(); //list population restarts with visibility
+ }
}
void LLPanelOutfitEdit::onAddWearableClicked(void)
@@ -1058,9 +1062,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 3f700496a9..3a35c49007 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -42,6 +42,7 @@
#include "llpanelwearing.h"
#include "llsaveoutfitcombobtn.h"
#include "llsidepanelappearance.h"
+#include "llviewercontrol.h"
#include "llviewerfoldertype.h"
static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
@@ -67,6 +68,10 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
{
+ if (mAppearanceTabs)
+ {
+ gSavedSettings.setS32("LastAppearanceTab", mAppearanceTabs->getCurrentPanelIndex());
+ }
}
// virtual
@@ -87,6 +92,9 @@ BOOL LLPanelOutfitsInventory::postBuild()
mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this, true));
+ if (!mAppearanceTabs->selectTab(gSavedSettings.getS32("LastAppearanceTab")))
+ mAppearanceTabs->selectFirstTab();
+
return TRUE;
}
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 2fa4ee376a..610b3a6396 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -502,10 +502,6 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
if(!parcel->getGroupID().isNull())
{
- // FIXME: Using parcel group as region group.
- gCacheName->getGroup(parcel->getGroupID(),
- boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2));
-
std::string owner =
LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString();
mParcelOwner->setText(owner);
@@ -524,12 +520,20 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString();
mParcelOwner->setText(parcel_owner);
LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText));
+ mRegionGroupText->setText( getString("none_text"));
}
if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
{
mRegionOwnerText->setText(mRegionOwnerText->getText() + getString("sale_pending_text"));
}
+
+ if(!parcel->getGroupID().isNull())
+ {
+ // FIXME: Using parcel group as region group.
+ gCacheName->getGroup(parcel->getGroupID(),
+ boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2));
+ }
}
mEstateRatingText->setText(region->getSimAccessString());
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index a9a0c30e26..5d43c38612 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -711,6 +711,34 @@ void LLPanelPlaces::onEditButtonClicked()
updateVerbs();
}
+class LLUpdateLandmarkParent : public LLInventoryCallback
+{
+public:
+ LLUpdateLandmarkParent(LLPointer<LLViewerInventoryItem> item, LLUUID new_parent) :
+ mItem(item),
+ mNewParentId(new_parent)
+ {};
+ /* virtual */ void fire(const LLUUID& inv_item_id)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ mItem->setParent(mNewParentId);
+ mItem->updateParentOnServer(FALSE);
+
+ gInventory.updateItem(mItem);
+ gInventory.notifyObservers();
+ }
+
+private:
+ LLPointer<LLViewerInventoryItem> mItem;
+ LLUUID mNewParentId;
+};
+
void LLPanelPlaces::onSaveButtonClicked()
{
if (!mLandmarkInfo || mItem.isNull())
@@ -726,6 +754,7 @@ void LLPanelPlaces::onSaveButtonClicked()
LLUUID item_id = mItem->getUUID();
LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
+ bool change_parent = folder_id != mItem->getParentUUID();
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem);
@@ -734,10 +763,16 @@ void LLPanelPlaces::onSaveButtonClicked()
{
new_item->rename(current_title_value);
new_item->setDescription(current_notes_value);
- new_item->updateServer(FALSE);
+ LLPointer<LLInventoryCallback> cb;
+ if (change_parent)
+ {
+ cb = new LLUpdateLandmarkParent(new_item, folder_id);
+ }
+ LLInventoryModel::LLCategoryUpdate up(mItem->getParentUUID(), 0);
+ gInventory.accountForUpdate(up);
+ update_inventory_item(new_item, cb);
}
-
- if(folder_id != mItem->getParentUUID())
+ else if (change_parent)
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1);
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/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index b2952834fb..21ac7604ff 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -135,7 +135,7 @@ BOOL LLPanelSnapshotInventory::postBuild()
// virtual
void LLPanelSnapshotInventory::onOpen(const LLSD& key)
{
- getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()));
+ getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload()));
LLPanelSnapshot::onOpen(key);
}
@@ -155,7 +155,7 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
void LLPanelSnapshotInventoryBase::onSend()
{
- S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
if (can_afford_transaction(expected_upload_cost))
{
if (mSnapshotFloater)
@@ -191,7 +191,7 @@ BOOL LLPanelOutfitSnapshotInventory::postBuild()
// virtual
void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key)
{
- getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()));
+ getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload()));
LLPanelSnapshot::onOpen(key);
}
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 269f16c5e4..95c14e4226 100644
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -77,12 +77,12 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions()
mCommitCallbackRegistrar.add("Snapshot.SendToFacebook", boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this));
mCommitCallbackRegistrar.add("Snapshot.SendToTwitter", boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this));
mCommitCallbackRegistrar.add("Snapshot.SendToFlickr", boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this));
- LLGlobalEconomy::Singleton::getInstance()->addObserver(this);
+ LLGlobalEconomy::getInstance()->addObserver(this);
}
LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
{
- LLGlobalEconomy::Singleton::getInstance()->removeObserver(this);
+ LLGlobalEconomy::getInstance()->removeObserver(this);
}
// virtual
@@ -100,7 +100,7 @@ void LLPanelSnapshotOptions::onOpen(const LLSD& key)
void LLPanelSnapshotOptions::updateUploadCost()
{
- S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost));
}
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 3de9dc2f80..fe0608d544 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -104,7 +104,9 @@ private:
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> {
+class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage>
+{
+ LLSINGLETON_EMPTY_CTOR(LLTeleportHistoryFlatItemStorage);
protected:
typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t;
diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h
index f37bd9c048..78dd997029 100644
--- a/indra/newview/llpaneltopinfobar.h
+++ b/indra/newview/llpaneltopinfobar.h
@@ -28,6 +28,7 @@
#define LLPANELTOPINFOBAR_H_
#include "llpanel.h"
+#include "llinitdestroyclass.h"
class LLButton;
class LLTextBox;
@@ -36,6 +37,8 @@ class LLParcelChangeObserver;
class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>, private LLDestroyClass<LLPanelTopInfoBar>
{
+ LLSINGLETON(LLPanelTopInfoBar);
+ ~LLPanelTopInfoBar();
LOG_CLASS(LLPanelTopInfoBar);
friend class LLDestroyClass<LLPanelTopInfoBar>;
@@ -43,9 +46,6 @@ class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>,
public:
typedef boost::signals2::signal<void ()> resize_signal_t;
- LLPanelTopInfoBar();
- ~LLPanelTopInfoBar();
-
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
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/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index 711a869e82..cb4c07a417 100644
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -144,8 +144,7 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr;
// LLPathfindingManager
//---------------------------------------------------------------------------
-LLPathfindingManager::LLPathfindingManager()
- : LLSingleton<LLPathfindingManager>(),
+LLPathfindingManager::LLPathfindingManager():
mNavMeshMap(),
mAgentStateSignal()
{
diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h
index e8fad590ba..a44cd892da 100644
--- a/indra/newview/llpathfindingmanager.h
+++ b/indra/newview/llpathfindingmanager.h
@@ -48,6 +48,9 @@ class LinksetsResponder;
class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
{
+ LLSINGLETON(LLPathfindingManager);
+ virtual ~LLPathfindingManager();
+
friend class LLNavMeshSimStateChangeNode;
friend class NavMeshStatusResponder;
friend class LLAgentStateChangeNode;
@@ -60,9 +63,6 @@ public:
kRequestError
} ERequestStatus;
- LLPathfindingManager();
- virtual ~LLPathfindingManager();
-
void initSystem();
void quitSystem();
diff --git a/indra/newview/llpathfindingpathtool.cpp b/indra/newview/llpathfindingpathtool.cpp
index 006755e20b..3187325101 100644
--- a/indra/newview/llpathfindingpathtool.cpp
+++ b/indra/newview/llpathfindingpathtool.cpp
@@ -46,7 +46,6 @@
LLPathfindingPathTool::LLPathfindingPathTool()
: LLTool(PATH_TOOL_NAME),
- LLSingleton<LLPathfindingPathTool>(),
mFinalPathData(),
mTempPathData(),
mPathResult(LLPathingLib::LLPL_NO_PATH),
diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h
index 97284265f1..88cb3a15f8 100644
--- a/indra/newview/llpathfindingpathtool.h
+++ b/indra/newview/llpathfindingpathtool.h
@@ -36,6 +36,9 @@
class LLPathfindingPathTool : public LLTool, public LLSingleton<LLPathfindingPathTool>
{
+ LLSINGLETON(LLPathfindingPathTool);
+ virtual ~LLPathfindingPathTool();
+
public:
typedef enum
{
@@ -59,9 +62,6 @@ public:
kCharacterTypeD
} ECharacterType;
- LLPathfindingPathTool();
- virtual ~LLPathfindingPathTool();
-
typedef boost::function<void (void)> path_event_callback_t;
typedef boost::signals2::signal<void (void)> path_event_signal_t;
typedef boost::signals2::connection path_event_slot_t;
diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp
index 9c0222d0bc..264382ae82 100644
--- a/indra/newview/llpersistentnotificationstorage.cpp
+++ b/indra/newview/llpersistentnotificationstorage.cpp
@@ -36,9 +36,8 @@
#include "llscriptfloater.h"
#include "llviewermessage.h"
#include "llviewernetwork.h"
-LLPersistentNotificationStorage::LLPersistentNotificationStorage()
- : LLSingleton<LLPersistentNotificationStorage>()
- , LLNotificationStorage("")
+LLPersistentNotificationStorage::LLPersistentNotificationStorage():
+ LLNotificationStorage("")
, mLoaded(false)
{
}
diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h
index bf0306380e..40c9923c74 100644
--- a/indra/newview/llpersistentnotificationstorage.h
+++ b/indra/newview/llpersistentnotificationstorage.h
@@ -45,10 +45,10 @@ class LLSD;
class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>, public LLNotificationStorage
{
+ LLSINGLETON(LLPersistentNotificationStorage);
+ ~LLPersistentNotificationStorage();
LOG_CLASS(LLPersistentNotificationStorage);
public:
- LLPersistentNotificationStorage();
- ~LLPersistentNotificationStorage();
void saveNotifications();
void loadNotifications();
diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp
index 9957039f72..f40b3e0295 100644
--- a/indra/newview/llpresetsmanager.cpp
+++ b/indra/newview/llpresetsmanager.cpp
@@ -55,6 +55,10 @@ void LLPresetsManager::triggerChangeSignal()
void LLPresetsManager::createMissingDefault()
{
+ if(gDirUtilp->getLindenUserDir().empty())
+ {
+ return;
+ }
std::string default_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, PRESETS_GRAPHIC, PRESETS_DEFAULT + ".xml");
if (!gDirUtilp->fileExists(default_file))
{
@@ -104,8 +108,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/llpresetsmanager.h b/indra/newview/llpresetsmanager.h
index 21f9885f27..0014e32267 100644
--- a/indra/newview/llpresetsmanager.h
+++ b/indra/newview/llpresetsmanager.h
@@ -46,6 +46,9 @@ enum EDefaultOptions
class LLPresetsManager : public LLSingleton<LLPresetsManager>
{
+ LLSINGLETON(LLPresetsManager);
+ ~LLPresetsManager();
+
public:
typedef std::list<std::string> preset_name_list_t;
@@ -67,9 +70,6 @@ public:
preset_name_list_t mPresetNames;
- LLPresetsManager();
- ~LLPresetsManager();
-
preset_list_signal_t mPresetListChangeSignal;
private:
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/llproductinforequest.h b/indra/newview/llproductinforequest.h
index 75dbf220d1..d1036374e8 100644
--- a/indra/newview/llproductinforequest.h
+++ b/indra/newview/llproductinforequest.h
@@ -41,12 +41,11 @@
*/
class LLProductInfoRequestManager : public LLSingleton<LLProductInfoRequestManager>
{
+ LLSINGLETON(LLProductInfoRequestManager);
public:
- LLProductInfoRequestManager();
std::string getDescriptionForSku(const std::string& sku);
private:
- friend class LLSingleton<LLProductInfoRequestManager>;
/* virtual */ void initSingleton();
void getLandDescriptionsCoro(std::string url);
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index d0d6376867..c7aaf604f5 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -50,6 +50,7 @@ class LLDate;
*/
class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LLSimpleListener
{
+ LLSINGLETON_EMPTY_CTOR(LLRecentPeople);
LOG_CLASS(LLRecentPeople);
public:
typedef boost::signals2::signal<void ()> signal_t;
diff --git a/indra/newview/llregioninfomodel.h b/indra/newview/llregioninfomodel.h
index d22a0de463..ea9640efda 100644
--- a/indra/newview/llregioninfomodel.h
+++ b/indra/newview/llregioninfomodel.h
@@ -36,6 +36,7 @@ class LLMessageSystem;
*/
class LLRegionInfoModel : public LLSingleton<LLRegionInfoModel>
{
+ LLSINGLETON(LLRegionInfoModel);
LOG_CLASS(LLRegionInfoModel);
public:
@@ -73,10 +74,8 @@ public:
std::string mSimType;
protected:
- friend class LLSingleton<LLRegionInfoModel>;
friend class LLViewerRegion;
- LLRegionInfoModel();
/**
* Refresh model with data from the incoming server message.
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index cb5af50c5f..5b0d189137 100644
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -74,9 +74,10 @@ protected:
class LLRemoteParcelInfoProcessor : public LLSingleton<LLRemoteParcelInfoProcessor>
{
-public:
+ LLSINGLETON_EMPTY_CTOR(LLRemoteParcelInfoProcessor);
virtual ~LLRemoteParcelInfoProcessor() {}
+public:
void addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer);
void removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer);
diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h
index 5223a314f3..2ac958e7b8 100644
--- a/indra/newview/llrootview.h
+++ b/indra/newview/llrootview.h
@@ -32,7 +32,9 @@
#include "lltooltip.h"
class LLRootViewRegistry : public LLChildRegistry<LLRootViewRegistry>
-{};
+{
+ LLSINGLETON(LLRootViewRegistry);
+};
class LLRootView : public LLView
{
diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h
index 2b6ea57b96..7cd531bd34 100644
--- a/indra/newview/llscenemonitor.h
+++ b/indra/newview/llscenemonitor.h
@@ -39,10 +39,10 @@ class LLViewerTexture;
class LLSceneMonitor : public LLSingleton<LLSceneMonitor>
{
+ LLSINGLETON(LLSceneMonitor);
+ ~LLSceneMonitor();
LOG_CLASS(LLSceneMonitor);
public:
- LLSceneMonitor();
- ~LLSceneMonitor();
void freezeAvatar(LLCharacter* avatarp);
void setDebugViewerVisible(bool visible);
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index ba2c37ce7c..681787bcbe 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -117,6 +117,14 @@ BOOL LLScreenChannelBase::postBuild()
void LLScreenChannelBase::reshape(S32 width, S32 height, BOOL called_from_parent)
{
+ if (mChannelAlignment == CA_CENTRE)
+ {
+ // Keep notifications and alerts centered
+ // WorldViewRectScaled is out of date at reshape but Window has same width
+ S32 channel_bound = gViewerWindow->getWindowRectScaled().getWidth() / 2;
+ setRect(LLRect(channel_bound, 0, channel_bound, 0));
+ updateRect(); //sets top and bottom only
+ }
redrawToasts();
}
diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h
index 70451194b3..c0b84abdcb 100644
--- a/indra/newview/llscriptfloater.h
+++ b/indra/newview/llscriptfloater.h
@@ -41,6 +41,7 @@ class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager>
// *TODO
// LLScriptFloaterManager and LLScriptFloater will need some refactoring after we
// know how script notifications should look like.
+ LLSINGLETON_EMPTY_CTOR(LLScriptFloaterManager);
public:
typedef enum e_object_type
diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h
index 3309a8fcac..5aab5e6765 100644
--- a/indra/newview/llsearchhistory.h
+++ b/indra/newview/llsearchhistory.h
@@ -28,6 +28,7 @@
#define LL_LLSEARCHHISTORY_H
#include "llsingleton.h"
+#include "llinitdestroyclass.h"
#include "llui.h"
/**
@@ -36,6 +37,7 @@
*/
class LLSearchHistory : public LLSingleton<LLSearchHistory>, private LLDestroyClass<LLSearchHistory>
{
+ LLSINGLETON(LLSearchHistory);
friend class LLDestroyClass<LLSearchHistory>;
public:
@@ -71,7 +73,6 @@ public:
*/
void addEntry(const std::string& search_text);
- LLSearchHistory();
/**
* Class for storing data about single search request.
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 323689b788..e07c11b1e3 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -6244,6 +6244,9 @@ void pushWireframe(LLDrawable* drawable)
void LLSelectNode::renderOneWireframe(const LLColor4& color)
{
+ //Need to because crash on ATI 3800 (and similar cards) MAINT-5018
+ LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
LLViewerObject* objectp = getObject();
if (!objectp)
{
@@ -7197,7 +7200,9 @@ U32 LLObjectSelection::getSelectedObjectTriangleCount(S32* vcount)
if (object)
{
- count += object->getTriangleCount(vcount);
+ S32 vt = 0;
+ count += object->getTriangleCount(&vt);
+ *vcount += vt;
}
}
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index bc50e443f8..c167ecd236 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -388,6 +388,9 @@ struct LLSelectGetFirstTest;
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
{
+ LLSINGLETON(LLSelectMgr);
+ ~LLSelectMgr();
+
public:
static BOOL sRectSelectInclusive; // do we need to surround an object to pick it?
static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded?
@@ -413,9 +416,6 @@ public:
LLCachedControl<bool> mDebugSelectMgr;
public:
- LLSelectMgr();
- ~LLSelectMgr();
-
static void cleanupGlobals();
// LLEditMenuHandler interface
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 049aae1336..58e48480c1 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -465,7 +465,11 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare
LL_DEBUGS() << "window reshaped, updating thumbnail" << LL_ENDL;
if (mViewContainer && mViewContainer->isInVisibleChain())
{
- updateSnapshot(TRUE);
+ // We usually resize only on window reshape, so give it a chance to redraw, assign delay
+ updateSnapshot(
+ TRUE, // new snapshot is needed
+ FALSE, // thumbnail will be updated either way.
+ AUTO_SNAPSHOT_TIME_DELAY); // shutter delay.
}
}
}
@@ -1032,7 +1036,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
std::string who_took_it;
LLAgentUI::buildFullname(who_took_it);
- S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
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;
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 5cff70f377..617bae3984 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -341,20 +341,18 @@ protected:
class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
{
+ LLSINGLETON(LLActiveSpeakerMgr);
LOG_CLASS(LLActiveSpeakerMgr);
-public:
- LLActiveSpeakerMgr();
protected:
virtual void updateSpeakerList();
};
class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
{
- LOG_CLASS(LLLocalSpeakerMgr);
-public:
- LLLocalSpeakerMgr();
+ LLSINGLETON(LLLocalSpeakerMgr);
~LLLocalSpeakerMgr ();
+ LOG_CLASS(LLLocalSpeakerMgr);
protected:
virtual void updateSpeakerList();
};
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index 78fe7863c8..5ca1d4b4a5 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -48,6 +48,8 @@
*/
class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, LLVoiceClientParticipantObserver
{
+ LLSINGLETON(SpeakingIndicatorManager);
+ ~SpeakingIndicatorManager();
LOG_CLASS(SpeakingIndicatorManager);
public:
@@ -91,10 +93,6 @@ private:
typedef speaking_indicators_mmap_t::const_iterator indicator_const_iterator;
typedef std::pair<indicator_const_iterator, indicator_const_iterator> indicator_range_t;
- friend class LLSingleton<SpeakingIndicatorManager>;
- SpeakingIndicatorManager();
- ~SpeakingIndicatorManager();
-
/**
* Callback to determine when voice channel is changed.
*
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index a2c8e7772e..1bc20ccf12 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -193,6 +193,7 @@
#include "llstartuplistener.h"
#include "lltoolbarview.h"
#include "llexperiencelog.h"
+#include "llcleanup.h"
#if LL_WINDOWS
#include "lldxhardware.h"
@@ -771,7 +772,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
@@ -2804,7 +2809,7 @@ void LLStartUp::initExperiences()
void LLStartUp::cleanupNameCache()
{
- LLAvatarNameCache::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLAvatarNameCache);
delete gCacheName;
gCacheName = NULL;
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 041eae4b3c..72c5c961aa 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -309,7 +309,7 @@ void LLStatusBar::refresh()
(LLViewerMedia::hasInWorldMedia() || LLViewerMedia::hasParcelMedia() || LLViewerMedia::hasParcelAudio());
mMediaToggle->setEnabled(button_enabled);
// Note the "sense" of the toggle is opposite whether media is playing or not
- bool any_media_playing = (LLViewerMedia::isAnyMediaShowing() ||
+ bool any_media_playing = (LLViewerMedia::isAnyMediaPlaying() ||
LLViewerMedia::isParcelMediaPlaying() ||
LLViewerMedia::isParcelAudioPlaying());
mMediaToggle->setValue(!any_media_playing);
@@ -562,8 +562,8 @@ void LLStatusBar::onClickMediaToggle(void* data)
{
LLStatusBar *status_bar = (LLStatusBar*)data;
// "Selected" means it was showing the "play" icon (so media was playing), and now it shows "pause", so turn off media
- bool enable = ! status_bar->mMediaToggle->getValue();
- LLViewerMedia::setAllMediaEnabled(enable);
+ bool pause = status_bar->mMediaToggle->getValue();
+ LLViewerMedia::setAllMediaPaused(pause);
}
BOOL can_afford_transaction(S32 cost)
diff --git a/indra/newview/llstylemap.h b/indra/newview/llstylemap.h
index 8aa0af535c..96b3920593 100644
--- a/indra/newview/llstylemap.h
+++ b/indra/newview/llstylemap.h
@@ -39,6 +39,7 @@ typedef std::map<LLUUID, LLStyle::Params> style_map_t;
class LLStyleMap : public LLSingleton<LLStyleMap>
{
+ LLSINGLETON_EMPTY_CTOR(LLStyleMap);
public:
// Just like the [] accessor but it will add the entry in if it doesn't exist.
const LLStyle::Params &lookupAgent(const LLUUID &source);
diff --git a/indra/newview/llsyntaxid.h b/indra/newview/llsyntaxid.h
index 0afa6dc04b..1360b3e042 100644
--- a/indra/newview/llsyntaxid.h
+++ b/indra/newview/llsyntaxid.h
@@ -38,9 +38,9 @@ class fetchKeywordsFileResponder;
class LLSyntaxIdLSL : public LLSingleton<LLSyntaxIdLSL>
{
- friend class LLSingleton<LLSyntaxIdLSL>;
+ LLSINGLETON(LLSyntaxIdLSL);
friend class fetchKeywordsFileResponder;
-
+
private:
std::set<std::string> mInflightFetches;
typedef boost::signals2::signal<void()> syntax_id_changed_signal_t;
@@ -67,7 +67,6 @@ private:
LLSD mKeywordsXml;
public:
- LLSyntaxIdLSL();
void initialize();
bool keywordFetchInProgress();
LLSD getKeywordsXML() const { return mKeywordsXml; };
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index d02293e6ff..b96a2573a1 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -32,6 +32,7 @@
#include "llscreenchannel.h"
#include "llsyswellitem.h"
#include "lltransientdockablefloater.h"
+#include "llinitdestroyclass.h"
class LLAvatarName;
class LLChiclet;
diff --git a/indra/newview/llteleporthistory.h b/indra/newview/llteleporthistory.h
index e9c29c39bf..db0ccdda59 100644
--- a/indra/newview/llteleporthistory.h
+++ b/indra/newview/llteleporthistory.h
@@ -73,6 +73,8 @@ public:
*/
class LLTeleportHistory: public LLSingleton<LLTeleportHistory>
{
+ LLSINGLETON(LLTeleportHistory);
+ ~LLTeleportHistory();
LOG_CLASS(LLTeleportHistory);
public:
@@ -81,9 +83,6 @@ public:
typedef boost::function<void()> history_callback_t;
typedef boost::signals2::signal<void()> history_signal_t;
- LLTeleportHistory();
- ~LLTeleportHistory();
-
/**
* Go back in the history.
*/
diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h
index cf4c85a991..946ac0af1a 100644
--- a/indra/newview/llteleporthistorystorage.h
+++ b/indra/newview/llteleporthistorystorage.h
@@ -68,6 +68,8 @@ public:
*/
class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage>
{
+ LLSINGLETON(LLTeleportHistoryStorage);
+ ~LLTeleportHistoryStorage();
LOG_CLASS(LLTeleportHistoryStorage);
public:
@@ -78,9 +80,6 @@ public:
typedef boost::function<void(S32 removed_index)> history_callback_t;
typedef boost::signals2::signal<void(S32 removed_index)> history_signal_t;
- LLTeleportHistoryStorage();
- ~LLTeleportHistoryStorage();
-
/**
* @return history items.
*/
diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h
index b643056198..1b8df708c6 100644
--- a/indra/newview/lltextureatlasmanager.h
+++ b/indra/newview/lltextureatlasmanager.h
@@ -85,12 +85,11 @@ private:
class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager>
{
-private:
+ LLSINGLETON(LLTextureAtlasManager);
+ ~LLTextureAtlasManager();
typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ;
public:
- LLTextureAtlasManager();
- ~LLTextureAtlasManager();
LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
LLSpatialGroup* groupp, LLViewerTexture* imagep) ;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 37cc908e84..a541273621 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -547,10 +547,18 @@ bool LLTextureCacheRemoteWorker::doWrite()
// First state / stage : check that what we're trying to cache is in an OK shape
if (mState == INIT)
{
- llassert_always(mOffset == 0); // We currently do not support write offsets
- llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative...
- llassert_always(mImageSize >= mDataSize);
- mState = CACHE;
+ if ((mOffset != 0) // We currently do not support write offsets
+ || (mDataSize <= 0) // Things will go badly wrong if mDataSize is nul or negative...
+ || (mImageSize < mDataSize))
+ {
+ LL_WARNS() << "INIT state check failed" << LL_ENDL;
+ mDataSize = -1; // failed
+ done = true;
+ }
+ else
+ {
+ mState = CACHE;
+ }
}
// No LOCAL state for write(): because it doesn't make much sense to cache a local file...
@@ -559,7 +567,7 @@ bool LLTextureCacheRemoteWorker::doWrite()
if (!done && (mState == CACHE))
{
bool alreadyCached = false;
- LLTextureCache::Entry entry ;
+ LLTextureCache::Entry entry;
// Checks if this image is already in the entry list
idx = mCache->getHeaderCacheEntry(mID, entry);
@@ -571,107 +579,132 @@ bool LLTextureCacheRemoteWorker::doWrite()
// (almost always) write to the fast cache.
if (mRawImage->getDataSize())
{
- llassert_always(mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel));
+ if(!mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel))
+ {
+ LL_WARNS() << "writeToFastCache failed" << LL_ENDL;
+ mDataSize = -1; // failed
+ done = true;
+ }
+ }
}
}
- }
else
{
alreadyCached = mCache->updateEntry(idx, entry, mImageSize, mDataSize); // update the existing entry.
}
- if (idx < 0)
- {
- LL_WARNS() << "LLTextureCacheWorker: " << mID
- << " Unable to create header entry for writing!" << LL_ENDL;
- mDataSize = -1; // failed
- done = true;
- }
- else
+ if (!done)
{
- if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE))
+ if (idx < 0)
{
- // Small texture already cached case: we're done with writing
+ LL_WARNS() << "LLTextureCacheWorker: " << mID
+ << " Unable to create header entry for writing!" << LL_ENDL;
+ mDataSize = -1; // failed
done = true;
}
else
{
- // If the texture has already been cached, we don't resave the header and go directly to the body part
- mState = alreadyCached ? BODY : HEADER;
+ if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE))
+ {
+ // Small texture already cached case: we're done with writing
+ done = true;
+ }
+ else
+ {
+ // If the texture has already been cached, we don't resave the header and go directly to the body part
+ mState = alreadyCached ? BODY : HEADER;
+ }
}
}
}
+
// Third stage / state : write the header record in the header file (texture.cache)
if (!done && (mState == HEADER))
{
- llassert_always(idx >= 0); // we need an entry here or storing the header makes no sense
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file
- S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header
- S32 bytes_written;
-
- if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE)
+ if (idx < 0) // we need an entry here or storing the header makes no sense
{
- // We need to write a full record in the header cache so, if the amount of data is smaller
- // than a record, we need to transfer the data to a buffer padded with 0 and write that
- U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE);
- memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros
- memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer
- bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool());
- FREE_MEM(LLImageBase::getPrivatePool(), padBuffer);
+ LL_WARNS() << "index check failed" << LL_ENDL;
+ mDataSize = -1; // failed
+ done = true;
}
else
{
- // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file
- bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool());
- }
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header
+ S32 bytes_written;
- if (bytes_written <= 0)
- {
- LL_WARNS() << "LLTextureCacheWorker: " << mID
+ if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ // We need to write a full record in the header cache so, if the amount of data is smaller
+ // than a record, we need to transfer the data to a buffer padded with 0 and write that
+ U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE);
+ memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros
+ memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer
+ bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool());
+ FREE_MEM(LLImageBase::getPrivatePool(), padBuffer);
+ }
+ else
+ {
+ // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file
+ bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool());
+ }
+
+ if (bytes_written <= 0)
+ {
+ LL_WARNS() << "LLTextureCacheWorker: " << mID
<< " Unable to write header entry!" << LL_ENDL;
- mDataSize = -1; // failed
- done = true;
- }
+ mDataSize = -1; // failed
+ done = true;
+ }
- // If we wrote everything (may be more with padding) in the header cache,
- // we're done so we don't have a body to store
- if (mDataSize <= bytes_written)
- {
- done = true;
- }
- else
- {
- mState = BODY;
+ // If we wrote everything (may be more with padding) in the header cache,
+ // we're done so we don't have a body to store
+ if (mDataSize <= bytes_written)
+ {
+ done = true;
+ }
+ else
+ {
+ mState = BODY;
+ }
}
}
// Fourth stage / state : write the body file, i.e. the rest of the texture in a "UUID" file name
if (!done && (mState == BODY))
{
- llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise...
- S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE;
-
+ if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) // wouldn't make sense to be here otherwise...
{
- // build the cache file name from the UUID
- std::string filename = mCache->getTextureFileName(mID);
-// LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL;
- S32 bytes_written = LLAPRFile::writeEx( filename,
- mWriteData + TEXTURE_CACHE_ENTRY_SIZE,
- 0, file_size,
- mCache->getLocalAPRFilePool());
- if (bytes_written <= 0)
+ LL_WARNS() << "mDataSize check failed" << LL_ENDL;
+ mDataSize = -1; // failed
+ done = true;
+ }
+ else
+ {
+ S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE;
+
{
- LL_WARNS() << "LLTextureCacheWorker: " << mID
+ // build the cache file name from the UUID
+ std::string filename = mCache->getTextureFileName(mID);
+ // LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL;
+ S32 bytes_written = LLAPRFile::writeEx(filename,
+ mWriteData + TEXTURE_CACHE_ENTRY_SIZE,
+ 0, file_size,
+ mCache->getLocalAPRFilePool());
+ if (bytes_written <= 0)
+ {
+ LL_WARNS() << "LLTextureCacheWorker: " << mID
<< " incorrect number of bytes written to body: " << bytes_written
<< " / " << file_size << LL_ENDL;
- mDataSize = -1; // failed
- done = true;
+ mDataSize = -1; // failed
+ done = true;
+ }
}
+
+ // Nothing else to do at that point...
+ done = true;
}
-
- // Nothing else to do at that point...
- done = true;
}
mRawImage = NULL;
@@ -1928,6 +1961,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 adacbfe3aa..c159830c22 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -1326,7 +1326,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/lltoolbrush.h b/indra/newview/lltoolbrush.h
index 2ec6911de9..c108d83256 100644
--- a/indra/newview/lltoolbrush.h
+++ b/indra/newview/lltoolbrush.h
@@ -43,10 +43,10 @@ class LLViewerRegion;
class LLToolBrushLand : public LLTool, public LLEditMenuHandler, public LLSingleton<LLToolBrushLand>
{
+ LLSINGLETON(LLToolBrushLand);
typedef std::set<LLViewerRegion*> region_list_t;
public:
- LLToolBrushLand();
// x,y in window coords, 0,0 = left,bot
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 2b4fa757f6..d9adec82b4 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -683,7 +683,7 @@ LLToolCompGun::LLToolCompGun()
: LLToolComposite(std::string("Mouselook"))
{
mGun = new LLToolGun(this);
- mGrab = new LLToolGrab(this);
+ mGrab = new LLToolGrabBase(this);
mNull = sNullTool;
setCurrentTool(mGun);
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index e75d3c22e2..86506f725e 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -103,9 +103,9 @@ public:
class LLToolCompInspect : public LLToolComposite, public LLSingleton<LLToolCompInspect>
{
-public:
- LLToolCompInspect();
+ LLSINGLETON(LLToolCompInspect);
virtual ~LLToolCompInspect();
+public:
// Overridden from LLToolComposite
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -128,9 +128,9 @@ private:
class LLToolCompTranslate : public LLToolComposite, public LLSingleton<LLToolCompTranslate>
{
-public:
- LLToolCompTranslate();
+ LLSINGLETON(LLToolCompTranslate);
virtual ~LLToolCompTranslate();
+public:
// Overridden from LLToolComposite
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -149,9 +149,9 @@ public:
class LLToolCompScale : public LLToolComposite, public LLSingleton<LLToolCompScale>
{
-public:
- LLToolCompScale();
+ LLSINGLETON(LLToolCompScale);
virtual ~LLToolCompScale();
+public:
// Overridden from LLToolComposite
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -171,9 +171,9 @@ public:
class LLToolCompRotate : public LLToolComposite, public LLSingleton<LLToolCompRotate>
{
-public:
- LLToolCompRotate();
+ LLSINGLETON(LLToolCompRotate);
virtual ~LLToolCompRotate();
+public:
// Overridden from LLToolComposite
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -194,9 +194,9 @@ protected:
class LLToolCompCreate : public LLToolComposite, public LLSingleton<LLToolCompCreate>
{
-public:
- LLToolCompCreate();
+ LLSINGLETON(LLToolCompCreate);
virtual ~LLToolCompCreate();
+public:
// Overridden from LLToolComposite
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -214,14 +214,14 @@ protected:
// LLToolCompGun
class LLToolGun;
-class LLToolGrab;
+class LLToolGrabBase;
class LLToolSelect;
class LLToolCompGun : public LLToolComposite, public LLSingleton<LLToolCompGun>
{
-public:
- LLToolCompGun();
+ LLSINGLETON(LLToolCompGun);
virtual ~LLToolCompGun();
+public:
// Overridden from LLToolComposite
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
@@ -237,7 +237,7 @@ public:
protected:
LLToolGun* mGun;
- LLToolGrab* mGrab;
+ LLToolGrabBase* mGrab;
LLTool* mNull;
};
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 63be1ef09b..766046785b 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -43,11 +43,10 @@ class LLPickInfo;
class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
{
+ LLSINGLETON(LLToolDragAndDrop);
public:
typedef boost::signals2::signal<void ()> enddrag_signal_t;
- LLToolDragAndDrop();
-
// overridden from LLTool
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
@@ -281,8 +280,8 @@ private:
class LLDragAndDropDictionary : public LLSingleton<LLDragAndDropDictionary>,
public LLDictionary<EDragAndDropType, DragAndDropEntry>
{
+ LLSINGLETON(LLDragAndDropDictionary);
public:
- LLDragAndDropDictionary();
dragOrDrop3dImpl get(EDragAndDropType dad_type, EDropTarget drop_target);
};
};
diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h
index 7eb13b0fbc..e4b8ae12b8 100644
--- a/indra/newview/lltoolface.h
+++ b/indra/newview/lltoolface.h
@@ -35,9 +35,9 @@ class LLPickInfo;
class LLToolFace
: public LLTool, public LLSingleton<LLToolFace>
{
-public:
- LLToolFace();
+ LLSINGLETON(LLToolFace);
virtual ~LLToolFace();
+public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
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/lltoolfocus.h b/indra/newview/lltoolfocus.h
index d23eb2cce6..cfc235b6c2 100644
--- a/indra/newview/lltoolfocus.h
+++ b/indra/newview/lltoolfocus.h
@@ -34,9 +34,9 @@ class LLPickInfo;
class LLToolCamera
: public LLTool, public LLSingleton<LLToolCamera>
{
-public:
- LLToolCamera();
+ LLSINGLETON(LLToolCamera);
virtual ~LLToolCamera();
+public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index c0ca4d7a9a..ed32e584a5 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -69,7 +69,7 @@ extern BOOL gDebugClicks;
//
// Methods
//
-LLToolGrab::LLToolGrab( LLToolComposite* composite )
+LLToolGrabBase::LLToolGrabBase( LLToolComposite* composite )
: LLTool( std::string("Grab"), composite ),
mMode( GRAB_INACTIVE ),
mVerticalDragging( FALSE ),
@@ -88,12 +88,12 @@ LLToolGrab::LLToolGrab( LLToolComposite* composite )
mHideBuildHighlight(FALSE)
{ }
-LLToolGrab::~LLToolGrab()
+LLToolGrabBase::~LLToolGrabBase()
{ }
// virtual
-void LLToolGrab::handleSelect()
+void LLToolGrabBase::handleSelect()
{
if(gFloaterTools)
{
@@ -106,7 +106,7 @@ void LLToolGrab::handleSelect()
gGrabBtnSpin = FALSE;
}
-void LLToolGrab::handleDeselect()
+void LLToolGrabBase::handleDeselect()
{
if( hasMouseCapture() )
{
@@ -123,7 +123,7 @@ void LLToolGrab::handleDeselect()
}
-BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask)
+BOOL LLToolGrabBase::handleDoubleClick(S32 x, S32 y, MASK mask)
{
if (gDebugClicks)
{
@@ -133,7 +133,7 @@ BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
+BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (gDebugClicks)
{
@@ -152,7 +152,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
return TRUE;
}
-void LLToolGrab::pickCallback(const LLPickInfo& pick_info)
+void LLToolGrabBase::pickCallback(const LLPickInfo& pick_info)
{
LLToolGrab::getInstance()->mGrabPick = pick_info;
LLViewerObject *objectp = pick_info.getObject();
@@ -182,7 +182,7 @@ void LLToolGrab::pickCallback(const LLPickInfo& pick_info)
}
}
-BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
+BOOL LLToolGrabBase::handleObjectHit(const LLPickInfo& info)
{
mGrabPick = info;
LLViewerObject* objectp = mGrabPick.getObject();
@@ -315,7 +315,7 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
}
-void LLToolGrab::startSpin()
+void LLToolGrabBase::startSpin()
{
LLViewerObject* objectp = mGrabPick.getObject();
if (!objectp)
@@ -339,7 +339,7 @@ void LLToolGrab::startSpin()
}
-void LLToolGrab::stopSpin()
+void LLToolGrabBase::stopSpin()
{
mSpinGrabbing = FALSE;
@@ -373,7 +373,7 @@ void LLToolGrab::stopSpin()
}
-void LLToolGrab::startGrab()
+void LLToolGrabBase::startGrab()
{
// Compute grab_offset in the OBJECT's root's coordinate frame
// (sometimes root == object)
@@ -422,7 +422,7 @@ void LLToolGrab::startGrab()
}
-BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
+BOOL LLToolGrabBase::handleHover(S32 x, S32 y, MASK mask)
{
if (!gViewerWindow->getLeftMouseDown())
{
@@ -466,7 +466,7 @@ const F32 GRAB_SENSITIVITY_Y = 0.0075f;
// Dragging.
-void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
+void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)
{
LLViewerObject* objectp = mGrabPick.getObject();
if (!objectp || !hasMouseCapture() ) return;
@@ -724,7 +724,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
}
-void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask)
+void LLToolGrabBase::handleHoverNonPhysical(S32 x, S32 y, MASK mask)
{
LLViewerObject* objectp = mGrabPick.getObject();
if (!objectp || !hasMouseCapture() ) return;
@@ -881,7 +881,7 @@ void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask)
// Not dragging. Just showing affordances
-void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
+void LLToolGrabBase::handleHoverInactive(S32 x, S32 y, MASK mask)
{
// JC - TODO - change cursor based on gGrabBtnVertical, gGrabBtnSpin
LL_DEBUGS("UserInput") << "hover handled by LLToolGrab (inactive-not over editable object)" << LL_ENDL;
@@ -889,7 +889,7 @@ void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
}
// User is trying to do something that's not allowed.
-void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask)
+void LLToolGrabBase::handleHoverFailed(S32 x, S32 y, MASK mask)
{
if( GRAB_NOOBJECT == mMode )
{
@@ -930,7 +930,7 @@ void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask)
-BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask)
+BOOL LLToolGrabBase::handleMouseUp(S32 x, S32 y, MASK mask)
{
// call the base class to propogate info to sim
LLTool::handleMouseUp(x, y, mask);
@@ -961,7 +961,7 @@ BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
-void LLToolGrab::stopEditing()
+void LLToolGrabBase::stopEditing()
{
if( hasMouseCapture() )
{
@@ -969,7 +969,7 @@ void LLToolGrab::stopEditing()
}
}
-void LLToolGrab::onMouseCaptureLost()
+void LLToolGrabBase::onMouseCaptureLost()
{
LLViewerObject* objectp = mGrabPick.getObject();
if (!objectp)
@@ -1026,7 +1026,7 @@ void LLToolGrab::onMouseCaptureLost()
}
-void LLToolGrab::stopGrab()
+void LLToolGrabBase::stopGrab()
{
LLViewerObject* objectp = mGrabPick.getObject();
if (!objectp)
@@ -1067,29 +1067,29 @@ void LLToolGrab::stopGrab()
}
-void LLToolGrab::draw()
+void LLToolGrabBase::draw()
{ }
-void LLToolGrab::render()
+void LLToolGrabBase::render()
{ }
-BOOL LLToolGrab::isEditing()
+BOOL LLToolGrabBase::isEditing()
{
return (mGrabPick.getObject().notNull());
}
-LLViewerObject* LLToolGrab::getEditingObject()
+LLViewerObject* LLToolGrabBase::getEditingObject()
{
return mGrabPick.getObject();
}
-LLVector3d LLToolGrab::getEditingPointGlobal()
+LLVector3d LLToolGrabBase::getEditingPointGlobal()
{
return getGrabPointGlobal();
}
-LLVector3d LLToolGrab::getGrabPointGlobal()
+LLVector3d LLToolGrabBase::getGrabPointGlobal()
{
switch(mMode)
{
diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h
index 5d24c8813e..02ed5c26d7 100644
--- a/indra/newview/lltoolgrab.h
+++ b/indra/newview/lltoolgrab.h
@@ -45,12 +45,17 @@ void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, co
void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick);
-
-class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab>
+/**
+ * LLToolGrabBase contains most of the semantics of LLToolGrab. It's just that
+ * LLToolGrab is an LLSingleton, but we also explicitly instantiate
+ * LLToolGrabBase as part of LLToolCompGun. You can't just make an extra
+ * instance of an LLSingleton!
+ */
+class LLToolGrabBase : public LLTool
{
public:
- LLToolGrab( LLToolComposite* composite = NULL );
- ~LLToolGrab();
+ LLToolGrabBase(LLToolComposite* composite=NULL);
+ ~LLToolGrabBase();
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -140,10 +145,14 @@ private:
BOOL mClickedInMouselook;
};
+/// This is the LLSingleton instance of LLToolGrab.
+class LLToolGrab : public LLToolGrabBase, public LLSingleton<LLToolGrab>
+{
+ LLSINGLETON_EMPTY_CTOR(LLToolGrab);
+};
+
extern BOOL gGrabBtnVertical;
extern BOOL gGrabBtnSpin;
extern LLTool* gGrabTransientTool;
#endif // LL_TOOLGRAB_H
-
-
diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h
index 961a6a4d93..e7c2060fba 100644
--- a/indra/newview/lltoolindividual.h
+++ b/indra/newview/lltoolindividual.h
@@ -39,9 +39,9 @@ class LLPickInfo;
class LLToolIndividual : public LLTool, public LLSingleton<LLToolIndividual>
{
-public:
- LLToolIndividual();
+ LLSINGLETON(LLToolIndividual);
virtual ~LLToolIndividual();
+public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
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/lltoolmgr.h b/indra/newview/lltoolmgr.h
index e5b45750d9..28465d5d2c 100644
--- a/indra/newview/lltoolmgr.h
+++ b/indra/newview/lltoolmgr.h
@@ -42,9 +42,9 @@ const MASK MASK_COPY = MASK_SHIFT;
class LLToolMgr : public LLSingleton<LLToolMgr>
{
-public:
- LLToolMgr();
+ LLSINGLETON(LLToolMgr);
~LLToolMgr();
+public:
// Must be called after gSavedSettings set up.
void initTools();
diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h
index 0c37be1f92..5ad9b67e21 100644
--- a/indra/newview/lltoolobjpicker.h
+++ b/indra/newview/lltoolobjpicker.h
@@ -35,8 +35,8 @@ class LLPickInfo;
class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker>
{
+ LLSINGLETON(LLToolObjPicker);
public:
- LLToolObjPicker();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 6391e675c5..95d155a474 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -37,9 +37,9 @@ class LLObjectSelection;
class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
{
+ LLSINGLETON(LLToolPie);
LOG_CLASS(LLToolPie);
public:
- LLToolPie( );
// Virtual functions inherited from LLMouseHandler
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 8a83bf31af..7575d8ad18 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -43,10 +43,10 @@ class LLPickInfo;
class LLToolPipette
: public LLTool, public LLSingleton<LLToolPipette>
{
-public:
- LLToolPipette();
+ LLSINGLETON(LLToolPipette);
virtual ~LLToolPipette();
+public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h
index b368a4b153..b5ba72f16d 100644
--- a/indra/newview/lltoolselectland.h
+++ b/indra/newview/lltoolselectland.h
@@ -35,10 +35,10 @@ class LLParcelSelection;
class LLToolSelectLand
: public LLTool, public LLSingleton<LLToolSelectLand>
{
-public:
- LLToolSelectLand( );
+ LLSINGLETON(LLToolSelectLand);
virtual ~LLToolSelectLand();
+public:
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h
index b4611c8c87..d126543f15 100644
--- a/indra/newview/lltransientfloatermgr.h
+++ b/indra/newview/lltransientfloatermgr.h
@@ -38,9 +38,7 @@ class LLTransientFloater;
*/
class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
{
-protected:
- LLTransientFloaterMgr();
- friend class LLSingleton<LLTransientFloaterMgr>;
+ LLSINGLETON(LLTransientFloaterMgr);
public:
enum ETransientGroup
diff --git a/indra/newview/lltwitterconnect.h b/indra/newview/lltwitterconnect.h
index be481a17c1..e77048cc35 100644
--- a/indra/newview/lltwitterconnect.h
+++ b/indra/newview/lltwitterconnect.h
@@ -43,6 +43,7 @@ class LLEventPump;
*/
class LLTwitterConnect : public LLSingleton<LLTwitterConnect>
{
+ LLSINGLETON(LLTwitterConnect);
LOG_CLASS(LLTwitterConnect);
public:
enum EConnectionState
@@ -81,10 +82,7 @@ public:
void openTwitterWeb(std::string url);
private:
- friend class LLSingleton<LLTwitterConnect>;
- LLTwitterConnect();
- ~LLTwitterConnect() {};
std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);
EConnectionState mConnectionState;
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/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index 08ba5a5f25..ad0c1734f9 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -48,8 +48,7 @@ struct ViewerAssetEntry : public LLDictionaryEntry
class LLViewerAssetDictionary : public LLSingleton<LLViewerAssetDictionary>,
public LLDictionary<LLViewerAssetType::EType, ViewerAssetEntry>
{
-public:
- LLViewerAssetDictionary();
+ LLSINGLETON(LLViewerAssetDictionary);
};
LLViewerAssetDictionary::LLViewerAssetDictionary()
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 94f1b09fa9..4271b20ad6 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -174,7 +174,7 @@ S32 LLResourceUploadInfo::getEconomyUploadCost()
getAssetType() == LLAssetType::AT_ANIMATION ||
getAssetType() == LLAssetType::AT_MESH)
{
- return LLGlobalEconomy::Singleton::instance().getPriceUpload();
+ return LLGlobalEconomy::instance().getPriceUpload();
}
return 0;
diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h
index 8c302c6549..16f9b63113 100644
--- a/indra/newview/llvieweraudio.h
+++ b/indra/newview/llvieweraudio.h
@@ -43,6 +43,9 @@ void audio_update_wind(bool force_update = true);
class LLViewerAudio : public LLSingleton<LLViewerAudio>
{
+ LLSINGLETON(LLViewerAudio);
+ virtual ~LLViewerAudio();
+
public:
enum EFadeState
@@ -52,9 +55,6 @@ public:
FADE_OUT,
};
- LLViewerAudio();
- virtual ~LLViewerAudio();
-
void startInternetStreamWithAutoFade(std::string streamURI);
void stopInternetStreamWithAutoFade();
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 57a0195d23..778e275727 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -113,6 +113,7 @@ LLViewerCamera::LLViewerCamera() : LLCamera()
{
calcProjection(getFar());
mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
+ mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
mPixelMeterRatio = 0.f;
mScreenPixelArea = 0;
@@ -882,6 +883,15 @@ void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
}
+BOOL LLViewerCamera::isDefaultFOVChanged()
+{
+ if(mPrevCameraFOVDefault != mCameraFOVDefault)
+ {
+ mPrevCameraFOVDefault = mCameraFOVDefault;
+ return !gSavedSettings.getBOOL("IgnoreFOVZoomForLODs");
+ }
+ return FALSE;
+}
// static
void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value)
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 7b2887d725..5901de289f 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -54,6 +54,7 @@ extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInst
LL_ALIGN_PREFIX(16)
class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera>
{
+ LLSINGLETON(LLViewerCamera);
public:
void* operator new(size_t size)
{
@@ -82,8 +83,6 @@ public:
static eCameraID sCurCameraID;
- LLViewerCamera();
-
void updateCameraLocation(const LLVector3 &center,
const LLVector3 &up_direction,
const LLVector3 &point_of_interest);
@@ -116,6 +115,8 @@ public:
void setDefaultFOV(F32 fov) ;
F32 getDefaultFOV() { return mCameraFOVDefault; }
+ BOOL isDefaultFOVChanged();
+
BOOL cameraUnderWater() const;
BOOL areVertsVisible(LLViewerObject* volumep, BOOL all_verts);
@@ -139,6 +140,7 @@ protected:
mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix
mutable LLMatrix4 mModelviewMatrix;
F32 mCameraFOVDefault;
+ F32 mPrevCameraFOVDefault;
F32 mCosHalfCameraFOV;
LLVector3 mLastPointOfInterest;
F32 mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance.
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index eb0a8d5a40..ec7a81584a 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -92,6 +92,7 @@
#include "llfloaternotificationstabbed.h"
#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
+#include "llfloateroutfitphotopreview.h"
#include "llfloateroutfitsnapshot.h"
#include "llfloaterpathfindingcharacters.h"
#include "llfloaterpathfindingconsole.h"
@@ -276,6 +277,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
+ LLFloaterReg::add("outfit_photo_preview", "floater_outfit_photo_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitPhotoPreview>);
LLFloaterPayUtil::registerFloater();
LLFloaterReg::add("pathfinding_characters", "floater_pathfinding_characters.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingCharacters>);
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index b8ff2cc9b4..9cb2e0336a 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -103,8 +103,7 @@ struct ViewerFolderEntry : public LLDictionaryEntry
class LLViewerFolderDictionary : public LLSingleton<LLViewerFolderDictionary>,
public LLDictionary<LLFolderType::EType, ViewerFolderEntry>
{
-public:
- LLViewerFolderDictionary();
+ LLSINGLETON(LLViewerFolderDictionary);
protected:
bool initEnsemblesFromFile(); // Reads in ensemble information from foldertypes.xml
};
diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h
index a983012e2e..da50e07a43 100644
--- a/indra/newview/llviewerhelp.h
+++ b/indra/newview/llviewerhelp.h
@@ -39,7 +39,7 @@ class LLUICtrl;
class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp>
{
- friend class LLSingleton<LLViewerHelp>;
+ LLSINGLETON_EMPTY_CTOR(LLViewerHelp);
public:
/// display the specified help topic in the help viewer
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 98d1e80df8..caffeadb73 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -93,107 +93,10 @@ void doInventoryCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
///----------------------------------------------------------------------------
class LLLocalizedInventoryItemsDictionary : public LLSingleton<LLLocalizedInventoryItemsDictionary>
{
+ LLSINGLETON(LLLocalizedInventoryItemsDictionary);
public:
std::map<std::string, std::string> mInventoryItemsDict;
- LLLocalizedInventoryItemsDictionary()
- {
- mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape");
- mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin");
- mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair");
- mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes");
- mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt");
- mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants");
- mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes");
- mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks");
- mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket");
- mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves");
- mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt");
- mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants");
- mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt");
- mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha");
- mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo");
- mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics");
- mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
-
- mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
- mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
- mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
- mInventoryItemsDict["New Note"] = LLTrans::getString("New Note");
- mInventoryItemsDict["Contents"] = LLTrans::getString("Contents");
-
- mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture");
- mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures");
- mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures");
- mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures");
- mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures");
- mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures");
-
- //predefined gestures
-
- //male
- mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me");
- mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319
- mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss");
- mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo");
- mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored");
- mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey");
- mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh");
- mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed");
- mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug");
- mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out");
- mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow");
-
- //female
- mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle");
- mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry");
- mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed");
- mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me");
- mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319
- mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss");
- mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo");
- mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored");
- mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey");
- mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby");
- mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh");
- mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good");
- mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here");
- mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please");
- mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed");
- mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug");
- mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out");
- mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow");
-
- //common
- mInventoryItemsDict["/bow"] = LLTrans::getString("/bow");
- mInventoryItemsDict["/clap"] = LLTrans::getString("/clap");
- mInventoryItemsDict["/count"] = LLTrans::getString("/count");
- mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish");
- mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb");
- mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle");
- mInventoryItemsDict["/no"] = LLTrans::getString("/no");
- mInventoryItemsDict["/no!"] = LLTrans::getString("/no!");
- mInventoryItemsDict["/paper"] = LLTrans::getString("/paper");
- mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme");
- mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou");
- mInventoryItemsDict["/rock"] = LLTrans::getString("/rock");
- mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor");
- mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke");
- mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch");
- mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle");
- mInventoryItemsDict["/yes"] = LLTrans::getString("/yes");
- mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!");
- mInventoryItemsDict["afk"] = LLTrans::getString("afk");
- mInventoryItemsDict["dance1"] = LLTrans::getString("dance1");
- mInventoryItemsDict["dance2"] = LLTrans::getString("dance2");
- mInventoryItemsDict["dance3"] = LLTrans::getString("dance3");
- mInventoryItemsDict["dance4"] = LLTrans::getString("dance4");
- mInventoryItemsDict["dance5"] = LLTrans::getString("dance5");
- mInventoryItemsDict["dance6"] = LLTrans::getString("dance6");
- mInventoryItemsDict["dance7"] = LLTrans::getString("dance7");
- mInventoryItemsDict["dance8"] = LLTrans::getString("dance8");
- }
-
/**
* Finds passed name in dictionary and replaces it with found localized value.
*
@@ -216,6 +119,103 @@ public:
}
};
+LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary()
+{
+ mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape");
+ mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin");
+ mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair");
+ mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes");
+ mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt");
+ mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants");
+ mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes");
+ mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks");
+ mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket");
+ mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves");
+ mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt");
+ mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants");
+ mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt");
+ mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha");
+ mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo");
+ mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics");
+ mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
+
+ mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
+ mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
+ mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
+ mInventoryItemsDict["New Note"] = LLTrans::getString("New Note");
+ mInventoryItemsDict["Contents"] = LLTrans::getString("Contents");
+
+ mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture");
+ mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures");
+ mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures");
+ mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures");
+ mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures");
+ mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures");
+
+ //predefined gestures
+
+ //male
+ mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me");
+ mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319
+ mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss");
+ mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo");
+ mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored");
+ mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey");
+ mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh");
+ mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed");
+ mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug");
+ mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out");
+ mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow");
+
+ //female
+ mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle");
+ mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry");
+ mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed");
+ mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me");
+ mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319
+ mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss");
+ mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo");
+ mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored");
+ mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey");
+ mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby");
+ mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh");
+ mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good");
+ mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here");
+ mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please");
+ mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed");
+ mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug");
+ mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out");
+ mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow");
+
+ //common
+ mInventoryItemsDict["/bow"] = LLTrans::getString("/bow");
+ mInventoryItemsDict["/clap"] = LLTrans::getString("/clap");
+ mInventoryItemsDict["/count"] = LLTrans::getString("/count");
+ mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish");
+ mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb");
+ mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle");
+ mInventoryItemsDict["/no"] = LLTrans::getString("/no");
+ mInventoryItemsDict["/no!"] = LLTrans::getString("/no!");
+ mInventoryItemsDict["/paper"] = LLTrans::getString("/paper");
+ mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme");
+ mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou");
+ mInventoryItemsDict["/rock"] = LLTrans::getString("/rock");
+ mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor");
+ mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke");
+ mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch");
+ mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle");
+ mInventoryItemsDict["/yes"] = LLTrans::getString("/yes");
+ mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!");
+ mInventoryItemsDict["afk"] = LLTrans::getString("afk");
+ mInventoryItemsDict["dance1"] = LLTrans::getString("dance1");
+ mInventoryItemsDict["dance2"] = LLTrans::getString("dance2");
+ mInventoryItemsDict["dance3"] = LLTrans::getString("dance3");
+ mInventoryItemsDict["dance4"] = LLTrans::getString("dance4");
+ mInventoryItemsDict["dance5"] = LLTrans::getString("dance5");
+ mInventoryItemsDict["dance6"] = LLTrans::getString("dance6");
+ mInventoryItemsDict["dance7"] = LLTrans::getString("dance7");
+ mInventoryItemsDict["dance8"] = LLTrans::getString("dance8");
+}
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -1006,6 +1006,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())
@@ -1013,13 +1029,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();
}
@@ -1035,13 +1047,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();
@@ -1060,13 +1067,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();
}
@@ -1300,12 +1302,18 @@ void update_inventory_item(
if (updates.has("asset_id"))
{
updates.erase("asset_id");
- updates["hash_id"] = update_item->getTransactionID();
+ if (update_item->getTransactionID().notNull())
+ {
+ updates["hash_id"] = update_item->getTransactionID();
+ }
}
if (updates.has("shadow_id"))
{
updates.erase("shadow_id");
- updates["hash_id"] = update_item->getTransactionID();
+ if (update_item->getTransactionID().notNull())
+ {
+ updates["hash_id"] = update_item->getTransactionID();
+ }
}
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::UpdateItem(item_id, updates, cr);
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 5194679a0c..074d51b8b3 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -30,7 +30,7 @@
#include "llinventory.h"
#include "llframetimer.h"
#include "llwearable.h"
-#include "llui.h" //for LLDestroyClass
+#include "llinitdestroyclass.h" //for LLDestroyClass
#include <boost/signals2.hpp> // boost::signals2::trackable
diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h
index 80c758a5af..016b435ee8 100644
--- a/indra/newview/llviewerjoystick.h
+++ b/indra/newview/llviewerjoystick.h
@@ -45,10 +45,10 @@ typedef enum e_joystick_driver_state
class LLViewerJoystick : public LLSingleton<LLViewerJoystick>
{
-public:
- LLViewerJoystick();
+ LLSINGLETON(LLViewerJoystick);
virtual ~LLViewerJoystick();
-
+
+public:
void init(bool autoenable);
void terminate();
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index 2186ed3c52..fd4315a319 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -57,6 +57,7 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
struct LLKeyboardActionRegistry
: public LLRegistrySingleton<std::string, boost::function<void (EKeystate keystate)>, LLKeyboardActionRegistry>
{
+ LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
};
LLViewerKeyboard gViewerKeyboard;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 6ed063e066..43b4102bca 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -167,6 +167,7 @@ static bool sForceUpdate = false;
static LLUUID sOnlyAudibleTextureID = LLUUID::null;
static F64 sLowestLoadableImplInterest = 0.0f;
static bool sAnyMediaShowing = false;
+static bool sAnyMediaPlaying = false;
static boost::signals2::connection sTeleportFinishConnection;
static std::string sUpdatedCookies;
static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt";
@@ -606,6 +607,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
createSpareBrowserMediaSource();
sAnyMediaShowing = false;
+ sAnyMediaPlaying = false;
sUpdatedCookies = getCookieStore()->getChangedCookies();
if(!sUpdatedCookies.empty())
{
@@ -808,6 +810,11 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
sAnyMediaShowing = true;
}
+ if (!pimpl->getUsedInUI() && pimpl->hasMedia() && (!pimpl->isMediaPaused() || !pimpl->isMediaTimeBased()))
+ {
+ sAnyMediaPlaying = true;
+ }
+
}
}
@@ -858,6 +865,13 @@ bool LLViewerMedia::isAnyMediaShowing()
//////////////////////////////////////////////////////////////////////////////////////////
// static
+bool LLViewerMedia::isAnyMediaPlaying()
+{
+ return sAnyMediaPlaying;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
void LLViewerMedia::setAllMediaEnabled(bool val)
{
// Set "tentative" autoplay first. We need to do this here or else
@@ -913,6 +927,78 @@ void LLViewerMedia::setAllMediaEnabled(bool val)
//////////////////////////////////////////////////////////////////////////////////////////
// static
+void LLViewerMedia::setAllMediaPaused(bool val)
+{
+ // Set "tentative" autoplay first. We need to do this here or else
+ // re-enabling won't start up the media below.
+ gSavedSettings.setBOOL("MediaTentativeAutoPlay", val);
+
+ // Then
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if (!pimpl->getUsedInUI())
+ {
+ // upause/pause time based media, enable/disable any other
+ if (!val)
+ {
+ pimpl->setDisabled(val);
+ if (pimpl->isMediaTimeBased() && pimpl->isMediaPaused())
+ {
+ pimpl->play();
+ return;
+ }
+ }
+ else if (pimpl->isMediaTimeBased() && pimpl->mMediaSource)
+ {
+ pimpl->pause();
+ }
+ else
+ {
+ pimpl->setDisabled(val);
+ }
+ }
+ }
+
+ // Also do Parcel Media and Parcel Audio
+ if (!val)
+ {
+ if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
+ {
+ LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+ }
+
+ if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
+ !LLViewerMedia::isParcelAudioPlaying() &&
+ gAudiop &&
+ LLViewerMedia::hasParcelAudio())
+ {
+ if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying())
+ {
+ // 'false' means unpause
+ gAudiop->pauseInternetStream(false);
+ }
+ else
+ {
+ LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLViewerMedia::getParcelAudioURL());
+ }
+ }
+ }
+ else {
+ // This actually unloads the impl, as opposed to "stop"ping the media
+ LLViewerParcelMedia::stop();
+ if (gAudiop)
+ {
+ LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
bool LLViewerMedia::isParcelMediaPlaying()
{
return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia());
@@ -1490,7 +1576,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 +1848,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 +1865,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 +1914,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 +1971,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 +1994,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..5c876861c4 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -105,9 +105,12 @@ public:
// Is any media currently "showing"? Includes Parcel Media. Does not include media in the UI.
static bool isAnyMediaShowing();
+ static bool isAnyMediaPlaying();
// Set all media enabled or disabled, depending on val. Does not include media in the UI.
static void setAllMediaEnabled(bool val);
-
+ // Set all media paused or playing, depending on val. Does not include media in the UI.
+ static void setAllMediaPaused(bool val);
+
static void updateMedia(void* dummy_arg = NULL);
static void initClass();
@@ -299,7 +302,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/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index 0b2a64868e..368c671f84 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -41,10 +41,10 @@ class LLViewerMediaFocus :
public LLFocusableElement,
public LLSingleton<LLViewerMediaFocus>
{
-public:
- LLViewerMediaFocus();
+ LLSINGLETON(LLViewerMediaFocus);
~LLViewerMediaFocus();
-
+
+public:
// Set/clear the face that has media focus (takes keyboard input and has the full set of controls)
void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
void clearFocus();
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 20e1fce2d9..74e1b865d8 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -133,6 +133,7 @@
#include "llpathfindingmanager.h"
#include "llstartup.h"
#include "boost/unordered_map.hpp"
+#include "llcleanup.h"
using namespace LLAvatarAppearanceDefines;
@@ -397,13 +398,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);
@@ -8482,7 +8485,7 @@ class LLWorldPostProcess : public view_listener_t
void handle_flush_name_caches()
{
- LLAvatarNameCache::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLAvatarNameCache);
if (gCacheName) gCacheName->clear();
}
@@ -8526,7 +8529,7 @@ class LLToggleUIHints : public view_listener_t
void LLUploadCostCalculator::calculateCost()
{
- S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
// getPriceUpload() returns -1 if no data available yet.
if(upload_cost >= 0)
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 54b12cae12..d46bb0199b 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -84,7 +84,7 @@ class LLFileEnableUpload : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
return true;
-// bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
+// bool new_value = gStatusBar && LLGlobalEconomy::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::getInstance()->getPriceUpload());
// return new_value;
}
};
@@ -93,6 +93,12 @@ class LLFileEnableUploadModel : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
+ LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::findInstance("upload_model");
+ if (fmp && fmp->isModelLoading())
+ {
+ return false;
+ }
+
return true;
}
};
@@ -359,7 +365,7 @@ class LLFileUploadModel : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::getInstance("upload_model");
- if (fmp)
+ if (fmp && !fmp->isModelLoading())
{
fmp->loadModel(3);
}
@@ -423,7 +429,7 @@ class LLFileUploadBulk : public view_listener_t
if (picker.getMultipleOpenFiles())
{
std::string filename = picker.getFirstFile();
- S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
while (!filename.empty())
{
@@ -508,8 +514,8 @@ class LLFileEnableCloseAllWindows : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::getInstance();
- LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::getInstance();
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
+ 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;
@@ -523,10 +529,10 @@ class LLFileCloseAllWindows : public view_listener_t
{
bool app_quitting = false;
gFloaterView->closeAllChildren(app_quitting);
- LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::getInstance();
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
if (floater_snapshot)
floater_snapshot->closeFloater(app_quitting);
- LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::getInstance();
+ LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance();
if (floater_outfit_snapshot)
floater_outfit_snapshot->closeFloater(app_quitting);
if (gMenuHolder) gMenuHolder->hideMenus();
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 92df3866f7..d81cb804e4 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;
}
@@ -5463,9 +5467,12 @@ static std::string reason_from_transaction_type(S32 transaction_type,
case TRANS_CLASSIFIED_CHARGE:
return LLTrans::getString("to publish a classified ad");
+ case TRANS_GIFT:
+ // Simulator returns "Payment" if no custom description has been entered
+ return (item_desc == "Payment" ? std::string() : item_desc);
+
// These have no reason to display, but are expected and should not
// generate warnings
- case TRANS_GIFT:
case TRANS_PAY_OBJECT:
case TRANS_OBJECT_PAYS:
return std::string();
@@ -5575,6 +5582,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
LLSD payload;
bool you_paid_someone = (source_id == gAgentID);
+ std::string gift_suffix = (transaction_type == TRANS_GIFT ? "_gift" : "");
if (you_paid_someone)
{
if(!gSavedSettings.getBOOL("NotifyMoneySpend"))
@@ -5588,8 +5596,8 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
{
if (dest_id.notNull())
{
- message = success ? LLTrans::getString("you_paid_ldollars", args) :
- LLTrans::getString("you_paid_failure_ldollars", args);
+ message = success ? LLTrans::getString("you_paid_ldollars" + gift_suffix, args) :
+ LLTrans::getString("you_paid_failure_ldollars" + gift_suffix, args);
}
else
{
@@ -5616,7 +5624,8 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
payload["dest_id"] = dest_id;
notification = success ? "PaymentSent" : "PaymentFailure";
}
- else {
+ else
+ {
// ...someone paid you
if(!gSavedSettings.getBOOL("NotifyMoneyReceived"))
{
@@ -5627,9 +5636,10 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
name_id = source_id;
if (!reason.empty())
{
- message = LLTrans::getString("paid_you_ldollars", args);
+ message = LLTrans::getString("paid_you_ldollars" + gift_suffix, args);
}
- else {
+ else
+ {
message = LLTrans::getString("paid_you_ldollars_no_reason", args);
}
final_args["MESSAGE"] = message;
@@ -6274,9 +6284,9 @@ void process_frozen_message(LLMessageSystem *msgsystem, void **user_data)
// do some extra stuff once we get our economy data
void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)
{
- LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::Singleton::getInstance());
+ LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::getInstance());
- S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL;
@@ -6381,6 +6391,16 @@ bool unknown_script_question_cb(const LLSD& notification, const LLSD& response)
return false;
}
+void experiencePermissionBlock(LLUUID experience, LLSD result)
+{
+ LLSD permission;
+ LLSD data;
+ permission["permission"] = "Block";
+ data[experience.asString()] = permission;
+ data["experience"] = experience;
+ LLEventPumps::instance().obtain("experience_permission").post(data);
+}
+
bool script_question_cb(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -6457,14 +6477,8 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
if (!region)
return false;
- LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), LLExperienceCache::ExperienceGetFn_t());
+ LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), boost::bind(&experiencePermissionBlock, experience, _1));
- LLSD permission;
- LLSD data;
- permission["permission"] = "Block";
- data[experience.asString()] = permission;
- data["experience"] = experience;
- LLEventPumps::instance().obtain("experience_permission").post(data);
}
}
return false;
@@ -6601,6 +6615,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/llviewermessage.h b/indra/newview/llviewermessage.h
index d8f5c71f8d..b0eaa37541 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -210,6 +210,7 @@ void set_dad_inbox_object(const LLUUID& object_id);
class LLViewerMessage : public LLSingleton<LLViewerMessage>
{
+ LLSINGLETON_EMPTY_CTOR(LLViewerMessage);
public:
typedef boost::function<void()> teleport_started_callback_t;
typedef boost::signals2::signal<void()> teleport_started_signal_t;
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 6666aecca2..6937d064f9 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";
@@ -91,13 +95,6 @@ LLGridManager::LLGridManager()
}
-LLGridManager::LLGridManager(const std::string& grid_file)
-{
- // initialize with an explicity grid file for testing.
- LL_DEBUGS("GridManager")<<LL_ENDL;
- initialize(grid_file);
-}
-
//
// LLGridManager - class for managing the list of known grids, and the current
// selection
@@ -125,6 +122,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 +130,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 +287,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 +305,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 +343,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 +354,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 +541,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..b8ff494b8b 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -58,16 +58,15 @@ protected:
**/
class LLGridManager : public LLSingleton<LLGridManager>
{
+ /// Instantiate the grid manager, load default grids, selects the default grid
+ LLSINGLETON(LLGridManager);
+ ~LLGridManager();
+
public:
/* ================================================================
* @name Initialization and Configuration
* @{
*/
- /// Instantiate the grid manager, load default grids, selects the default grid
- LLGridManager(const std::string& grid_file);
- LLGridManager();
- ~LLGridManager();
-
/// add grids from an external grids file
void initialize(const std::string& grid_file);
@@ -166,6 +165,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 +222,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..61dd71ab75 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -102,6 +102,7 @@
#include "llmediaentry.h"
#include "llfloaterperms.h"
#include "llvocache.h"
+#include "llcleanup.h"
//#define DEBUG_UPDATE_TYPE
@@ -244,9 +245,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),
@@ -529,11 +531,11 @@ void LLViewerObject::initVOClasses()
void LLViewerObject::cleanupVOClasses()
{
- LLVOGrass::cleanupClass();
- LLVOWater::cleanupClass();
- LLVOTree::cleanupClass();
- LLVOAvatar::cleanupClass();
- LLVOVolume::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLVOGrass);
+ SUBSYSTEM_CLEANUP(LLVOWater);
+ SUBSYSTEM_CLEANUP(LLVOTree);
+ SUBSYSTEM_CLEANUP(LLVOAvatar);
+ SUBSYSTEM_CLEANUP(LLVOVolume);
sObjectDataMap.clear();
}
@@ -1434,10 +1436,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 +1818,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 +2842,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 +2885,7 @@ void LLViewerObject::requestInventory()
void LLViewerObject::fetchInventoryFromServer()
{
- if (!mInventoryPending)
+ if (!isInventoryPending())
{
delete mInventory;
LLMessageSystem* msg = gMessageSystem;
@@ -2883,7 +2898,7 @@ void LLViewerObject::fetchInventoryFromServer()
msg->sendReliable(mRegionp->getHost());
// this will get reset by dirtyInventory or doInventoryCallback
- mInventoryPending = TRUE;
+ mInvRequestState = INVENTORY_REQUEST_PENDING;
}
}
@@ -2944,7 +2959,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 +2981,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 +3128,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 +5022,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 +6321,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/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index bb6bbf3308..29219843c9 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -75,6 +75,8 @@ public:
class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
{
+ LLSINGLETON(LLViewerParcelMgr);
+ ~LLViewerParcelMgr();
public:
typedef boost::function<void (const LLVector3d&, const bool& local)> teleport_finished_callback_t;
@@ -82,9 +84,6 @@ public:
typedef boost::function<void()> teleport_failed_callback_t;
typedef boost::signals2::signal<void()> teleport_failed_signal_t;
- LLViewerParcelMgr();
- ~LLViewerParcelMgr();
-
static void cleanupGlobals();
BOOL selectionEmpty() const;
diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h
index 40e8e1d45d..ab1cd715ab 100644
--- a/indra/newview/llviewerpartsim.h
+++ b/indra/newview/llviewerpartsim.h
@@ -135,9 +135,8 @@ protected:
class LLViewerPartSim : public LLSingleton<LLViewerPartSim>
{
+ LLSINGLETON(LLViewerPartSim);
public:
- LLViewerPartSim();
- virtual ~LLViewerPartSim(){}
void destroyClass();
typedef std::vector<LLViewerPartGroup *> group_list_t;
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 7843652589..97a060d95e 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -246,13 +246,11 @@ extern LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT
class LLViewerStats : public LLSingleton<LLViewerStats>
{
-public:
- void resetStats();
+ LLSINGLETON(LLViewerStats);
+ ~LLViewerStats();
public:
-
- LLViewerStats();
- ~LLViewerStats();
+ void resetStats();
void updateFrameStats(const F64Seconds time_diff);
diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h
index d1744f4910..c974bea49d 100644
--- a/indra/newview/llviewerstatsrecorder.h
+++ b/indra/newview/llviewerstatsrecorder.h
@@ -44,11 +44,11 @@ class LLViewerObject;
class LLViewerStatsRecorder : public LLSingleton<LLViewerStatsRecorder>
{
- public:
- LOG_CLASS(LLViewerStatsRecorder);
- LLViewerStatsRecorder();
+ LLSINGLETON(LLViewerStatsRecorder);
+ LOG_CLASS(LLViewerStatsRecorder);
~LLViewerStatsRecorder();
+ public:
void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size)
{
#if LL_RECORD_VIEWER_STATS
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/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index ba76770838..070544063a 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -237,6 +237,7 @@ private:
class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIImageList>
{
+ LLSINGLETON_EMPTY_CTOR(LLUIImageList);
public:
// LLImageProviderInterface
/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority);
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 cd9ab3e672..cce988c2fe 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -208,6 +208,7 @@
#include "llwindowlistener.h"
#include "llviewerwindowlistener.h"
#include "llpaneltopinfobar.h"
+#include "llcleanup.h"
#if LL_WINDOWS
#include <tchar.h> // For Unicode conversion methods
@@ -251,6 +252,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;
@@ -287,13 +293,8 @@ public:
class RecordToChatConsole : public LLSingleton<RecordToChatConsole>
{
+ LLSINGLETON(RecordToChatConsole);
public:
- RecordToChatConsole()
- : LLSingleton<RecordToChatConsole>(),
- mRecorder(new RecordToChatConsoleRecorder())
- {
- }
-
void startRecorder() { LLError::addRecorder(mRecorder); }
void stopRecorder() { LLError::removeRecorder(mRecorder); }
@@ -301,6 +302,11 @@ private:
LLError::RecorderPtr mRecorder;
};
+RecordToChatConsole::RecordToChatConsole():
+ mRecorder(new RecordToChatConsoleRecorder())
+{
+}
+
////////////////////////////////////////////////////////////////////////////
//
// LLDebugText
@@ -1593,6 +1599,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 +1675,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 +1764,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 +1874,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);
@@ -2119,10 +2177,7 @@ void LLViewerWindow::shutdownViews()
// destroy the nav bar, not currently part of gViewerWindow
// *TODO: Make LLNavigationBar part of gViewerWindow
- if (LLNavigationBar::instanceExists())
- {
- delete LLNavigationBar::getInstance();
- }
+ LLNavigationBar::deleteSingleton();
LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ;
// destroy menus after instantiating navbar above, as it needs
@@ -2158,7 +2213,7 @@ void LLViewerWindow::shutdownGL()
// Shutdown GL cleanly. Order is very important here.
//--------------------------------------------------------
LLFontGL::destroyDefaultFonts();
- LLFontManager::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLFontManager);
stop_glerror();
gSky.cleanup();
@@ -2181,7 +2236,7 @@ void LLViewerWindow::shutdownGL()
LLWorldMapView::cleanupTextures();
LLViewerTextureManager::cleanup() ;
- LLImageGL::cleanupClass() ;
+ SUBSYSTEM_CLEANUP(LLImageGL) ;
LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ;
@@ -2194,7 +2249,7 @@ void LLViewerWindow::shutdownGL()
gGL.shutdown();
- LLVertexBuffer::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLVertexBuffer);
LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ;
}
@@ -5211,7 +5266,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 +5279,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 cdf5b686a7..72b7370621 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -156,7 +156,8 @@ public:
min_width,
min_height;
Optional<bool> fullscreen,
- ignore_pixel_depth;
+ ignore_pixel_depth,
+ first_run;
Params();
};
@@ -210,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);
@@ -415,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);
@@ -428,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;
@@ -506,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/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/llvocache.h b/indra/newview/llvocache.h
index 082f5f0b1d..7aabde1b2d 100644
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -223,6 +223,9 @@ private:
//
class LLVOCache : public LLSingleton<LLVOCache>
{
+ LLSINGLETON(LLVOCache);
+ ~LLVOCache() ;
+
private:
struct HeaderEntryInfo
{
@@ -253,13 +256,8 @@ private:
};
typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;
typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t;
-private:
- friend class LLSingleton<LLVOCache>;
- LLVOCache() ;
public:
- ~LLVOCache() ;
-
void initCache(ELLPath location, U32 size, U32 cache_version) ;
void removeCache(ELLPath location, bool started = false) ;
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index ef15b2c79e..309c3eebdd 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -167,8 +167,8 @@ private:
class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
{
+ LLSINGLETON(LLVoiceChannelProximal);
public:
- LLVoiceChannelProximal();
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
/*virtual*/ void handleStatusChange(EStatusType status);
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index b05bcb23b7..32637dcf42 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -299,11 +299,11 @@ public:
class LLVoiceClient: public LLSingleton<LLVoiceClient>
{
+ LLSINGLETON(LLVoiceClient);
LOG_CLASS(LLVoiceClient);
-public:
- LLVoiceClient();
~LLVoiceClient();
+public:
typedef boost::signals2::signal<void(void)> micro_changed_signal_t;
micro_changed_signal_t mMicroChangedSignal;
@@ -485,6 +485,8 @@ protected:
**/
class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>
{
+ LLSINGLETON(LLSpeakerVolumeStorage);
+ ~LLSpeakerVolumeStorage();
LOG_CLASS(LLSpeakerVolumeStorage);
public:
@@ -513,10 +515,6 @@ public:
void removeSpeakerVolume(const LLUUID& speaker_id);
private:
- friend class LLSingleton<LLSpeakerVolumeStorage>;
- LLSpeakerVolumeStorage();
- ~LLSpeakerVolumeStorage();
-
const static std::string SETTINGS_FILE_NAME;
void load();
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index f32c7c975f..81e924e438 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -56,12 +56,11 @@ class LLVivoxVoiceClient : public LLSingleton<LLVivoxVoiceClient>,
virtual public LLVoiceModuleInterface,
virtual public LLVoiceEffectInterface
{
+ LLSINGLETON(LLVivoxVoiceClient);
LOG_CLASS(LLVivoxVoiceClient);
-public:
- LLVivoxVoiceClient();
virtual ~LLVivoxVoiceClient();
-
-
+
+public:
/// @name LLVoiceModuleInterface virtual implementations
/// @see LLVoiceModuleInterface
//@{
@@ -1027,10 +1026,10 @@ protected:
class LLVivoxSecurity : public LLSingleton<LLVivoxSecurity>
{
- public:
- LLVivoxSecurity();
- virtual ~LLVivoxSecurity();
+ LLSINGLETON(LLVivoxSecurity);
+ virtual ~LLVivoxSecurity();
+ public:
std::string connectorHandle() { return mConnectorHandle; };
std::string accountHandle() { return mAccountHandle; };
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e69a8d1d1d..6d57526c7d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1213,18 +1213,18 @@ void LLVOVolume::sculpt()
}
}
-S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius)
+S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor)
{
S32 cur_detail;
if (LLPipeline::sDynamicLOD)
{
// We've got LOD in the profile, and in the twist. Use radius.
- F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
+ F32 tan_angle = (lod_factor*radius)/distance;
cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f));
}
else
{
- cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);
+ cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3);
}
return cur_detail;
}
@@ -1240,6 +1240,7 @@ BOOL LLVOVolume::calcLOD()
F32 radius;
F32 distance;
+ F32 lod_factor = LLVOVolume::sLODFactor;
if (mDrawable->isState(LLDrawable::RIGGED))
{
@@ -1275,12 +1276,18 @@ BOOL LLVOVolume::calcLOD()
distance *= rampDist;
}
- // DON'T Compensate for field of view changing on FOV zoom.
+
distance *= F_PI/3.f;
- cur_detail = computeLODDetail(ll_round(distance, 0.01f),
- ll_round(radius, 0.01f));
+ static LLCachedControl<bool> ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs");
+ if(!ignore_fov_zoom)
+ {
+ lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV();
+ }
+ cur_detail = computeLODDetail(ll_round(distance, 0.01f),
+ ll_round(radius, 0.01f),
+ lod_factor);
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) &&
mDrawable->getFace(0))
@@ -4429,7 +4436,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/llvovolume.h b/indra/newview/llvovolume.h
index a331908320..3b68d61ee9 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -327,7 +327,7 @@ public:
void clearRiggedVolume();
protected:
- S32 computeLODDetail(F32 distance, F32 radius);
+ S32 computeLODDetail(F32 distance, F32 radius, F32 lod_factor);
BOOL calcLOD();
LLFace* addFace(S32 face_index);
void updateTEData();
diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h
index fee3ec6f20..9a6624258e 100644
--- a/indra/newview/llwatchdog.h
+++ b/indra/newview/llwatchdog.h
@@ -75,10 +75,10 @@ private:
class LLWatchdogTimerThread; // Defined in the cpp
class LLWatchdog : public LLSingleton<LLWatchdog>
{
-public:
- LLWatchdog();
+ LLSINGLETON(LLWatchdog);
~LLWatchdog();
+public:
// Add an entry to the watchdog.
void add(LLWatchdogEntry* e);
void remove(LLWatchdogEntry* e);
diff --git a/indra/newview/llwaterparammanager.h b/indra/newview/llwaterparammanager.h
index dc7d41be2a..3f169e439a 100644
--- a/indra/newview/llwaterparammanager.h
+++ b/indra/newview/llwaterparammanager.h
@@ -214,6 +214,8 @@ struct WaterExpFloatControl
/// WindLight parameter manager class - what controls all the wind light shaders
class LLWaterParamManager : public LLSingleton<LLWaterParamManager>
{
+ LLSINGLETON(LLWaterParamManager);
+ ~LLWaterParamManager();
LOG_CLASS(LLWaterParamManager);
public:
typedef std::list<std::string> preset_name_list_t;
@@ -317,11 +319,7 @@ public:
F32 mDensitySliderValue;
private:
- friend class LLSingleton<LLWaterParamManager>;
/*virtual*/ void initSingleton();
- LLWaterParamManager();
- ~LLWaterParamManager();
-
void loadAllPresets();
void loadPresetsFromDir(const std::string& dir);
bool loadPreset(const std::string& path);
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index f8981d0c51..ee2270c323 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -653,24 +653,16 @@ LLWearableItemsList::~LLWearableItemsList()
{}
// virtual
-void LLWearableItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange /*= true*/)
+LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item)
{
- if (!item)
- {
- LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
- llassert(item != NULL);
- }
-
- LLPanelWearableOutfitItem *list_item = LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
- if (!list_item)
- return;
+ if (!item)
+ {
+ LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
+ llassert(item != NULL);
+ return NULL;
+ }
- bool is_item_added = addItem(list_item, item->getUUID(), ADD_BOTTOM, rearrange);
- if (!is_item_added)
- {
- LL_WARNS() << "Couldn't add flat list item." << LL_ENDL;
- llassert(is_item_added);
- }
+ return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
}
void LLWearableItemsList::updateList(const LLUUID& category_id)
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 18a30f083b..f3182ed163 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -411,8 +411,8 @@ public:
*/
class ContextMenu : public LLListContextMenu, public LLSingleton<ContextMenu>
{
+ LLSINGLETON(ContextMenu);
public:
- ContextMenu();
/*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);
protected:
@@ -453,7 +453,7 @@ public:
virtual ~LLWearableItemsList();
- /*virtual*/ void addNewItem(LLViewerInventoryItem* item, bool rearrange = true);
+ /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item);
void updateList(const LLUUID& category_id);
diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h
index d6f0fd09a6..782f7751e5 100644
--- a/indra/newview/llwearablelist.h
+++ b/indra/newview/llwearablelist.h
@@ -41,9 +41,9 @@
*/
class LLWearableList : public LLSingleton<LLWearableList>
{
-public:
- LLWearableList() {}
+ LLSINGLETON_EMPTY_CTOR(LLWearableList);
~LLWearableList();
+public:
void cleanup() ;
S32 getLength() const { return mList.size(); }
diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h
index a3cbf6dc03..90882cf04a 100644
--- a/indra/newview/llwindebug.h
+++ b/indra/newview/llwindebug.h
@@ -34,6 +34,7 @@
class LLWinDebug:
public LLSingleton<LLWinDebug>
{
+ LLSINGLETON_EMPTY_CTOR(LLWinDebug);
public:
static void init();
static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL);
diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h
index e13aed98ed..a10102edf7 100644
--- a/indra/newview/llwlparammanager.h
+++ b/indra/newview/llwlparammanager.h
@@ -213,6 +213,8 @@ public:
/// WindLight parameter manager class - what controls all the wind light shaders
class LLWLParamManager : public LLSingleton<LLWLParamManager>
{
+ LLSINGLETON(LLWLParamManager);
+ ~LLWLParamManager();
LOG_CLASS(LLWLParamManager);
public:
@@ -375,11 +377,7 @@ private:
static std::string getSysDir();
static std::string getUserDir();
- friend class LLSingleton<LLWLParamManager>;
/*virtual*/ void initSingleton();
- LLWLParamManager();
- ~LLWLParamManager();
-
// list of all the parameters, listed by name
std::map<LLWLParamKey, LLWLParamSet> mParamList;
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index b2d8418064..c9ac241d5a 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -61,8 +61,8 @@ class LLVOAvatar;
class LLWorld : public LLSingleton<LLWorld>
{
+ LLSINGLETON(LLWorld);
public:
- LLWorld();
void destroyClass();
LLViewerRegion* addRegion(const U64 &region_handle, const LLHost &host);
diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h
index 1a168e4b4d..5e5caa6a74 100644
--- a/indra/newview/llworldmap.h
+++ b/indra/newview/llworldmap.h
@@ -193,10 +193,10 @@ const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE);
class LLWorldMap : public LLSingleton<LLWorldMap>
{
-public:
- LLWorldMap();
+ LLSINGLETON(LLWorldMap);
~LLWorldMap();
+public:
// Clear all: list of region info, tiles, blocks and items
void reset();
diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h
index ac1ea1607c..65276df068 100644
--- a/indra/newview/llworldmapmessage.h
+++ b/indra/newview/llworldmapmessage.h
@@ -34,13 +34,13 @@ class LLMessageSystem;
class LLWorldMapMessage : public LLSingleton<LLWorldMapMessage>
{
+ LLSINGLETON(LLWorldMapMessage);
+ ~LLWorldMapMessage();
+
public:
typedef boost::function<void(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)>
url_callback_t;
- LLWorldMapMessage();
- ~LLWorldMapMessage();
-
// Process incoming answers to map stuff requests
static void processMapBlockReply(LLMessageSystem*, void**);
static void processMapItemReply(LLMessageSystem*, void**);
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/pipeline.cpp b/indra/newview/pipeline.cpp
index c6bbfb1c8f..32285d2784 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -114,6 +114,7 @@
#include "llpathfindingpathtool.h"
#include "llscenemonitor.h"
#include "llprogressview.h"
+#include "llcleanup.h"
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -3423,6 +3424,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
LLSpatialGroup* last_group = NULL;
+ BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged();
for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
{
LLCullResult::bridge_iterator cur_iter = i;
@@ -3436,7 +3438,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
- stateSort(bridge, camera);
+ stateSort(bridge, camera, fov_changed);
}
if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
@@ -3508,9 +3510,9 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
}
-void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
+void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed)
{
- if (bridge->getSpatialGroup()->changeLOD())
+ if (bridge->getSpatialGroup()->changeLOD() || fov_changed)
{
bool force_update = false;
bridge->updateDistance(camera, force_update);
@@ -7385,7 +7387,7 @@ void LLPipeline::doResetVertexBuffers(bool forced)
}
LLVOPartGroup::destroyGL();
- LLVertexBuffer::cleanupClass();
+ SUBSYSTEM_CLEANUP(LLVertexBuffer);
//delete all name pool caches
LLGLNamePool::cleanupPools();
@@ -11623,7 +11625,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
avatar->setImpostorDim(tdim);
- LLVOAvatar::sUseImpostors = true; // @TODO ???
+ LLVOAvatar::sUseImpostors = (0 != LLVOAvatar::sMaxNonImpostors);
sUseOcclusion = occlusion;
sReflectionRender = FALSE;
sImpostorRender = FALSE;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index bba36351d9..5ddb4e0f01 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -254,7 +254,7 @@ public:
void stateSort(LLCamera& camera, LLCullResult& result);
void stateSort(LLSpatialGroup* group, LLCamera& camera);
- void stateSort(LLSpatialBridge* bridge, LLCamera& camera);
+ void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE);
void stateSort(LLDrawable* drawablep, LLCamera& camera);
void postSort(LLCamera& camera);
void forAllVisibleDrawables(void (*func)(LLDrawable*));
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 670410c3d4..760c294f90 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -150,6 +150,7 @@ with the same filename but different name
<texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" />
<texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" />
<texture name="Command_Profile_Icon" file_name="toolbar_icons/profile.png" preload="true" />
+ <texture name="Command_Report_Abuse_Icon" file_name="toolbar_icons/report_abuse.png" preload="true" />
<texture name="Command_Search_Icon" file_name="toolbar_icons/search.png" preload="true" />
<texture name="Command_Snapshot_Icon" file_name="toolbar_icons/snapshot.png" preload="true" />
<texture name="Command_Speak_Icon" file_name="toolbar_icons/speak.png" preload="true" />
@@ -777,6 +778,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" />
diff --git a/indra/newview/skins/default/textures/toolbar_icons/report_abuse.png b/indra/newview/skins/default/textures/toolbar_icons/report_abuse.png
new file mode 100644
index 0000000000..d5cb6ca259
--- /dev/null
+++ b/indra/newview/skins/default/textures/toolbar_icons/report_abuse.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index 8c0b5748de..779b168ae0 100644
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -25,6 +25,7 @@ Grafik kort: [GRAPHICS_CARD]
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]
</floater.string>
<floater.string name="none">
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/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 810022525a..375c7dc0ee 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -64,6 +64,7 @@ Grafikkarte: [GRAPHICS_CARD]
J2C-Decoderversion: [J2C_VERSION]
Audiotreiberversion: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF-Version: [LLCEFLIB_VERSION]
+LibVLC-Version: [LIBVLC_VERSION]
Voice-Server-Version: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
diff --git a/indra/newview/skins/default/xui/en/floater_avatar.xml b/indra/newview/skins/default/xui/en/floater_avatar.xml
index cd5cca02bd..92c5d8bcbe 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
positioning="cascading"
- ignore_ui_scale="false"
legacy_header_height="225"
can_minimize="true"
can_close="true"
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index 521389d7b3..72a7b5540c 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -43,13 +43,11 @@
name="controls"
width="226">
<panel
- color="Transparent"
follows="all"
height="102"
layout="topleft"
left="8"
name="preset_views_list"
- opaque="true"
top="24"
width="212"
visible="false">
@@ -100,14 +98,11 @@
</panel_camera_item>
</panel>
<panel
- color="Transparent"
follows="all"
height="68"
- item_pad="4"
layout="topleft"
left="8"
name="camera_modes_list"
- opaque="true"
top="24"
width="212"
visible="false">
diff --git a/indra/newview/skins/default/xui/en/floater_destinations.xml b/indra/newview/skins/default/xui/en/floater_destinations.xml
index 94ebaa9cb2..4fe8e3bdd1 100644
--- a/indra/newview/skins/default/xui/en/floater_destinations.xml
+++ b/indra/newview/skins/default/xui/en/floater_destinations.xml
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
positioning="cascading"
- ignore_ui_scale="false"
legacy_header_height="225"
can_minimize="true"
can_close="true"
- user_resize="true"
can_resize="true"
min_height="230"
min_width="350"
diff --git a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
index 8ec6735a01..52084e5f8e 100644
--- a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
positioning="cascading"
- ignore_ui_scale="false"
legacy_header_height="225"
can_minimize="true"
can_close="true"
diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml
index 2ea34fb751..b34d70516a 100644
--- a/indra/newview/skins/default/xui/en/floater_facebook.xml
+++ b/indra/newview/skins/default/xui/en/floater_facebook.xml
@@ -22,8 +22,7 @@
top="7"
height="437"
follows="all"
- halign="center"
- use_highlighting_on_hover="true">
+ halign="center">
<panel
filename="panel_facebook_status.xml"
class="llfacebookstatuspanel"
diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml
index 24de3ddd8d..52ef16c7e8 100644
--- a/indra/newview/skins/default/xui/en/floater_flickr.xml
+++ b/indra/newview/skins/default/xui/en/floater_flickr.xml
@@ -29,8 +29,7 @@
top="7"
height="555"
follows="all"
- halign="center"
- use_highlighting_on_hover="true">
+ halign="center">
<panel
filename="panel_flickr_photo.xml"
class="llflickrphotopanel"
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 28c89868bd..34fa0b0fe9 100644
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -121,7 +121,6 @@
follows="all"
layout="topleft"
name="conversations_list_panel"
- opaque="true"
top_pad="0"
left="5"
right="-1"/>
@@ -144,7 +143,6 @@
follows="all"
layout="topleft"
name="stub_panel"
- opaque="true"
top_pad="0"
left="0"
right="-1">
diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml
index 5e84283ab0..90166232e9 100644
--- a/indra/newview/skins/default/xui/en/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/en/floater_moveview.xml
@@ -155,7 +155,6 @@
layout="topleft"
name="move right btn"
quadrant="right"
- right_delta="4"
scale_image="false"
tool_tip="Walk right (press Shift + Right Arrow or D)"
top_pad="10"
@@ -210,7 +209,6 @@
image_pressed_selected="Movement_Down_On"
image_unselected="Movement_Down_Off"
layout="topleft"
- right_delta="0"
name="move down btn"
scale_image="false"
tool_tip="Fly down (press C)"
diff --git a/indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml b/indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml
new file mode 100644
index 0000000000..bfc1c39e9d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="false"
+ height="325"
+ layout="topleft"
+ name="outfit_photo_preview"
+ help_topic="preview_texture"
+ width="410">
+ <floater.string
+ name="Title">
+ Texture: [NAME]
+ </floater.string>
+ <floater.string
+ name="exceed_limits">
+ Max outfit photo size is [MAX_WIDTH]*[MAX_HEIGHT]. Please select another texture.
+ </floater.string>
+ <floater.string
+ name="photo_confirmation">
+ Set this as Outfit Photo for [OUTFIT]?
+ </floater.string>
+ <text
+ type="string"
+ halign="right"
+ length="1"
+ follows="right|bottom"
+ height="16"
+ layout="topleft"
+ left="110"
+ name="dimensions"
+ top="255"
+ width="200">
+ [WIDTH]px x [HEIGHT]px
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ name="notification"
+ left="25"
+ halign="center"
+ top_pad="5"
+ width="360">
+ </text>
+ <button
+ follows="right|bottom"
+ height="22"
+ label="OK"
+ layout="topleft"
+ name="ok_btn"
+ top_pad="5"
+ right="-115"
+ top_delta="0"
+ width="90" />
+ <button
+ follows="right|bottom"
+ height="22"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-20"
+ top_delta="0"
+ width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 9d91f801a6..3e3f8b49ce 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="186"
+ height="208"
layout="topleft"
name="Give Money"
help_topic="give_money"
@@ -43,6 +43,26 @@
width="180">
Test Name That Is Extremely Long To Check Clipping
</text>
+ <text
+ type="string"
+ follows="top|left"
+ height="18"
+ left="10"
+ name="payment_message_label"
+ top_pad="6"
+ width="120">
+ Description (optional):
+ </text>
+ <line_editor
+ border_style="line"
+ follows="left|top|right"
+ height="19"
+ top_delta="-2"
+ layout="topleft"
+ max_length_bytes="127"
+ name="payment_message"
+ right="-11"
+ width="109" />
<panel
border_thickness="0"
height="104"
@@ -125,7 +145,7 @@
top_pad="0"
max_length_bytes="9"
name="amount"
- width="90" />
+ right="-1" />
<button
enabled="false"
height="23"
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_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index 6021ba0a5a..53618b684b 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -85,8 +85,7 @@
layout="topleft"
left_delta="-12"
name="unknown"
- top_pad="4"
- width="">
+ top_pad="4">
Size: [DIMENSIONS]
</text>
@@ -219,7 +218,6 @@
height="260"
follows="left|top|right|bottom"
column_padding="0"
- can_resize="false"
draw_heading="true"
multi_select="true"
search_column="1"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 3c28233875..91e4c1b603 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1104,7 +1104,6 @@ even though the user gets a free copy.
name="Edit Cost"
label="L$"
label_width="15"
- label_text.valign="center"
valign="center"
width="85"
min_val="0"
diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml
index 3e1a91e58d..5e8dfb8a52 100644
--- a/indra/newview/skins/default/xui/en/floater_twitter.xml
+++ b/indra/newview/skins/default/xui/en/floater_twitter.xml
@@ -20,8 +20,7 @@
tab_position="top"
top="7"
height="457"
- halign="center"
- use_highlighting_on_hover="true">
+ halign="center">
<panel
filename="panel_twitter_photo.xml"
class="lltwitterphotopanel"
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_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
index 06d0b849a3..61cc9dfe77 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
@@ -95,6 +95,9 @@
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="empty_lostnfound" />
+ <on_enable
+ function="Inventory.GearDefault.Enable"
+ parameter="empty_lostnfound" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
@@ -152,5 +155,8 @@
<on_click
function="Inventory.GearDefault.Custom.Action"
parameter="empty_trash" />
+ <on_enable
+ function="Inventory.GearDefault.Enable"
+ parameter="empty_trash" />
</menu_item_call>
</toggleable_menu>
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 c27fac6731..8d8d546b24 100644
--- a/indra/newview/skins/default/xui/en/mime_types.xml
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -130,7 +130,7 @@
movie
</widgettype>
<impl>
- media_plugin_cef
+ media_plugin_libvlc
</impl>
</scheme>
<scheme name="libvlc">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index b2425649a4..db90e6a163 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
@@ -1483,7 +1491,20 @@ Delete Notecard?
notext="Cancel"
yestext="OK"/>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="LoadPreviousReportScreenshot"
+ type="alertmodal">
+ <unique/>
+Do you want to use previous screenshot for your report?
+ <tag>confirm</tag>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="GestureSaveFailedTooManySteps"
@@ -1631,14 +1652,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?
+ 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]
</url>
<usetemplate
ignoretext="My graphics driver is out of date"
@@ -1650,45 +1671,6 @@ Visit [_URL] for more information?
<notification
icon="alertmodal.tga"
- name="AMDOldDriver"
- type="alertmodal">
- There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
-
- Visit [_URL] to check for driver updates?
- <tag>confirm</tag>
- <url option="0" name="url">
- http://support.amd.com/us/Pages/AMDSupportHub.aspx
- </url>
- <usetemplate
- ignoretext="My graphics driver is out of date"
- name="okcancelignore"
- notext="No"
- yestext="Yes"/>
- <tag>fail</tag>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="NVIDIAOldDriver"
- type="alertmodal">
- There is likely a newer driver for your graphics chip. Updating graphics drivers can substantially improve performance.
-
- Visit [_URL] to check for driver updates?
- <tag>confirm</tag>
- <url option="0" name="url">
- http://www.nvidia.com/Download/index.aspx?lang=en-us
- </url>
- <usetemplate
- ignoretext="My graphics driver is out of date"
- name="okcancelignore"
- notext="No"
- yestext="Yes"/>
- <tag>fail</tag>
- </notification>
-
-
- <notification
- icon="alertmodal.tga"
name="UnknownGPU"
type="alertmodal">
Your system contains a graphics card that [APP_NAME] doesn't recognize.
@@ -1904,7 +1886,16 @@ Go to [_URL] for information on purchasing L$?
notext="Cancel"
yestext="OK"/>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="MuteLimitReached"
+ persist="false"
+ type="notify">
+Unable to add new entry to block list because you reached the limit of [MUTE_LIMIT] entries.
+ <tag>fail</tag>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="UnableToLinkObjects"
@@ -3349,6 +3340,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 +3673,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 +4074,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 +4205,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 +4224,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 +5356,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 +5785,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 +5898,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 +7420,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 +7446,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 +8887,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 +9868,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 +9911,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 +10019,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 +10284,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 +11089,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>
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index ded814bbeb..3a34bcbe21 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -15,7 +15,6 @@
<layout_stack
follows="left|right|top"
height="172"
- min_height="172"
left="0"
name="ui_stack"
orientation="horizontal"
@@ -50,7 +49,7 @@
label="Username"
combo_editor.font="SansSerifLarge"
max_chars="128"
- commit_on_focus_lost="false"
+ combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
@@ -107,7 +106,7 @@
follows="left|top"
image_unselected="PushButton_Login"
image_pressed="PushButton_Login_Pressed"
- image_hover="PushButton_Login_Over"
+ image_hover_unselected="PushButton_Login_Over"
label="Log In"
label_color="White"
font="SansSerifMedium"
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
index 94c468e1bb..4d9316768b 100644
--- a/indra/newview/skins/default/xui/en/panel_notification.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
background_opaque="false"
- border_visible="false"
+ border_visible="false"
background_visible="true"
bg_alpha_color="PanelNotificationBackground"
bg_opaque_color="PanelNotificationBackground"
@@ -10,18 +10,17 @@
left="0"
name="notification_panel"
chrome="true"
- show_title="false"
top="0"
- height="140"
+ height="140"
translate="false"
width="305">
<!-- THIS PANEL CONTROLS TOAST HEIGHT? -->
<panel
- border_visible="false"
- bevel_style="none"
+ border_visible="false"
+ bevel_style="none"
background_visible="true"
- bg_alpha_color="ToastBackground"
- bg_opaque_color="ToastBackground"
+ bg_alpha_color="ToastBackground"
+ bg_opaque_color="ToastBackground"
follows="left|right|top"
height="100"
label="info_panel"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
index c1272c6bf8..e3790ae09b 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml
@@ -34,12 +34,9 @@
Searching...
</text>
<scroll_container
- border="true"
- bevel_style="none"
follows="all"
height="400"
width="312"
- min_width="312"
layout="topleft"
left="4"
top="0"
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..0cd56af6d7 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"
@@ -157,7 +157,6 @@
enabled_control="ShowScriptErrors"
control_name="ShowScriptErrorsLocation"
follows="top|left"
- draw_border="false"
height="16"
layout="topleft"
left_delta="50"
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..71e4009571 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -140,7 +140,6 @@
<radio_group
control_name="PreferredBrowserBehavior"
- draw_border="false"
follows="left|top"
height="60"
layout="topleft"
@@ -273,6 +272,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_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 615abbaa89..798dc1c5a6 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -394,7 +394,6 @@
<radio_group
enabled_control="EnableVoiceChat"
control_name="VoiceEarLocation"
- draw_border="false"
follows="left|top"
layout="topleft"
left_delta="-168"
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
index 489d286e67..4672ff8048 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -51,7 +51,7 @@
left_delta="50"
name="version_channel_text"
top_delta="0"
- width="200">
+ width="225">
unknown
</text>
<text
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
index 975b08be05..8e92552921 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml
@@ -61,8 +61,7 @@
right="-2"
height="319"
follows="all"
- halign="center"
- use_highlighting_on_hover="true">
+ halign="center">
<panel
follows="all"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index d3e24a19ef..9995523e61 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -59,7 +59,6 @@
name="inbox_layout_panel"
visible="false"
min_dim="35"
- max_dim="235"
expanded_min_dim="90"
height="235">
<panel
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b70ed5c306..0cfa247032 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -45,9 +45,20 @@ Graphics Card Vendor: [GRAPHICS_CARD_VENDOR]
Graphics Card: [GRAPHICS_CARD]
</string>
<string name="AboutDriver">Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]</string>
+ <string name="AboutOGL">OpenGL Version: [OPENGL_VERSION]</string>
+ <string name="AboutSettings">
+Window size: [WINDOW_WIDTH]x[WINDOW_HEIGHT]
+Font Size Adjustment: [FONT_SIZE_ADJUSTMENT]pt
+UI Scaling: [UI_SCALE]
+Draw distance: [DRAW_DISTANCE]m
+Bandwidth: [NET_BANDWITH]kbit/s
+LOD factor: [LOD_FACTOR]
+Render quality: [RENDER_QUALITY] / 7
+Advanced Lighting Model: [GPU_SHADERS]
+Texture memory: [TEXTURE_MEMORY]MB
+VFS (cache) creation time: [VFS_TIME]
+ </string>
<string name="AboutLibs">
-OpenGL Version: [OPENGL_VERSION]
-
J2C Decoder Version: [J2C_VERSION]
Audio Driver Version: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF Version: [LLCEFLIB_VERSION]
@@ -500,6 +511,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 -->
@@ -2500,6 +2512,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
@@ -2567,7 +2588,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>
@@ -2835,6 +2857,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.
@@ -3681,12 +3709,15 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<!-- Financial operations strings -->
<string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT] [REASON].</string>
+ <string name="paid_you_ldollars_gift">[NAME] paid you L$[AMOUNT]: [REASON]</string>
<string name="paid_you_ldollars_no_reason">[NAME] paid you L$[AMOUNT].</string>
<string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string>
+ <string name="you_paid_ldollars_gift">You paid [NAME] L$[AMOUNT]: [REASON]</string>
<string name="you_paid_ldollars_no_info">You paid L$[AMOUNT].</string>
<string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string>
<string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string>
<string name="you_paid_failure_ldollars">You failed to pay [NAME] L$[AMOUNT] [REASON].</string>
+ <string name="you_paid_failure_ldollars_gift">You failed to pay [NAME] L$[AMOUNT]: [REASON]</string>
<string name="you_paid_failure_ldollars_no_info">You failed to pay L$[AMOUNT].</string>
<string name="you_paid_failure_ldollars_no_reason">You failed to pay [NAME] L$[AMOUNT].</string>
<string name="you_paid_failure_ldollars_no_name">You failed to pay L$[AMOUNT] [REASON].</string>
@@ -4021,6 +4052,7 @@ Try enclosing path to the editor with double quotes.
<string name="Command_Places_Label">Places</string>
<string name="Command_Preferences_Label">Preferences</string>
<string name="Command_Profile_Label">Profile</string>
+ <string name="Command_Report_Abuse_Label">Report Abuse</string>
<string name="Command_Search_Label">Search</string>
<string name="Command_Snapshot_Label">Snapshot</string>
<string name="Command_Speak_Label">Speak</string>
@@ -4052,6 +4084,7 @@ Try enclosing path to the editor with double quotes.
<string name="Command_Places_Tooltip">Places you've saved</string>
<string name="Command_Preferences_Tooltip">Preferences</string>
<string name="Command_Profile_Tooltip">Edit or view your profile</string>
+ <string name="Command_Report_Abuse_Tooltip">Report Abuse</string>
<string name="Command_Search_Tooltip">Find places, events, people</string>
<string name="Command_Snapshot_Tooltip">Take a picture</string>
<string name="Command_Speak_Tooltip">Speak with people nearby using your microphone</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/slider.xml b/indra/newview/skins/default/xui/en/widgets/slider.xml
index f735d09476..6cceafc9ae 100644
--- a/indra/newview/skins/default/xui/en/widgets/slider.xml
+++ b/indra/newview/skins/default/xui/en/widgets/slider.xml
@@ -8,7 +8,6 @@
text_color="LabelTextColor"
text_disabled_color="LabelDisabledColor">
<slider.value_editor name="slider editor"
- max_length="10"
follows="left|bottom"/>
<slider.value_text name="slider text"
follows="left|bottom"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml
index ba2fdf4f1f..1511116ba6 100644
--- a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml
+++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml
@@ -5,8 +5,7 @@
follows="left|top"
>
<multiselect_text font="SansSerifSmall"/>
- <caption_text text="Multiple"
- halign="center"
+ <caption_text halign="center"
font="SansSerifSmall"
v_pad="2"/>
<border bevel_style="in"/>
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/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index ea6cea060b..21ac8a5e53 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -55,6 +55,7 @@ Tarjeta gráfica: [GRAPHICS_CARD]
Versión de J2C Decoder: [J2C_VERSION]
Versión de Audio Driver: [AUDIO_DRIVER_VERSION]
Versión de LLCEFLib/CEF: [LLCEFLIB_VERSION]
+Versión de LibVLC: [LIBVLC_VERSION]
Versión del servidor de voz: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index ae091aba39..5b9f64d5d7 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -64,6 +64,7 @@ Carte graphique : [GRAPHICS_CARD]
Version J2C Decoder : [J2C_VERSION]
Version Audio Driver : [AUDIO_DRIVER_VERSION]
Version LLCEFLib/CEF : [LLCEFLIB_VERSION]
+Version LibVLC : [LIBVLC_VERSION]
Version serveur vocal : [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index effd6f5040..24f57c4230 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -61,6 +61,7 @@ Scheda grafica: [GRAPHICS_CARD]
Versione J2C Decoder: [J2C_VERSION]
Versione Driver audio: [AUDIO_DRIVER_VERSION]
Versione LLCEFLib/CEF: [LLCEFLIB_VERSION]
+Versione LibVLC: [LIBVLC_VERSION]
Versione server voce: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 1ad977fe88..78c7b4810a 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -63,6 +63,7 @@ OS バージョン:[OS_VERSION]
J2C デコーダバージョン:[J2C_VERSION]
オーディオドライババージョン:[AUDIO_DRIVER_VERSION]
LLCEFLib/CEF バージョン: [LLCEFLIB_VERSION]
+LibVLC バージョン: [LIBVLC_VERSION]
ボイスサーバーバージョン: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index dd85f1eb9b..e9dd18043d 100644
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -44,6 +44,7 @@ Wersja OpenGL: [OPENGL_VERSION]
Wersja dekodera J2C: [J2C_VERSION]
Wersja sterownika dźwięku (Audio Driver): [AUDIO_DRIVER_VERSION]
Wersja LLCEFLib/CEF: [LLCEFLIB_VERSION]
+Wersja LibVLC: [LIBVLC_VERSION]
Wersja serwera głosu (Voice Server): [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 50bb9b7e66..c06ee612ac 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -55,6 +55,7 @@ Placa gráfica: [GRAPHICS_CARD]
Versão do J2C Decoder: [J2C_VERSION]
Versão do driver de áudio: [AUDIO_DRIVER_VERSION]
Versão de LLCEFLib/CEF: [LLCEFLIB_VERSION]
+Versão de LibVLC: [LIBVLC_VERSION]
Versão do servidor de voz: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 04bb55c965..b7f054c8fc 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -64,6 +64,7 @@ SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
Версия декодера J2C: [J2C_VERSION]
Версия драйвера звука: [AUDIO_DRIVER_VERSION]
Версия LLCEFLib/CEF: [LLCEFLIB_VERSION]
+Версия LibVLC: [LIBVLC_VERSION]
Версия голосового сервера: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index 67c9197907..3f400e4664 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -64,6 +64,7 @@ Grafik Kartı: [GRAPHICS_CARD]
J2C Kod Çözücü Sürümü: [J2C_VERSION]
Ses Sürücüsü Sürümü: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF Sürümü: [LLCEFLIB_VERSION]
+LibVLC Sürümü: [LIBVLC_VERSION]
Ses Sunucusu Sürümü: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index 2ce310b224..3de2dd8881 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -64,6 +64,7 @@
J2C 解碼器版本: [J2C_VERSION]
音效驅動程式版本: [AUDIO_DRIVER_VERSION]
LLCEFLib/CEF版本:[LLCEFLIB_VERSION]
+LibVLC版本: [LIBVLC_VERSION]
語音伺服器版本: [VOICE_VERSION]
</string>
<string name="AboutTraffic">
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/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index ea5014a59c..4f7f87b6b0 100644
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -34,6 +34,7 @@
#include "../llagent.h"
#include "message.h"
#include "llurlentry.h"
+#include "llpounceable.h"
namespace {
const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
@@ -62,7 +63,7 @@ void LLMessageSystem::addUUID(char const *,LLUUID const &) { }
void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }
void LLMessageSystem::nextBlockFast(char const *) { }
void LLMessageSystem::newMessage(char const *) { }
-LLMessageSystem * gMessageSystem;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
char const* const _PREHASH_AgentID = 0; // never dereferenced during this test
char const* const _PREHASH_AgentData = 0; // never dereferenced during this test
LLAgent gAgent;
diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp
index 8718360f0c..76063e6db1 100644
--- a/indra/test/message_tut.cpp
+++ b/indra/test/message_tut.cpp
@@ -103,7 +103,7 @@ namespace tut
~LLMessageSystemTestData()
{
// not end_messaging_system()
- delete gMessageSystem;
+ delete static_cast<LLMessageSystem*>(gMessageSystem);
gMessageSystem = NULL;
// rm contents of temp dir