From 117e22047c5752352342d64e3fb7ce00a4eb8113 Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Fri, 15 Aug 2008 23:45:04 -0500
Subject: Second Life viewer sources 1.18.1.2
---
linden/doc/contributions.txt | 23 +-
linden/etc/message.xml | 85 +-
linden/indra/SConstruct | 129 +-
linden/indra/indra_complete/indra_complete.sln | 4 +
linden/indra/indra_complete/indra_complete_vc8.sln | 2 +-
linden/indra/lib/python/indra/__init__.py | 12 +-
linden/indra/lib/python/indra/compatibility.py | 121 -
linden/indra/lib/python/indra/ipc/__init__.py | 27 +
linden/indra/lib/python/indra/ipc/compatibility.py | 123 +
linden/indra/lib/python/indra/ipc/llmessage.py | 373 ++
linden/indra/lib/python/indra/ipc/tokenstream.py | 154 +
linden/indra/lib/python/indra/llmanifest.py | 580 ---
linden/indra/lib/python/indra/llmessage.py | 375 --
linden/indra/lib/python/indra/tokenstream.py | 152 -
linden/indra/lib/python/indra/util/__init__.py | 27 +
linden/indra/lib/python/indra/util/llmanifest.py | 582 +++
.../linux_crash_logger/linux_crash_logger.cpp | 10 +-
linden/indra/llaudio/audioengine.cpp | 2 +-
linden/indra/llcharacter/lljoint.cpp | 33 -
linden/indra/llcharacter/lljoint.h | 5 -
linden/indra/llcharacter/llmotion.cpp | 11 +
linden/indra/llcharacter/llmotion.h | 8 +-
linden/indra/llcharacter/llmotioncontroller.cpp | 157 +-
linden/indra/llcharacter/llmotioncontroller.h | 15 +-
linden/indra/llcharacter/llpose.cpp | 20 +-
linden/indra/llcharacter/llpose.h | 2 +-
linden/indra/llcommon/indra_constants.h | 10 +-
linden/indra/llcommon/llapr.h | 2 +-
linden/indra/llcommon/llcommon.vcproj | 3 -
linden/indra/llcommon/lldate.cpp | 48 +
linden/indra/llcommon/lldate.h | 6 +
linden/indra/llcommon/llfasttimer.cpp | 8 +-
linden/indra/llcommon/llfixedbuffer.cpp | 2 +-
linden/indra/llcommon/llhash.h | 4 +-
linden/indra/llcommon/llmemory.cpp | 5 +-
linden/indra/llcommon/llmemtype.h | 2 +
linden/indra/llcommon/llpagemem.h | 393 --
linden/indra/llcommon/llpreprocessor.h | 27 +-
linden/indra/llcommon/llprocessor.cpp | 184 +-
linden/indra/llcommon/llprocessor.h | 15 +
linden/indra/llcommon/llsdserialize_xml.cpp | 6 +-
linden/indra/llcommon/llsdutil.cpp | 2 +-
linden/indra/llcommon/llskiplist.h | 12 +-
linden/indra/llcommon/llstring.h | 10 +-
linden/indra/llcommon/llsys.cpp | 204 +-
linden/indra/llcommon/llsys.h | 13 +-
linden/indra/llcommon/llthread.cpp | 4 +-
linden/indra/llcommon/lltimer.cpp | 14 +-
linden/indra/llcommon/lltimer.h | 2 +-
linden/indra/llcommon/lluri.cpp | 35 +-
linden/indra/llcommon/lluri.h | 97 +-
linden/indra/llcommon/llversion.h | 4 +-
linden/indra/llcommon/llworkerthread.cpp | 2 +
linden/indra/llcommon/stdtypes.h | 22 +-
linden/indra/llcommon/timing.h | 2 +-
linden/indra/llimage/llimagejpeg.h | 9 +-
linden/indra/llinventory/llinventory.cpp | 12 +-
linden/indra/llinventory/llpermissions.cpp | 6 +-
linden/indra/llinventory/llsaleinfo.cpp | 6 +-
linden/indra/llmath/llcrc.cpp | 19 +-
linden/indra/llmath/llcrc.h | 2 +-
linden/indra/llmath/llmath.h | 3 +
linden/indra/llmath/llmath.vcproj | 12 +
linden/indra/llmath/llmath_vc8.vcproj | 16 +
linden/indra/llmath/llmd5.cpp | 111 +-
linden/indra/llmath/llmd5.h | 17 +-
linden/indra/llmath/lloctree.h | 68 +-
linden/indra/llmath/llrect.h | 47 +-
linden/indra/llmath/lltreenode.h | 22 +-
linden/indra/llmath/lluuid.cpp | 4 +-
linden/indra/llmath/llv4math.h | 143 +
linden/indra/llmath/llv4matrix3.h | 222 ++
linden/indra/llmath/llv4matrix4.h | 251 ++
linden/indra/llmath/llv4vector3.h | 82 +
linden/indra/llmath/llvolume.cpp | 18 +-
linden/indra/llmath/llvolume.h | 2 +-
linden/indra/llmedia/files.lst | 3 +
linden/indra/llmedia/llmedia_vc8.vcproj | 594 +--
linden/indra/llmedia/llmediabase.cpp | 8 +
linden/indra/llmedia/llmediaimplgstreamer.cpp | 715 ++++
linden/indra/llmedia/llmediaimplgstreamer.h | 126 +
linden/indra/llmedia/llmediaimplgstreamer_syms.cpp | 189 +
linden/indra/llmedia/llmediaimplgstreamer_syms.h | 75 +
.../llmedia/llmediaimplgstreamer_syms_raw.inc | 42 +
.../llmedia/llmediaimplgstreamer_syms_rawa.inc | 5 +
.../llmedia/llmediaimplgstreamer_syms_rawv.inc | 5 +
.../indra/llmedia/llmediaimplgstreamervidplug.cpp | 461 +++
linden/indra/llmedia/llmediaimplgstreamervidplug.h | 101 +
linden/indra/llmedia/llmediamoviebase.cpp | 8 +
linden/indra/llmessage/llcurl.cpp | 2 +-
linden/indra/llmessage/lldatapacker.cpp | 5 +-
linden/indra/llmessage/llhttpassetstorage.cpp | 6 +-
linden/indra/llmessage/llhttpclient.cpp | 40 +-
linden/indra/llmessage/llhttpclient.h | 2 +
linden/indra/llmessage/lliohttpserver.cpp | 37 +-
linden/indra/llmessage/llmessageconfig.cpp | 16 +
linden/indra/llmessage/llmessageconfig.h | 2 +
linden/indra/llmessage/llmessagereader.cpp | 3 +-
linden/indra/llmessage/llmessagetemplateparser.cpp | 1 +
linden/indra/llmessage/llnamevalue.cpp | 3 +
linden/indra/llmessage/llnamevalue.h | 1 -
linden/indra/llmessage/llservicebuilder.cpp | 19 +-
linden/indra/llmessage/lltemplatemessagereader.cpp | 11 +-
linden/indra/llmessage/lluseroperation.cpp | 21 +-
linden/indra/llmessage/lluseroperation.h | 4 +
linden/indra/llmessage/llxfer_file.cpp | 6 +-
linden/indra/llmessage/message.cpp | 1 +
linden/indra/llmessage/message.h | 103 +-
linden/indra/llrender/llfont.cpp | 37 +-
linden/indra/llrender/llimagegl.cpp | 3 +-
linden/indra/llrender/llimagegl.h | 1 -
linden/indra/llui/files.lst | 1 -
linden/indra/llui/llbutton.cpp | 28 +-
linden/indra/llui/llbutton.h | 7 +-
linden/indra/llui/llcheckboxctrl.cpp | 12 +
linden/indra/llui/llcheckboxctrl.h | 2 +
linden/indra/llui/llctrlselectioninterface.h | 3 +-
linden/indra/llui/llfloater.cpp | 286 +-
linden/indra/llui/llfloater.h | 14 +-
linden/indra/llui/llfocusmgr.cpp | 9 +-
linden/indra/llui/llfocusmgr.h | 1 +
linden/indra/llui/lllineeditor.h | 1 +
linden/indra/llui/llmenugl.cpp | 52 +-
linden/indra/llui/llpanel.cpp | 659 +++-
linden/indra/llui/llpanel.h | 58 +
linden/indra/llui/llradiogroup.cpp | 66 +-
linden/indra/llui/llradiogroup.h | 21 +-
linden/indra/llui/llresizebar.cpp | 86 +-
linden/indra/llui/llresizebar.h | 11 +-
linden/indra/llui/llresmgr.cpp | 3 +
linden/indra/llui/llscrollcontainer.cpp | 3 +-
linden/indra/llui/llscrolllistctrl.cpp | 55 +-
linden/indra/llui/llscrolllistctrl.h | 1 +
linden/indra/llui/llslider.cpp | 158 +-
linden/indra/llui/llslider.h | 6 +
linden/indra/llui/llsliderctrl.cpp | 10 +-
linden/indra/llui/llsliderctrl.h | 4 +-
linden/indra/llui/lltabcontainer.cpp | 114 +-
linden/indra/llui/lltabcontainer.h | 11 +-
linden/indra/llui/lltabcontainervertical.cpp | 74 +-
linden/indra/llui/lltexteditor.cpp | 51 +-
linden/indra/llui/lltexteditor.h | 4 +-
linden/indra/llui/llui.cpp | 60 +-
linden/indra/llui/llui.h | 57 +-
linden/indra/llui/lluictrl.cpp | 2 +-
linden/indra/llui/lluictrl.h | 3 +
linden/indra/llui/lluictrlfactory.cpp | 36 +-
linden/indra/llui/lluictrlfactory.h | 8 +
linden/indra/llui/lluistring.cpp | 3 +
linden/indra/llui/lluistring.h | 2 +
linden/indra/llui/lluixmltags.h | 1 +
linden/indra/llui/llview.cpp | 125 +-
linden/indra/llui/llview.h | 2 +-
linden/indra/llvfs/files.sunos5.lst | 1 +
linden/indra/llvfs/lldir.cpp | 3 +
linden/indra/llvfs/lldir_linux.cpp | 17 +-
linden/indra/llvfs/lldir_solaris.cpp | 374 ++
linden/indra/llvfs/lldir_solaris.h | 61 +
linden/indra/llvfs/llvfs.cpp | 90 +-
linden/indra/llwindow/files.sunos5.lst | 4 +
linden/indra/llwindow/files.win32.lst | 2 +
linden/indra/llwindow/llglstubs.h | 2 +-
linden/indra/llwindow/llwindowsdl.cpp | 46 +-
linden/indra/llwindow/llwindowsolaris.cpp | 58 +
linden/indra/llwindow/llwindowsolaris.h | 116 +
linden/indra/llwindow/llwindowwin32.cpp | 12 +
linden/indra/llxml/llxmlnode.cpp | 11 +-
linden/indra/llxml/llxmlnode.h | 4 +
linden/indra/llxml/llxmlparser.h | 4 +
linden/indra/lscript/lscript_compile/indra.l | 9 +-
linden/indra/lscript/lscript_compile/indra.y | 4 +
.../lscript/lscript_compile/lscript_bytecode.cpp | 5 +-
.../lscript/lscript_execute/lscript_execute.cpp | 14 +-
.../lscript/lscript_execute/lscript_readlso.cpp | 14 +-
linden/indra/mac_updater/mac_updater.cpp | 9 +-
.../indra/newview/English.lproj/InfoPlist.strings | 4 +-
linden/indra/newview/Info-SecondLife.plist | 2 +-
linden/indra/newview/fakevoicesoundsignal.cpp | 49 +
linden/indra/newview/fakevoicesoundsignal.h | 25 +
linden/indra/newview/featuretable_solaris.txt | 173 +
linden/indra/newview/files.lst | 13 +-
linden/indra/newview/licenses-solaris.txt | 516 +++
linden/indra/newview/linux_tools/client-readme.txt | 29 +-
linden/indra/newview/linux_tools/unicode.ttf | 2 +-
linden/indra/newview/linux_tools/wrapper.sh | 17 +
linden/indra/newview/llagent.cpp | 62 +-
linden/indra/newview/llagent.h | 2 +-
linden/indra/newview/llaudiosourcevo.cpp | 2 +-
linden/indra/newview/llaudiostatus.cpp | 412 --
linden/indra/newview/llaudiostatus.h | 52 -
linden/indra/newview/llcallingcard.cpp | 1 +
linden/indra/newview/llchatbar.cpp | 155 +-
linden/indra/newview/llchatbar.h | 21 +-
linden/indra/newview/llcolorswatch.cpp | 15 -
linden/indra/newview/llcolorswatch.h | 2 -
linden/indra/newview/llcontroldef.cpp | 604 ++-
linden/indra/newview/lldebugmessagebox.cpp | 10 +-
linden/indra/newview/lldebugview.cpp | 14 -
linden/indra/newview/lldrawable.h | 1 +
linden/indra/newview/lldrawpoolsky.h | 2 +-
linden/indra/newview/lldrawpoolwater.cpp | 2 +-
linden/indra/newview/llemote.h | 2 +
linden/indra/newview/llface.h | 1 -
linden/indra/newview/llfasttimerview.cpp | 3 +-
linden/indra/newview/llfeaturemanager.cpp | 7 +
linden/indra/newview/llfirstuse.cpp | 13 +
linden/indra/newview/llfirstuse.h | 1 +
linden/indra/newview/llfloateractivespeakers.cpp | 831 ++++
linden/indra/newview/llfloateractivespeakers.h | 211 +
linden/indra/newview/llfloateranimpreview.cpp | 2 +-
linden/indra/newview/llfloateravatarpicker.cpp | 7 +-
linden/indra/newview/llfloaterchat.cpp | 213 +-
linden/indra/newview/llfloaterchat.h | 25 +-
linden/indra/newview/llfloaterchatterbox.cpp | 342 ++
linden/indra/newview/llfloaterchatterbox.h | 87 +
linden/indra/newview/llfloatercustomize.cpp | 28 +-
linden/indra/newview/llfloaterdirectory.cpp | 14 +-
linden/indra/newview/llfloaterfriends.cpp | 395 +-
linden/indra/newview/llfloaterfriends.h | 26 +-
linden/indra/newview/llfloatergroups.cpp | 477 ++-
linden/indra/newview/llfloatergroups.h | 79 +-
linden/indra/newview/llfloaterhtmlhelp.cpp | 2 +-
linden/indra/newview/llfloaterimport.cpp | 5 +-
linden/indra/newview/llfloaterinspect.cpp | 19 +-
linden/indra/newview/llfloaterland.cpp | 73 +-
linden/indra/newview/llfloaterland.h | 2 +
linden/indra/newview/llfloatermute.cpp | 1 +
linden/indra/newview/llfloaternamedesc.cpp | 4 +-
linden/indra/newview/llfloaternewim.cpp | 8 +-
linden/indra/newview/llfloaterpostcard.cpp | 2 +-
linden/indra/newview/llfloaterpreference.cpp | 10 +-
linden/indra/newview/llfloaterpreference.h | 2 +
linden/indra/newview/llfloaterregioninfo.cpp | 26 +-
linden/indra/newview/llfloaterscriptdebug.cpp | 11 +-
linden/indra/newview/llfloatersnapshot.cpp | 22 +-
linden/indra/newview/llfloatertest.cpp | 7 +
linden/indra/newview/llfloatertest.h | 8 +
linden/indra/newview/llfloatertools.cpp | 11 +-
linden/indra/newview/llfloatertools.h | 2 -
linden/indra/newview/llfloatervoicewizard.cpp | 444 +++
linden/indra/newview/llfloatervoicewizard.h | 100 +
linden/indra/newview/llfloaterworldmap.cpp | 75 +-
linden/indra/newview/llfloaterworldmap.h | 1 +
linden/indra/newview/llfolderview.cpp | 79 +-
linden/indra/newview/llframestatview.cpp | 6 +
linden/indra/newview/llgesturemgr.cpp | 68 +-
linden/indra/newview/llgesturemgr.h | 2 +-
linden/indra/newview/llglslshader.cpp | 21 +-
linden/indra/newview/llhoverview.cpp | 7 +
linden/indra/newview/llhudeffectlookat.cpp | 63 +-
linden/indra/newview/llhudmanager.cpp | 101 -
linden/indra/newview/llhudmanager.h | 10 -
linden/indra/newview/llhudobject.cpp | 4 +
linden/indra/newview/llhudobject.h | 3 +-
linden/indra/newview/llhudtext.cpp | 3 +-
linden/indra/newview/llimpanel.cpp | 1020 ++++-
linden/indra/newview/llimpanel.h | 155 +-
linden/indra/newview/llimview.cpp | 823 ++--
linden/indra/newview/llimview.h | 57 +-
linden/indra/newview/llinventoryactions.cpp | 4 +-
linden/indra/newview/llinventorybridge.cpp | 9 +-
linden/indra/newview/llinventorymodel.cpp | 9 +-
linden/indra/newview/llinventoryview.cpp | 12 +-
linden/indra/newview/llmediaremotectrl.cpp | 167 +-
linden/indra/newview/llmediaremotectrl.h | 92 +-
linden/indra/newview/llmemoryview.cpp | 53 +-
linden/indra/newview/llmemoryview.h | 7 +
linden/indra/newview/llmutelist.cpp | 124 +-
linden/indra/newview/llmutelist.h | 32 +-
linden/indra/newview/llnetmap.cpp | 2 +-
linden/indra/newview/llnotify.cpp | 215 +-
linden/indra/newview/llnotify.h | 60 +-
linden/indra/newview/lloverlaybar.cpp | 453 ++-
linden/indra/newview/lloverlaybar.h | 45 +-
linden/indra/newview/llpanelaudioprefs.cpp | 142 +-
linden/indra/newview/llpanelaudioprefs.h | 15 +-
linden/indra/newview/llpanelaudiovolume.cpp | 109 +
linden/indra/newview/llpanelaudiovolume.h | 55 +
linden/indra/newview/llpanelavatar.cpp | 36 +-
linden/indra/newview/llpanelavatar.h | 18 +-
linden/indra/newview/llpanelclassified.cpp | 21 +-
linden/indra/newview/llpanelclassified.h | 25 +-
linden/indra/newview/llpaneldebug.cpp | 2 +
linden/indra/newview/llpaneldirbrowser.cpp | 5 +-
linden/indra/newview/llpaneldisplay.cpp | 1 +
linden/indra/newview/llpanelgeneral.cpp | 2 -
linden/indra/newview/llpanelgroup.cpp | 11 +-
linden/indra/newview/llpanelinventory.cpp | 2 +-
linden/indra/newview/llpanellogin.cpp | 32 +-
linden/indra/newview/llpanellogin.h | 1 +
linden/indra/newview/llpanelpermissions.cpp | 16 +-
linden/indra/newview/llpolymesh.cpp | 5 +-
linden/indra/newview/llprefschat.cpp | 13 -
linden/indra/newview/llprefsvoice.cpp | 277 ++
linden/indra/newview/llprefsvoice.h | 87 +
linden/indra/newview/llpreview.cpp | 3 +-
linden/indra/newview/llpreviewscript.cpp | 32 +-
linden/indra/newview/llpreviewsound.cpp | 15 +-
linden/indra/newview/llpreviewtexture.cpp | 2 +-
linden/indra/newview/llselectmgr.cpp | 40 +-
linden/indra/newview/llselectmgr.h | 5 +-
linden/indra/newview/llstartup.cpp | 128 +-
linden/indra/newview/llstatusbar.cpp | 110 +-
linden/indra/newview/llstatusbar.h | 25 +-
linden/indra/newview/lltoolbar.cpp | 35 +-
linden/indra/newview/lltoolbar.h | 3 +-
linden/indra/newview/lltooldraganddrop.cpp | 2 -
linden/indra/newview/lltoolselect.cpp | 2 +-
linden/indra/newview/lluserauth.cpp | 2 +
linden/indra/newview/llviewercontrol.h | 2 +
linden/indra/newview/llviewerimage.h | 22 +-
linden/indra/newview/llviewerimagelist.cpp | 17 +
linden/indra/newview/llviewerinventory.cpp | 6 +-
linden/indra/newview/llviewerjointattachment.cpp | 17 +-
linden/indra/newview/llviewerjointmesh.cpp | 215 +-
linden/indra/newview/llviewerjointmesh.h | 16 +
linden/indra/newview/llviewerjointmesh_sse.cpp | 114 +
linden/indra/newview/llviewerjointmesh_sse2.cpp | 121 +
linden/indra/newview/llviewerjointmesh_vec.cpp | 95 +
linden/indra/newview/llviewermenu.cpp | 168 +-
linden/indra/newview/llviewermenufile.cpp | 16 +-
linden/indra/newview/llviewermessage.cpp | 98 +-
linden/indra/newview/llviewerobject.cpp | 23 +-
linden/indra/newview/llviewerobject.h | 5 +-
linden/indra/newview/llviewerobjectlist.cpp | 6 +-
linden/indra/newview/llviewerparcelmgr.cpp | 19 +-
linden/indra/newview/llviewerpartsim.cpp | 2 +-
linden/indra/newview/llviewerpartsource.cpp | 6 +
linden/indra/newview/llviewerprecompiledheaders.h | 2 -
linden/indra/newview/llviewerregion.cpp | 148 +-
linden/indra/newview/llviewerregion.h | 16 +-
linden/indra/newview/llviewertexteditor.cpp | 17 +-
linden/indra/newview/llvieweruictrlfactory.cpp | 7 -
linden/indra/newview/llvieweruictrlfactory.h | 2 -
linden/indra/newview/llviewerwindow.cpp | 338 +-
linden/indra/newview/llviewerwindow.h | 5 +
linden/indra/newview/llvoavatar.cpp | 318 +-
linden/indra/newview/llvoavatar.h | 16 +
linden/indra/newview/llvocache.cpp | 45 +-
linden/indra/newview/llvograss.cpp | 8 +-
linden/indra/newview/llvoiceclient.cpp | 4076 ++++++++++++++++++++
linden/indra/newview/llvoiceclient.h | 523 +++
linden/indra/newview/llvoiceremotectrl.cpp | 180 +
linden/indra/newview/llvoiceremotectrl.h | 56 +
linden/indra/newview/llvoicevisualizer.cpp | 431 +++
linden/indra/newview/llvoicevisualizer.h | 111 +
linden/indra/newview/llvolumesliderctrl.cpp | 193 -
linden/indra/newview/llvolumesliderctrl.h | 56 -
linden/indra/newview/llvopartgroup.cpp | 2 +-
linden/indra/newview/llvosky.cpp | 8 +-
linden/indra/newview/llvotree.cpp | 4 +-
linden/indra/newview/llvovolume.cpp | 4 +-
linden/indra/newview/llweb.cpp | 2 +
linden/indra/newview/llwebbrowserctrl.cpp | 4 +-
linden/indra/newview/llworldmap.cpp | 11 +-
linden/indra/newview/llworldmap.h | 4 +-
linden/indra/newview/llworldmapview.cpp | 3 +-
linden/indra/newview/llxmlrpctransaction.cpp | 2 +
.../newview/macview.xcodeproj/project.pbxproj | 238 +-
linden/indra/newview/moviemaker.cpp | 10 +-
linden/indra/newview/newview.vcproj | 210 +-
linden/indra/newview/newview_vc8.vcproj | 208 +-
linden/indra/newview/pipeline.cpp | 265 +-
linden/indra/newview/pipeline.h | 27 +-
linden/indra/newview/postbuild.bat | 52 +-
linden/indra/newview/releasenotes.txt | 80 +-
linden/indra/newview/res/newViewRes.rc | 8 +-
.../newview/secondlife setup build firstlook.bat | 4 -
.../newview/secondlife setup build voicebeta.bat | 4 +
.../secondlife setup build voicefirstlook.bat | 4 +
linden/indra/newview/skins/textures/textures.xml | 22 +-
linden/indra/newview/skins/xui/de/role_actions.xml | 82 +-
linden/indra/newview/skins/xui/en-us/alerts.xml | 59 +-
.../newview/skins/xui/en-us/floater_about.xml | 5 +-
.../newview/skins/xui/en-us/floater_about_land.xml | 78 +-
.../skins/xui/en-us/floater_active_speakers.xml | 72 +
.../skins/xui/en-us/floater_audio_volume.xml | 11 +
.../skins/xui/en-us/floater_buy_contents.xml | 2 +-
.../skins/xui/en-us/floater_chat_history.xml | 134 +-
.../newview/skins/xui/en-us/floater_chatterbox.xml | 6 +
.../skins/xui/en-us/floater_device_settings.xml | 4 +
.../newview/skins/xui/en-us/floater_friends.xml | 225 +-
.../newview/skins/xui/en-us/floater_groups.xml | 80 +-
.../indra/newview/skins/xui/en-us/floater_im.xml | 39 +-
.../skins/xui/en-us/floater_instant_message.xml | 57 +-
.../xui/en-us/floater_instant_message_ad_hoc.xml | 119 +
.../xui/en-us/floater_instant_message_group.xml | 160 +
.../en-us/floater_inventory_item_properties.xml | 4 +-
.../newview/skins/xui/en-us/floater_my_friends.xml | 9 +
.../newview/skins/xui/en-us/floater_report_bug.xml | 4 +-
.../newview/skins/xui/en-us/floater_select_key.xml | 15 +
.../skins/xui/en-us/floater_settings_debug.xml | 7 +-
.../indra/newview/skins/xui/en-us/floater_test.xml | 5 +
.../skins/xui/en-us/floater_voice_wizard.xml | 17 +
.../newview/skins/xui/en-us/menu_inventory.xml | 16 +-
.../indra/newview/skins/xui/en-us/menu_viewer.xml | 70 +-
linden/indra/newview/skins/xui/en-us/notify.xml | 93 +-
.../indra/newview/skins/xui/en-us/panel_audio.xml | 39 +
.../newview/skins/xui/en-us/panel_audio_device.xml | 77 +
.../newview/skins/xui/en-us/panel_friends.xml | 62 +
.../newview/skins/xui/en-us/panel_group_roles.xml | 2 +
.../indra/newview/skins/xui/en-us/panel_groups.xml | 43 +
.../skins/xui/en-us/panel_master_volume.xml | 13 +
.../newview/skins/xui/en-us/panel_media_remote.xml | 27 +-
.../newview/skins/xui/en-us/panel_music_remote.xml | 27 +-
.../newview/skins/xui/en-us/panel_overlaybar.xml | 17 +-
.../skins/xui/en-us/panel_preferences_audio.xml | 155 +-
.../skins/xui/en-us/panel_preferences_chat.xml | 2 +-
.../xui/en-us/panel_preferences_graphics3.xml | 2 +-
.../skins/xui/en-us/panel_preferences_voice.xml | 89 +
.../skins/xui/en-us/panel_region_estate.xml | 7 +-
.../newview/skins/xui/en-us/panel_status_bar.xml | 8 +-
.../newview/skins/xui/en-us/panel_toolbar.xml | 7 +-
.../newview/skins/xui/en-us/panel_voice_enable.xml | 98 +
.../skins/xui/en-us/panel_voice_options.xml | 46 +
.../newview/skins/xui/en-us/panel_voice_remote.xml | 12 +
linden/indra/newview/skins/xui/es/role_actions.xml | 372 +-
linden/indra/newview/skins/xui/fr/role_actions.xml | 378 +-
linden/indra/newview/skins/xui/ja/role_actions.xml | 84 +-
linden/indra/newview/skins/xui/ko/role_actions.xml | 84 +-
linden/indra/newview/skins/xui/pt/role_actions.xml | 372 +-
linden/indra/newview/skins/xui/zh/role_actions.xml | 366 +-
linden/indra/newview/viewer.cpp | 944 ++---
linden/indra/newview/viewer.h | 7 +
linden/indra/newview/viewer_manifest.py | 197 +-
linden/indra/test/files.lst | 1 +
linden/indra/test/llbuffer_tut.cpp | 2 +
linden/indra/test/llhttpdate_tut.cpp | 92 +
linden/indra/test/llmessagetemplateparser_tut.cpp | 1 +
linden/indra/test/llpermissions_tut.cpp | 1 +
linden/indra/test/llsdmessagereader_tut.cpp | 1 +
linden/indra/test/llservicebuilder_tut.cpp | 17 +
linden/indra/test/lltemplatemessagebuilder_tut.cpp | 1 +
linden/indra/test/lluri_tut.cpp | 12 +-
linden/indra/test/message_tut.cpp | 1 +
linden/indra/test/test_llmanifest.py | 2 +-
linden/indra/win_crash_logger/resource.h | 28 -
linden/indra/win_crash_logger/win_crash_logger.rc | 10 +-
linden/scripts/template_verifier.py | 159 +-
439 files changed, 26450 insertions(+), 9119 deletions(-)
delete mode 100644 linden/indra/lib/python/indra/compatibility.py
create mode 100644 linden/indra/lib/python/indra/ipc/__init__.py
create mode 100644 linden/indra/lib/python/indra/ipc/compatibility.py
create mode 100644 linden/indra/lib/python/indra/ipc/llmessage.py
create mode 100644 linden/indra/lib/python/indra/ipc/tokenstream.py
delete mode 100644 linden/indra/lib/python/indra/llmanifest.py
delete mode 100644 linden/indra/lib/python/indra/llmessage.py
delete mode 100644 linden/indra/lib/python/indra/tokenstream.py
create mode 100644 linden/indra/lib/python/indra/util/__init__.py
create mode 100644 linden/indra/lib/python/indra/util/llmanifest.py
delete mode 100644 linden/indra/llcommon/llpagemem.h
create mode 100644 linden/indra/llmath/llv4math.h
create mode 100644 linden/indra/llmath/llv4matrix3.h
create mode 100644 linden/indra/llmath/llv4matrix4.h
create mode 100644 linden/indra/llmath/llv4vector3.h
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer.cpp
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer.h
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer_syms.cpp
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer_syms.h
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc
create mode 100644 linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc
create mode 100644 linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
create mode 100644 linden/indra/llmedia/llmediaimplgstreamervidplug.h
create mode 100644 linden/indra/llvfs/files.sunos5.lst
create mode 100644 linden/indra/llvfs/lldir_solaris.cpp
create mode 100644 linden/indra/llvfs/lldir_solaris.h
create mode 100644 linden/indra/llwindow/files.sunos5.lst
create mode 100644 linden/indra/llwindow/files.win32.lst
create mode 100644 linden/indra/llwindow/llwindowsolaris.cpp
create mode 100644 linden/indra/llwindow/llwindowsolaris.h
create mode 100644 linden/indra/newview/fakevoicesoundsignal.cpp
create mode 100644 linden/indra/newview/fakevoicesoundsignal.h
create mode 100644 linden/indra/newview/featuretable_solaris.txt
create mode 100644 linden/indra/newview/licenses-solaris.txt
delete mode 100644 linden/indra/newview/llaudiostatus.cpp
delete mode 100644 linden/indra/newview/llaudiostatus.h
create mode 100644 linden/indra/newview/llfloateractivespeakers.cpp
create mode 100644 linden/indra/newview/llfloateractivespeakers.h
create mode 100644 linden/indra/newview/llfloaterchatterbox.cpp
create mode 100644 linden/indra/newview/llfloaterchatterbox.h
create mode 100644 linden/indra/newview/llfloatervoicewizard.cpp
create mode 100644 linden/indra/newview/llfloatervoicewizard.h
create mode 100644 linden/indra/newview/llpanelaudiovolume.cpp
create mode 100644 linden/indra/newview/llpanelaudiovolume.h
create mode 100644 linden/indra/newview/llprefsvoice.cpp
create mode 100644 linden/indra/newview/llprefsvoice.h
create mode 100644 linden/indra/newview/llviewerjointmesh_sse.cpp
create mode 100644 linden/indra/newview/llviewerjointmesh_sse2.cpp
create mode 100644 linden/indra/newview/llviewerjointmesh_vec.cpp
create mode 100644 linden/indra/newview/llvoiceclient.cpp
create mode 100644 linden/indra/newview/llvoiceclient.h
create mode 100644 linden/indra/newview/llvoiceremotectrl.cpp
create mode 100644 linden/indra/newview/llvoiceremotectrl.h
create mode 100644 linden/indra/newview/llvoicevisualizer.cpp
create mode 100644 linden/indra/newview/llvoicevisualizer.h
delete mode 100644 linden/indra/newview/llvolumesliderctrl.cpp
delete mode 100644 linden/indra/newview/llvolumesliderctrl.h
delete mode 100644 linden/indra/newview/secondlife setup build firstlook.bat
create mode 100644 linden/indra/newview/secondlife setup build voicebeta.bat
create mode 100644 linden/indra/newview/secondlife setup build voicefirstlook.bat
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_active_speakers.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_audio_volume.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_chatterbox.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_device_settings.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_instant_message_ad_hoc.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_instant_message_group.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_my_friends.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_select_key.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_test.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/floater_voice_wizard.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_audio.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_audio_device.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_friends.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_groups.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_master_volume.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_preferences_voice.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_voice_enable.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_voice_options.xml
create mode 100644 linden/indra/newview/skins/xui/en-us/panel_voice_remote.xml
create mode 100644 linden/indra/test/llhttpdate_tut.cpp
diff --git a/linden/doc/contributions.txt b/linden/doc/contributions.txt
index 4546053..26f37a4 100644
--- a/linden/doc/contributions.txt
+++ b/linden/doc/contributions.txt
@@ -4,22 +4,27 @@ along with the issue identifier corresponding to the patches we've
received from them. To see more about these contributions, visit
http://jira.secondlife.com/ and enter the issue identifier.
-Able Whitman - VWR-650
+Able Whitman - VWR-650, VWR-1460
Alissa Sabre - VWR-81, VWR-83, VWR-171, VWR-251, VWR-414, VWR-415, VWR-459, VWR-606, VWR-652, VWR-1351, VWR-1410
Argent Stonecutter - VWR-68
Benja Kepler - VWR-746
Blakar Ogre - VWR-881
blino Nakamura - VWR-17
bushing Spatula - VWR-424, VWR-119
+Catherine Pfeffer - VWR-1282
Dale Glass - VWR-120, VWR-560
Drewan Keats - VWR-28, VWR-248, VWR-412
Duckless Vandyke - VWR-383
Dylan Haskell - VWR-72
-Dzonatas Sol - VWR-198, VWR-878
-Eddy Stryker - VWR-15, VWR-23
+Dzonatas Sol - VWR-198, VWR-878, VWR-1704, VWR-1705, VWR-1729, VWR-975
+Eddy Stryker - VWR-15, VWR-23, VWR-1468
+EponymousDylan Ra - VWR-1465
+Fee Larsson - VWR-1314
Fremont Cunningham - VWR-1147
-Gigs Taggart - VWR-71, VWR-326, VWR-1217
+Gigs Taggart - VWR-71, VWR-326, VWR-1217, VWR-1434
Ginko Bayliss - VWR-4
+Grazer Kline - VWR-1092
+Gudmund Shepherd - VWR-1594
Hikkoshi Sakai - VWR-429
Hiro Sommambulist - VWR-66, VWR-97, VWR-100, VWR-105, VWR-108, VWR-118, VWR-132, VWR-136, VWR-143
Iskar Ariantho - VWR-1223
@@ -27,20 +32,22 @@ Jacek Antonelli - VWR-165, VWR-188, VWR-427, VWR-597
Joghert LeSabre - VWR-64
Kage Pixel - VWR-11
Kunnis Basiat - VWR-82
-Nicholaz Beresford - VWR-132, VWR-176, VWR-793, VWR-794, VWR-802, VWR-803, VWR-804, VWR-805, VWR-808, VWR-809, VWR-810, VWR-823, VWR-869, VWR-870, VWR-871, VWR-873, VWR-908, VWR-966, VWR-1410, VWR-1418
+McCabe Maxsted - VWR-1318
+Nicholaz Beresford - VWR-132, VWR-176, VWR-364, VWR-691, VWR-793, VWR-794, VWR-802, VWR-803, VWR-804, VWR-805, VWR-808, VWR-809, VWR-810, VWR-823, VWR-856, VWR-869, VWR-870, VWR-871, VWR-873, VWR-908, VWR-966, VWR-1221, VWR-1270, VWR-1296, VWR-1410, VWR-1418, VWR-1453, VWR-1455, VWR-1470, VWR-1578, VWR-1626, VWR-1655, VWR-1698, VWR-1706, VWR-1723, VWR-1732, VWR-1861
Paul Churchill - VWR-20
Paula Innis - VWR-30, VWR-1049
Peekay Semyorka - VWR-7, VWR-19, VWR-49, VWR-79
Ryozu Kojima - VWR-287
SignpostMarv Martin - VWR-154, VWR-155
Simon Nolan - VWR-409
-SpacedOut Frye - VWR-57, VWR-94, VWR-121, VWR-123
+SpacedOut Frye - VWR-57, VWR-94, VWR-121, VWR-123, VWR-1823
Stevex Janus - VWR-1182
Still Defiant - VWR-207, VWR-446
Strife Onizuka - SVC-9, VWR-74, VWR-85, VWR-148
tenebrous pau - VWR-247
-TBBle Kurosawa - VWR-938, VWR-941, VWR-944
+TBBle Kurosawa - VWR-938, VWR-941, VWR-944, VWR-945
Tharax Ferraris - VWR-605
+Thraxis Epsilon - VWR-383, SVC-371
+Whoops Babii - VWR-1640
Zi Ree - VWR-671, VWR-682, VWR-1140
Zipherius Turas - VWR-76, VWR-77
-
diff --git a/linden/etc/message.xml b/linden/etc/message.xml
index ad2364a..304ba32 100644
--- a/linden/etc/message.xml
+++ b/linden/etc/message.xml
@@ -243,7 +243,6 @@
trusted-sender
false
-
EdgeDataPacket
- ChatterBoxSessionLeaveReply
+ ChatterBoxSessionAgentListUpdates
- ChatterBoxSessionAgentListUpdates
+ ChatterBoxInvitation
- ChatterBoxInvitation
+
+ ParcelVoiceInfoRequest
+
+
+
+ ParcelVoiceInfo
+
+ avatarnotesrequest
+
+
+ avatarclassifiedsrequest
+
+
+ avatarpickrequest
+
+
+ pickinforequest
+
+
+ ProvisionVoiceAccountRequest
+
+
+
+ RequiredVoiceVersion
+
+
+
capBans
messageBans
diff --git a/linden/indra/SConstruct b/linden/indra/SConstruct
index f988b1b..e90a7e6 100644
--- a/linden/indra/SConstruct
+++ b/linden/indra/SConstruct
@@ -10,7 +10,7 @@
# installed, with headers. We pick up the correct flags to use for
# these libraries using the "pkg-config" command.
#
-# cairo glib-2.0 gtk+-2.0 sdl vorbis vorbisenc vorbisfile
+# cairo glib-2.0 atk gmobile-2.0 gdk-2.0 gdk-pixbuf-2.0 pango pangoft2 pangox pangoxft gtk+-2.0 sdl vorbis vorbisenc vorbisfile
#
# Then build as follows:
#
@@ -99,6 +99,7 @@ opts.AddOptions(
BoolOption('DISTCC', 'Enabled distcc', True),
BoolOption('MOZLIB', 'Enabled llmozlib/mozilla support', True),
BoolOption('FMOD', 'Enabled FMOD audio support', True),
+ BoolOption('GSTREAMER', 'Enabled GStreamer support', True),
BoolOption('COLORGCC', 'Enabled colorgcc', True),
EnumOption('GRID', 'Client package\'s default grid', 'default',
allowed_values=('default', 'aditi', 'agni', 'dmz', 'durga', 'firstlook', 'ganga', 'shakti', 'siva', 'soma', 'uma', 'vaak')),
@@ -114,6 +115,7 @@ arch = optenv['ARCH']
target_param = optenv['BTARGET']
enable_distcc = optenv['DISTCC']
enable_mozlib = optenv['MOZLIB']
+enable_gstreamer = optenv['GSTREAMER']
enable_colorgcc = optenv['COLORGCC']
grid = optenv['GRID']
standalone = optenv['STANDALONE']
@@ -133,14 +135,35 @@ duplicate = True
if standalone and platform != 'linux':
print >> sys.stderr, 'Warning: standalone builds have only been tested on Linux'
-standalone_pkgs = 'cairo glib-2.0 gtk+-2.0 sdl vorbis vorbisenc vorbisfile'
+standalone_pkgs = [
+ 'apr-1',
+ 'apr-util-1',
+ 'atk',
+ 'cairo',
+ 'freetype2',
+ 'gdk-2.0',
+ 'gdk-pixbuf-2.0',
+ 'glib-2.0',
+ 'gmodule-2.0',
+ 'gtk+-2.0',
+ 'libcurl',
+ 'libpng',
+ 'pango',
+ 'pangoft2',
+ 'pangox',
+ 'pangoxft',
+ 'sdl',
+ 'vorbis',
+ 'vorbisenc',
+ 'vorbisfile',
+ ]
def pkgconfig(opt, pkgs=None):
return os.popen('pkg-config %s %s' %
- (opt, pkgs or standalone_pkgs)).read().strip()
+ (opt, pkgs or ' '.join(standalone_pkgs))).read().strip()
if standalone:
- missing = [pkg for pkg in standalone_pkgs.split()
+ missing = [pkg for pkg in standalone_pkgs
if os.system('pkg-config --exists ' + pkg)]
if missing:
print >> sys.stderr, ('Error: pkg-config cannot find these '
@@ -194,7 +217,10 @@ for build_target in targets:
if arch == 'x86_64' and os.path.exists('/usr/lib64'):
client_external_libs = [File('/usr/lib64/libresolv.a')]
else:
- client_external_libs = ['llresolv6']
+ # Custom libresolv build which avoids a billion flavors of
+ # brokenness prevalent in common libresolvs out there.
+ client_external_libs = ['resolv']
+ include_dirs += ['../libraries/' + system_str + '/include/llresolv8']
else:
client_external_libs = ['resolv']
@@ -230,7 +256,9 @@ for build_target in targets:
# Generic GCC flags
cflags = '-g -pipe -Wall -Wno-trigraphs -Wno-sign-compare -Werror '
cxxflags = ''
- cppflags = ''
+ cppflags = '-D_FORTIFY_SOURCE=2 '
+ if standalone:
+ cppflags += '-DLL_STANDALONE '
if build_target == 'server':
# Server flags
@@ -255,6 +283,7 @@ for build_target in targets:
client_cppflags = ''
cppflags += client_cppflags + ' '
+
if platform == 'linux':
# Linux-only flags
cppflags += '-DLL_LINUX=1 '
@@ -267,14 +296,14 @@ for build_target in targets:
include_dirs += [d[2:] for d in
pkgconfig('--cflags-only-I').split()]
else:
- client_external_libs += [ 'gtk-x11-2.0' ]
+ client_external_libs += [ 'gtk-x11-2.0', 'atk-1.0', 'gmodule-2.0', 'gdk-x11-2.0', 'gdk_pixbuf-2.0', 'pango-1.0', 'pangoft2-1.0', 'pangox-1.0', 'pangoxft-1.0', 'Xinerama' ]
incdirs = [ 'ELFIO', 'atk-1.0', 'glib-2.0', 'gtk-2.0',
'llfreetype2', 'pango-1.0' ]
include_dirs += ['../libraries/' + system_str + '/include/' + d
for d in incdirs]
if elfio:
- client_external_libs += [ 'elfio' ]
+ client_external_libs += [ 'ELFIO' ]
else:
cppflags += '-DLL_ELFBIN=0 '
@@ -285,6 +314,17 @@ for build_target in targets:
client_external_libs += [ 'mozjs', 'nspr4', 'plc4', 'plds4', 'profdirserviceprovider_s', 'xpcom', 'xul' ]
else:
cppflags += '-DLL_LIBXUL_ENABLED=0 '
+
+ # GStreamer stuff
+ if enable_gstreamer:
+ cppflags += '-DLL_GSTREAMER_ENABLED=1 '
+ client_external_libs += [ 'glib-2.0', 'gobject-2.0' ]
+ #client_external_libs += [ 'gstreamer-0.10', 'gstvideo-0.10', 'gstaudio-0.10' ]
+ include_dirs += [ '../libraries/' + system_str + '/include/gstreamer-0.10' ]
+ include_dirs += [ '../libraries/' + system_str + '/include/glib-2.0', '../libraries/' + system_str + '/include/glib-2.0/include' ]
+ include_dirs += [ '../libraries/' + system_str + '/include/libxml2']
+ else:
+ cppflags += '-DLL_GSTREAMER_ENABLED=0 '
else:
# Mac-only flags
cflags += '-x c++ -arch ppc -pipe -Wno-trigraphs -fpascal-strings -faltivec -fasm-blocks -g -fmessage-length=0 -mtune=G4 -Wno-deprecated-declarations -Wno-invalid-offsetof -mmacosx-version-min=10.3 -Wmost -Wno-sign-compare -Wno-switch -fconstant-cfstrings -ffor-scope -Wno-reorder '
@@ -392,6 +432,18 @@ for build_target in targets:
env_no_distcc = env.Copy(CXX = compiler_no_distcc)
+ vec_match = re.compile("_vec\.")
+ env_vec = env.Copy() # _vec is for default vector optimizations or none
+
+ sse_match = re.compile("_sse\.")
+ env_sse = env.Copy()
+ env_sse.Append(CPPFLAGS = ' -msse -mfpmath=sse')
+
+ sse2_match = re.compile("_sse2\.")
+ env_sse2 = env.Copy()
+ env_sse2.Append(CPPFLAGS = ' -msse2 -mfpmath=sse')
+
+
### Distributed build hosts ###
if enable_distcc:
@@ -419,6 +471,21 @@ for build_target in targets:
# HELPER FUNCTIONS #
#####################
+ ## handle special compiler modes
+
+ def file_obj(file):
+ if file == 'newsim/lltask.cpp':
+ print 'Found lltask!'
+ return env_no_distcc.Object(file)
+ elif vec_match.search(file) != None:
+ return env_vec.Object(file)
+ elif sse_match.search(file) != None:
+ return env_sse.Object(file)
+ elif sse2_match.search(file) != None:
+ return env_sse2.Object(file)
+ else:
+ return file
+
### Load a files.lst and files.PLATFORM.lst for each module ###
def load_files(module, source_fname):
@@ -429,12 +496,7 @@ for build_target in targets:
for x in list:
if not x.startswith('#'):
file = os.path.join(build_dir, x)
- if x == 'newsim/lltask.cpp':
- print 'Found lltask!'
- obj = env_no_distcc.Object(file)
- new_list.append(obj)
- else:
- new_list.append(file)
+ new_list.append(file_obj(file))
list_file.close()
except IOError, val:
print 'Error: unable to open file list',source_fname,
@@ -446,7 +508,7 @@ for build_target in targets:
list = Split(platform_list_file.read())
for x in list:
file = os.path.join(build_dir, x)
- new_list.append(file)
+ new_list.append(file_obj(file))
platform_list_file.close()
except IOError:
return new_list
@@ -460,18 +522,22 @@ for build_target in targets:
mod_name,
local_flags="",
source_files = 'files.lst',
- extra_depends=None):
+ extra_depends=None,
+ source_env=env):
files_list = load_files(input_dir, source_files)
BuildDir(build_dir + '/' + input_dir, input_dir, duplicate=duplicate)
- local_env = env.Copy(CPPFLAGS = env['CPPFLAGS'] + ' ' + local_flags)
+ local_env = source_env.Copy(CPPFLAGS=env['CPPFLAGS'] + ' ' + local_flags)
if extra_depends:
for x in files_list:
Depends(local_env.Object(x), extra_depends)
tgt = local_env.StaticLibrary(lib_dir + '/' + mod_name, files_list)
Default(tgt)
- def create_static_module(module, local_flags="", source_files = 'files.lst', extra_depends=None):
- create_static_module_from_dir(module, module, local_flags, source_files, extra_depends)
+ def create_static_module(module, local_flags="", source_env=env,
+ source_files='files.lst', extra_depends=None):
+ create_static_module_from_dir(module, module, local_flags,
+ source_files, extra_depends,
+ source_env=source_env)
def create_dynamic_module(
module,
@@ -484,11 +550,16 @@ for build_target in targets:
tgt = local_env.SharedLibrary(lib_dir + '/' + module, files_list, LIBS = module_libs)
Default(tgt)
+ # Some libraries need to be built using PIC so that they can be
+ # linked into libllkdu.so. If we're not building libllkdu.so, we
+ # don't need to add the PIC flag.
def create_cond_module(module, module_libs=[]):
- if build_target != 'client' or not opensource:
- create_static_module(module=module)
+ if build_target == 'client' and not opensource:
+ shared_env = env.Copy(CFLAGS=env['CFLAGS'] + '-fpic ',
+ CXXFLAGS=env['CXXFLAGS'] + '-fpic ')
+ create_static_module(module=module, source_env=shared_env)
else:
- create_dynamic_module(module=module, module_libs=module_libs)
+ create_static_module(module=module, source_env=env)
### Create an executable from the module ###
@@ -503,7 +574,7 @@ for build_target in targets:
### Check the message template for compatibility with the base ###
tgt = env.Command("template_verifier_output",
'../scripts/template_verifier.py',
- 'python $SOURCE --mode="development" 2>&1')
+ 'python $SOURCE --mode="development" --cache_master 2>&1')
Default(tgt)
AlwaysBuild(tgt)
@@ -539,7 +610,7 @@ for build_target in targets:
#############################
output_crashlogger_bin = 'linux_crash_logger/linux-crash-logger-' + arch + '-bin'
if standalone:
- external_libs = net_external_libs + [ 'db' ]
+ external_libs = net_external_libs
external_libs += [d[2:] for d in
pkgconfig('--libs-only-l', 'gtk+-2.0').split()]
else:
@@ -566,7 +637,6 @@ for build_target in targets:
external_libs = client_external_libs + common_external_libs
if standalone:
- external_libs += [ 'db' ]
external_libs += [ d[2:] for d in
pkgconfig('--libs-only-l').split() ]
else:
@@ -654,15 +724,13 @@ for build_target in targets:
internal_libs + external_libs)
# Dataserver
- Depends('dataserver/dataserver', 'launcher/launcher' + file_suffix)
- external_libs = common_external_libs + ['boost_regex-gcc-mt', 'mysqlclient', 'tcmalloc', 'stacktrace']
+ external_libs = common_external_libs + ['boost_regex-gcc-mt', 'mysqlclient']
internal_libs = [ 'llcharacter', 'lldatabase', 'llimage', 'llimagej2coj', 'llinventory',
'llscene', 'llmessage', 'llvfs', 'llxml', 'llcommon', 'llmath' ]
create_executable('dataserver/dataserver' + file_suffix, 'dataserver',
internal_libs + external_libs)
# Spaceserver
- Depends('newspace/spaceserver', 'dataserver/dataserver' + file_suffix)
external_libs = common_external_libs + ['mysqlclient']
internal_libs = ['llscene', 'lldatabase', 'llmessage', 'llvfs',
'llmath', 'llcommon']
@@ -670,7 +738,6 @@ for build_target in targets:
internal_libs + external_libs)
# Rpcserver
- Depends('rpcserver/rpcserver', 'newspace/spaceserver' + file_suffix)
external_libs = common_external_libs + ['xmlrpc', 'mysqlclient']
internal_libs = ['llscene', 'llmessage', 'lldatabase', 'llvfs',
'llmath', 'llcommon']
@@ -678,7 +745,6 @@ for build_target in targets:
internal_libs + external_libs)
# Mapserver
- Depends('mapserver/mapserver', 'rpcserver/rpcserver' + file_suffix)
external_libs = common_external_libs + ['OSMesa16', 'kdu',
'boost_regex-gcc-mt', 'iconv', 'jpeg', 'openjpeg', 'GL',
'mysqlclient', 'pthread', 'dl']
@@ -688,8 +754,7 @@ for build_target in targets:
internal_libs + external_libs)
# Simulator
- Depends('newsim/simulator' + file_suffix, 'mapserver/mapserver' + file_suffix)
- external_libs = common_external_libs + ['hkdynamics', 'hkgeometry', 'hkmath', 'hkbase', 'hkcollide', 'hkactions', 'boost_regex-gcc-mt', 'openjpeg', 'dl', 'kdu', 'mysqlclient', 'iconv', 'tcmalloc', 'stacktrace']
+ external_libs = common_external_libs + ['hkdynamics', 'hkgeometry', 'hkmath', 'hkbase', 'hkcollide', 'hkactions', 'boost_regex-gcc-mt', 'openjpeg', 'dl', 'kdu', 'mysqlclient', 'iconv']
internal_libs = [ 'lscript', 'llprimitive',
'llscene', 'llhavok', 'llinventory', 'llimage', 'llimagej2coj',
'llcharacter', 'llxml', 'lldatabase', 'llkdustatic',
diff --git a/linden/indra/indra_complete/indra_complete.sln b/linden/indra/indra_complete/indra_complete.sln
index 24495ff..76346f9 100644
--- a/linden/indra/indra_complete/indra_complete.sln
+++ b/linden/indra/indra_complete/indra_complete.sln
@@ -141,12 +141,14 @@ EndProject
ProjectSection(ProjectDependencies) = postProject
{7BCB4B2C-8378-4186-88EA-5742B5ABE17F} = {7BCB4B2C-8378-4186-88EA-5742B5ABE17F}
{44CE6D82-7320-4609-8FC3-5965C19F4808} = {44CE6D82-7320-4609-8FC3-5965C19F4808}
+ {BFA102B0-C891-4E13-B1CF-C2F28073DA8E} = {BFA102B0-C891-4E13-B1CF-C2F28073DA8E}
{E87FD9BE-BE42-4EA3-BF4D-D992223046D9} = {E87FD9BE-BE42-4EA3-BF4D-D992223046D9}
EndProjectSection
EndProject
ProjectSection(ProjectDependencies) = postProject
{7BCB4B2C-8378-4186-88EA-5742B5ABE17F} = {7BCB4B2C-8378-4186-88EA-5742B5ABE17F}
{F882263E-4F2A-43D9-A45A-FA4C8EC66552} = {F882263E-4F2A-43D9-A45A-FA4C8EC66552}
+ {BFA102B0-C891-4E13-B1CF-C2F28073DA8E} = {BFA102B0-C891-4E13-B1CF-C2F28073DA8E}
{E87FD9BE-BE42-4EA3-BF4D-D992223046D9} = {E87FD9BE-BE42-4EA3-BF4D-D992223046D9}
EndProjectSection
EndProject
@@ -254,6 +256,8 @@ Global
Debug = Debug
Release = Release
EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{7BCB4B2C-8378-4186-88EA-5742B5ABE17F}.Debug.ActiveCfg = Debug|Win32
{7BCB4B2C-8378-4186-88EA-5742B5ABE17F}.Debug.Build.0 = Debug|Win32
diff --git a/linden/indra/indra_complete/indra_complete_vc8.sln b/linden/indra/indra_complete/indra_complete_vc8.sln
index 9a35696..f6b4304 100644
--- a/linden/indra/indra_complete/indra_complete_vc8.sln
+++ b/linden/indra/indra_complete/indra_complete_vc8.sln
@@ -26,12 +26,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llinventory", "..\llinvento
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "newview", "..\newview\newview_vc8.vcproj", "{E6F4CF1B-6109-4CA8-B58D-87FA936CDE08}"
ProjectSection(ProjectDependencies) = postProject
+ {E928F33B-E090-4FA8-818B-6B5D8B0F1F4B} = {E928F33B-E090-4FA8-818B-6B5D8B0F1F4B}
{9D0C7E02-6506-4EE7-BC5C-75671D28D594} = {9D0C7E02-6506-4EE7-BC5C-75671D28D594}
{2ADE3C14-94C4-40BF-B033-70F3C954EE90} = {2ADE3C14-94C4-40BF-B033-70F3C954EE90}
{B5B53617-416F-404A-BF10-22EBCCA0E4FB} = {B5B53617-416F-404A-BF10-22EBCCA0E4FB}
{93B2BA29-FBE9-4376-92C1-6108DCFE09D3} = {93B2BA29-FBE9-4376-92C1-6108DCFE09D3}
{7BCB4B2C-8378-4186-88EA-5742B5ABE17F} = {7BCB4B2C-8378-4186-88EA-5742B5ABE17F}
- {E928F33B-E090-4FA8-818B-6B5D8B0F1F4B} = {E928F33B-E090-4FA8-818B-6B5D8B0F1F4B}
{FCC4483C-5B84-4944-B91F-4589A219BC0B} = {FCC4483C-5B84-4944-B91F-4589A219BC0B}
{F882263E-4F2A-43D9-A45A-FA4C8EC66552} = {F882263E-4F2A-43D9-A45A-FA4C8EC66552}
{076DD042-2E58-42EA-9401-53210B65C1FC} = {076DD042-2E58-42EA-9401-53210B65C1FC}
diff --git a/linden/indra/lib/python/indra/__init__.py b/linden/indra/lib/python/indra/__init__.py
index 7548558..220768f 100644
--- a/linden/indra/lib/python/indra/__init__.py
+++ b/linden/indra/lib/python/indra/__init__.py
@@ -1,8 +1,9 @@
-# @file __init__.py
-# @brief Initialization file for the indra module.
-#
-# Copyright (c) 2006-2007, Linden Research, Inc.
-#
+"""\
+@file __init__.py
+@brief Initialization file for the indra module.
+
+Copyright (c) 2006-2007, Linden Research, Inc.
+
# Second Life Viewer Source Code
# The source code in this file ("Source Code") is provided by Linden Lab
# to you under the terms of the GNU General Public License, version 2.0
@@ -23,3 +24,4 @@
# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
# COMPLETENESS OR PERFORMANCE.
+"""
diff --git a/linden/indra/lib/python/indra/compatibility.py b/linden/indra/lib/python/indra/compatibility.py
deleted file mode 100644
index abc1c6a..0000000
--- a/linden/indra/lib/python/indra/compatibility.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# @file compatibility.py
-# @brief Classes that manage compatibility states.
-#
-# Copyright (c) 2007-2007, Linden Research, Inc.
-#
-# Second Life Viewer Source Code
-# The source code in this file ("Source Code") is provided by Linden Lab
-# to you under the terms of the GNU General Public License, version 2.0
-# ("GPL"), unless you have obtained a separate licensing agreement
-# ("Other License"), formally executed by you and Linden Lab. Terms of
-# the GPL can be found in doc/GPL-license.txt in this distribution, or
-# online at http://secondlife.com/developers/opensource/gplv2
-#
-# There are special exceptions to the terms and conditions of the GPL as
-# it is applied to this Source Code. View the full text of the exception
-# in the file doc/FLOSS-exception.txt in this software distribution, or
-# online at http://secondlife.com/developers/opensource/flossexception
-#
-# By copying, modifying or distributing this software, you acknowledge
-# that you have read and understood your obligations described above,
-# and agree to abide by those obligations.
-#
-# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
-# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
-# COMPLETENESS OR PERFORMANCE.
-
-
-"""Compatibility combination table:
-
- I M O N S
- -- -- -- -- --
-I: I I I I I
-M: I M M M M
-O: I M O M O
-N: I M M N N
-S: I M O N S
-
-"""
-
-class _Compatibility(object):
- def __init__(self, reason):
- self.reasons = [ ]
- if reason:
- self.reasons.append(reason)
-
- def combine(self, other):
- if self._level() <= other._level():
- return self._buildclone(other)
- else:
- return other._buildclone(self)
-
- def prefix(self, leadin):
- self.reasons = [ leadin + r for r in self.reasons ]
-
- def same(self): return self._level() >= 1
- def deployable(self): return self._level() > 0
- def resolved(self): return self._level() > -1
- def compatible(self): return self._level() > -2
-
- def explain(self):
- return self.__class__.__name__ + "\n" + "\n".join(self.reasons) + "\n"
-
- def _buildclone(self, other=None):
- c = self._buildinstance()
- c.reasons = self.reasons
- if other:
- c.reasons = c.reasons + other.reasons
- return c
-
- def _buildinstance(self):
- return self.__class__(None)
-
-# def _level(self):
-# raise RuntimeError('implement in subclass')
-
-
-class Incompatible(_Compatibility):
- def _level(self):
- return -2
-
-class Mixed(_Compatibility):
- def __init__(self, *inputs):
- _Compatibility.__init__(self, None)
- for i in inputs:
- self.reasons += i.reasons
-
- def _buildinstance(self):
- return self.__class__()
-
- def _level(self):
- return -1
-
-class _Aged(_Compatibility):
- def combine(self, other):
- if self._level() == other._level():
- return self._buildclone(other)
- if int(self._level()) == int(other._level()):
- return Mixed(self, other)
- return _Compatibility.combine(self, other)
-
-class Older(_Aged):
- def _level(self):
- return -0.25
-
-class Newer(_Aged):
- def _level(self):
- return 0.25
-
-class Same(_Compatibility):
- def __init__(self):
- _Compatibility.__init__(self, None)
-
- def _buildinstance(self):
- return self.__class__()
-
- def _level(self):
- return 1
-
-
-
-
diff --git a/linden/indra/lib/python/indra/ipc/__init__.py b/linden/indra/lib/python/indra/ipc/__init__.py
new file mode 100644
index 0000000..92c9416
--- /dev/null
+++ b/linden/indra/lib/python/indra/ipc/__init__.py
@@ -0,0 +1,27 @@
+"""\
+@file __init__.py
+@brief Initialization file for the indra ipc module.
+
+Copyright (c) 2006-2007, Linden Research, Inc.
+
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlife.com/developers/opensource/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at http://secondlife.com/developers/opensource/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+"""
diff --git a/linden/indra/lib/python/indra/ipc/compatibility.py b/linden/indra/lib/python/indra/ipc/compatibility.py
new file mode 100644
index 0000000..358820c
--- /dev/null
+++ b/linden/indra/lib/python/indra/ipc/compatibility.py
@@ -0,0 +1,123 @@
+"""\
+@file compatibility.py
+@brief Classes that manage compatibility states.
+
+Copyright (c) 2007, Linden Research, Inc.
+
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlife.com/developers/opensource/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at http://secondlife.com/developers/opensource/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+"""
+
+
+"""Compatibility combination table:
+
+ I M O N S
+ -- -- -- -- --
+I: I I I I I
+M: I M M M M
+O: I M O M O
+N: I M M N N
+S: I M O N S
+
+"""
+
+class _Compatibility(object):
+ def __init__(self, reason):
+ self.reasons = [ ]
+ if reason:
+ self.reasons.append(reason)
+
+ def combine(self, other):
+ if self._level() <= other._level():
+ return self._buildclone(other)
+ else:
+ return other._buildclone(self)
+
+ def prefix(self, leadin):
+ self.reasons = [ leadin + r for r in self.reasons ]
+
+ def same(self): return self._level() >= 1
+ def deployable(self): return self._level() > 0
+ def resolved(self): return self._level() > -1
+ def compatible(self): return self._level() > -2
+
+ def explain(self):
+ return self.__class__.__name__ + "\n" + "\n".join(self.reasons) + "\n"
+
+ def _buildclone(self, other=None):
+ c = self._buildinstance()
+ c.reasons = self.reasons
+ if other:
+ c.reasons = c.reasons + other.reasons
+ return c
+
+ def _buildinstance(self):
+ return self.__class__(None)
+
+# def _level(self):
+# raise RuntimeError('implement in subclass')
+
+
+class Incompatible(_Compatibility):
+ def _level(self):
+ return -2
+
+class Mixed(_Compatibility):
+ def __init__(self, *inputs):
+ _Compatibility.__init__(self, None)
+ for i in inputs:
+ self.reasons += i.reasons
+
+ def _buildinstance(self):
+ return self.__class__()
+
+ def _level(self):
+ return -1
+
+class _Aged(_Compatibility):
+ def combine(self, other):
+ if self._level() == other._level():
+ return self._buildclone(other)
+ if int(self._level()) == int(other._level()):
+ return Mixed(self, other)
+ return _Compatibility.combine(self, other)
+
+class Older(_Aged):
+ def _level(self):
+ return -0.25
+
+class Newer(_Aged):
+ def _level(self):
+ return 0.25
+
+class Same(_Compatibility):
+ def __init__(self):
+ _Compatibility.__init__(self, None)
+
+ def _buildinstance(self):
+ return self.__class__()
+
+ def _level(self):
+ return 1
+
+
+
+
diff --git a/linden/indra/lib/python/indra/ipc/llmessage.py b/linden/indra/lib/python/indra/ipc/llmessage.py
new file mode 100644
index 0000000..de6fd3b
--- /dev/null
+++ b/linden/indra/lib/python/indra/ipc/llmessage.py
@@ -0,0 +1,373 @@
+"""\
+@file llmessage.py
+@brief Message template parsing and compatiblity
+
+Copyright (c) 2007, Linden Research, Inc.
+
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlife.com/developers/opensource/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at http://secondlife.com/developers/opensource/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+"""
+
+from sets import Set, ImmutableSet
+
+from compatibility import Incompatible, Older, Newer, Same
+from tokenstream import TokenStream
+
+###
+### Message Template
+###
+
+class Template:
+ def __init__(self):
+ self.messages = { }
+
+ def addMessage(self, m):
+ self.messages[m.name] = m
+
+ def compatibleWithBase(self, base):
+ messagenames = (
+ ImmutableSet(self.messages.keys())
+ | ImmutableSet(base.messages.keys())
+ )
+
+ compatibility = Same()
+ for name in messagenames:
+ selfmessage = self.messages.get(name, None)
+ basemessage = base.messages.get(name, None)
+
+ if not selfmessage:
+ c = Older("missing message %s, did you mean to deprecate?" % name)
+ elif not basemessage:
+ c = Newer("added message %s" % name)
+ else:
+ c = selfmessage.compatibleWithBase(basemessage)
+ c.prefix("in message %s: " % name)
+
+ compatibility = compatibility.combine(c)
+
+ return compatibility
+
+
+
+class Message:
+ HIGH = "High"
+ MEDIUM = "Medium"
+ LOW = "Low"
+ FIXED = "Fixed"
+ priorities = [ HIGH, MEDIUM, LOW, FIXED ]
+ prioritieswithnumber = [ FIXED ]
+
+ TRUSTED = "Trusted"
+ NOTTRUSTED = "NotTrusted"
+ trusts = [ TRUSTED, NOTTRUSTED ]
+
+ UNENCODED = "Unencoded"
+ ZEROCODED = "Zerocoded"
+ encodings = [ UNENCODED, ZEROCODED ]
+
+ NOTDEPRECATED = "NotDeprecated"
+ DEPRECATED = "Deprecated"
+ UDPDEPRECATED = "UDPDeprecated"
+ deprecations = [ NOTDEPRECATED, UDPDEPRECATED, DEPRECATED ]
+ # in order of increasing deprecation
+
+ def __init__(self, name, number, priority, trust, coding):
+ self.name = name
+ self.number = number
+ self.priority = priority
+ self.trust = trust
+ self.coding = coding
+ self.deprecateLevel = 0
+ self.blocks = [ ]
+
+ def deprecated(self):
+ return self.deprecateLevel != 0
+
+ def deprecate(self, deprecation):
+ self.deprecateLevel = self.deprecations.index(deprecation)
+
+ def addBlock(self, block):
+ self.blocks.append(block)
+
+ def compatibleWithBase(self, base):
+ if self.name != base.name:
+ # this should never happen in real life because of the
+ # way Template matches up messages by name
+ return Incompatible("has different name: %s vs. %s in base"
+ % (self.name, base.name))
+ if self.priority != base.priority:
+ return Incompatible("has different priority: %s vs. %s in base"
+ % (self.priority, base.priority))
+ if self.trust != base.trust:
+ return Incompatible("has different trust: %s vs. %s in base"
+ % (self.trust, base.trust))
+ if self.coding != base.coding:
+ return Incompatible("has different coding: %s vs. %s in base"
+ % (self.coding, base.coding))
+ if self.number != base.number:
+ return Incompatible("has different number: %s vs. %s in base"
+ % (self.number, base.number))
+
+ compatibility = Same()
+
+ if self.deprecateLevel != base.deprecateLevel:
+ if self.deprecateLevel < base.deprecateLevel:
+ c = Older("is less deprecated: %s vs. %s in base" % (
+ self.deprecations[self.deprecateLevel],
+ self.deprecations[base.deprecateLevel]))
+ else:
+ c = Newer("is more deprecated: %s vs. %s in base" % (
+ self.deprecations[self.deprecateLevel],
+ self.deprecations[base.deprecateLevel]))
+ compatibility = compatibility.combine(c)
+
+ selflen = len(self.blocks)
+ baselen = len(base.blocks)
+ samelen = min(selflen, baselen)
+
+ for i in xrange(0, samelen):
+ selfblock = self.blocks[i]
+ baseblock = base.blocks[i]
+
+ c = selfblock.compatibleWithBase(baseblock)
+ if not c.same():
+ c = Incompatible("block %d isn't identical" % i)
+ compatibility = compatibility.combine(c)
+
+ if selflen > baselen:
+ c = Newer("has %d extra blocks" % (selflen - baselen))
+ elif selflen < baselen:
+ c = Older("missing %d extra blocks" % (baselen - selflen))
+ else:
+ c = Same()
+
+ compatibility = compatibility.combine(c)
+ return compatibility
+
+
+
+class Block(object):
+ SINGLE = "Single"
+ MULTIPLE = "Multiple"
+ VARIABLE = "Variable"
+ repeats = [ SINGLE, MULTIPLE, VARIABLE ]
+ repeatswithcount = [ MULTIPLE ]
+
+ def __init__(self, name, repeat, count=None):
+ self.name = name
+ self.repeat = repeat
+ self.count = count
+ self.variables = [ ]
+
+ def addVariable(self, variable):
+ self.variables.append(variable)
+
+ def compatibleWithBase(self, base):
+ if self.name != base.name:
+ return Incompatible("has different name: %s vs. %s in base"
+ % (self.name, base.name))
+ if self.repeat != base.repeat:
+ return Incompatible("has different repeat: %s vs. %s in base"
+ % (self.repeat, base.repeat))
+ if self.repeat in Block.repeatswithcount:
+ if self.count != base.count:
+ return Incompatible("has different count: %s vs. %s in base"
+ % (self.count, base.count))
+
+ compatibility = Same()
+
+ selflen = len(self.variables)
+ baselen = len(base.variables)
+
+ for i in xrange(0, min(selflen, baselen)):
+ selfvar = self.variables[i]
+ basevar = base.variables[i]
+
+ c = selfvar.compatibleWithBase(basevar)
+ if not c.same():
+ c = Incompatible("variable %d isn't identical" % i)
+ compatibility = compatibility.combine(c)
+
+ if selflen > baselen:
+ c = Newer("has %d extra variables" % (selflen - baselen))
+ elif selflen < baselen:
+ c = Older("missing %d extra variables" % (baselen - selflen))
+ else:
+ c = Same()
+
+ compatibility = compatibility.combine(c)
+ return compatibility
+
+
+
+class Variable:
+ U8 = "U8"; U16 = "U16"; U32 = "U32"; U64 = "U64"
+ S8 = "S8"; S16 = "S16"; S32 = "S32"; S64 = "S64"
+ F32 = "F32"; F64 = "F64"
+ LLVECTOR3 = "LLVector3"; LLVECTOR3D = "LLVector3d"; LLVECTOR4 = "LLVector4"
+ LLQUATERNION = "LLQuaternion"
+ LLUUID = "LLUUID"
+ BOOL = "BOOL"
+ IPADDR = "IPADDR"; IPPORT = "IPPORT"
+ FIXED = "Fixed"
+ VARIABLE = "Variable"
+ types = [ U8, U16, U32, U64, S8, S16, S32, S64, F32, F64,
+ LLVECTOR3, LLVECTOR3D, LLVECTOR4, LLQUATERNION,
+ LLUUID, BOOL, IPADDR, IPPORT, FIXED, VARIABLE ]
+ typeswithsize = [ FIXED, VARIABLE ]
+
+ def __init__(self, name, type, size):
+ self.name = name
+ self.type = type
+ self.size = size
+
+ def compatibleWithBase(self, base):
+ if self.name != base.name:
+ return Incompatible("has different name: %s vs. %s in base"
+ % (self.name, base.name))
+ if self.type != base.type:
+ return Incompatible("has different type: %s vs. %s in base"
+ % (self.type, base.type))
+ if self.type in Variable.typeswithsize:
+ if self.size != base.size:
+ return Incompatible("has different size: %s vs. %s in base"
+ % (self.size, base.size))
+ return Same()
+
+
+
+###
+### Parsing Message Templates
+###
+
+class TemplateParser:
+ def __init__(self, tokens):
+ self._tokens = tokens
+ self._version = 0
+ self._numbers = { }
+ for p in Message.priorities:
+ self._numbers[p] = 0
+
+ def parseTemplate(self):
+ tokens = self._tokens
+ t = Template()
+ while True:
+ if tokens.want("version"):
+ v = float(tokens.require(tokens.wantFloat()))
+ self._version = v
+ t.version = v
+ continue
+
+ m = self.parseMessage()
+ if m:
+ t.addMessage(m)
+ continue
+
+ if self._version >= 2.0:
+ tokens.require(tokens.wantEOF())
+ break
+ else:
+ if tokens.wantEOF():
+ break
+
+ tokens.consume()
+ # just assume (gulp) that this is a comment
+ # line 468: "sim -> dataserver"
+ return t
+
+
+ def parseMessage(self):
+ tokens = self._tokens
+ if not tokens.want("{"):
+ return None
+
+ name = tokens.require(tokens.wantSymbol())
+ priority = tokens.require(tokens.wantOneOf(Message.priorities))
+
+ if self._version >= 2.0 or priority in Message.prioritieswithnumber:
+ number = int("+" + tokens.require(tokens.wantInteger()), 0)
+ else:
+ self._numbers[priority] += 1
+ number = self._numbers[priority]
+
+ trust = tokens.require(tokens.wantOneOf(Message.trusts))
+ coding = tokens.require(tokens.wantOneOf(Message.encodings))
+
+ m = Message(name, number, priority, trust, coding)
+
+ if self._version >= 2.0:
+ d = tokens.wantOneOf(Message.deprecations)
+ if d:
+ m.deprecate(d)
+
+ while True:
+ b = self.parseBlock()
+ if not b:
+ break
+ m.addBlock(b)
+
+ tokens.require(tokens.want("}"))
+
+ return m
+
+
+ def parseBlock(self):
+ tokens = self._tokens
+ if not tokens.want("{"):
+ return None
+ name = tokens.require(tokens.wantSymbol())
+ repeat = tokens.require(tokens.wantOneOf(Block.repeats))
+ if repeat in Block.repeatswithcount:
+ count = int(tokens.require(tokens.wantInteger()))
+ else:
+ count = None
+
+ b = Block(name, repeat, count)
+
+ while True:
+ v = self.parseVariable()
+ if not v:
+ break
+ b.addVariable(v)
+
+ tokens.require(tokens.want("}"))
+ return b
+
+
+ def parseVariable(self):
+ tokens = self._tokens
+ if not tokens.want("{"):
+ return None
+ name = tokens.require(tokens.wantSymbol())
+ type = tokens.require(tokens.wantOneOf(Variable.types))
+ if type in Variable.typeswithsize:
+ size = tokens.require(tokens.wantInteger())
+ else:
+ tokens.wantInteger() # in LandStatRequest: "{ ParcelLocalID S32 1 }"
+ size = None
+ tokens.require(tokens.want("}"))
+ return Variable(name, type, size)
+
+def parseTemplateString(s):
+ return TemplateParser(TokenStream().fromString(s)).parseTemplate()
+
+def parseTemplateFile(f):
+ return TemplateParser(TokenStream().fromFile(f)).parseTemplate()
diff --git a/linden/indra/lib/python/indra/ipc/tokenstream.py b/linden/indra/lib/python/indra/ipc/tokenstream.py
new file mode 100644
index 0000000..83b087a
--- /dev/null
+++ b/linden/indra/lib/python/indra/ipc/tokenstream.py
@@ -0,0 +1,154 @@
+"""\
+@file tokenstream.py
+@brief Message template parsing utility class
+
+Copyright (c) 2007, Linden Research, Inc.
+
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlife.com/developers/opensource/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at http://secondlife.com/developers/opensource/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+"""
+
+import re
+
+class _EOF(object):
+ pass
+
+EOF = _EOF()
+
+class _LineMarker(int):
+ pass
+
+_commentRE = re.compile(r'//.*')
+_symbolRE = re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*')
+_integerRE = re.compile(r'(0x[0-9A-Fa-f]+|0\d*|[1-9]\d*)')
+_floatRE = re.compile(r'\d+(\.\d*)?')
+
+
+class ParseError(Exception):
+ def __init__(self, stream, reason):
+ self.line = stream.line
+ self.context = stream._context()
+ self.reason = reason
+
+ def _contextString(self):
+ c = [ ]
+ for t in self.context:
+ if isinstance(t, _LineMarker):
+ break
+ c.append(t)
+ return " ".join(c)
+
+ def __str__(self):
+ return "line %d: %s @ ... %s" % (
+ self.line, self.reason, self._contextString())
+
+ def __nonzero__(self):
+ return False
+
+
+def _optionText(options):
+ n = len(options)
+ if n == 1:
+ return '"%s"' % options[0]
+ return '"' + '", "'.join(options[0:(n-1)]) + '" or "' + options[-1] + '"'
+
+
+class TokenStream(object):
+ def __init__(self):
+ self.line = 0
+ self.tokens = [ ]
+
+ def fromString(self, string):
+ return self.fromLines(string.split('\n'))
+
+ def fromFile(self, file):
+ return self.fromLines(file)
+
+ def fromLines(self, lines):
+ i = 0
+ for line in lines:
+ i += 1
+ self.tokens.append(_LineMarker(i))
+ self.tokens.extend(_commentRE.sub(" ", line).split())
+ self._consumeLines()
+ return self
+
+ def consume(self):
+ if not self.tokens:
+ return EOF
+ t = self.tokens.pop(0)
+ self._consumeLines()
+ return t
+
+ def _consumeLines(self):
+ while self.tokens and isinstance(self.tokens[0], _LineMarker):
+ self.line = self.tokens.pop(0)
+
+ def peek(self):
+ if not self.tokens:
+ return EOF
+ return self.tokens[0]
+
+ def want(self, t):
+ if t == self.peek():
+ return self.consume()
+ return ParseError(self, 'expected "%s"' % t)
+
+ def wantOneOf(self, options):
+ assert len(options)
+ if self.peek() in options:
+ return self.consume()
+ return ParseError(self, 'expected one of %s' % _optionText(options))
+
+ def wantEOF(self):
+ return self.want(EOF)
+
+ def wantRE(self, re, message=None):
+ t = self.peek()
+ if t != EOF:
+ m = re.match(t)
+ if m and m.end() == len(t):
+ return self.consume()
+ if not message:
+ message = "expected match for r'%s'" % re.pattern
+ return ParseError(self, message)
+
+ def wantSymbol(self):
+ return self.wantRE(_symbolRE, "expected symbol")
+
+ def wantInteger(self):
+ return self.wantRE(_integerRE, "expected integer")
+
+ def wantFloat(self):
+ return self.wantRE(_floatRE, "expected float")
+
+ def _context(self):
+ n = min(5, len(self.tokens))
+ return self.tokens[0:n]
+
+ def require(self, t):
+ if t:
+ return t
+ if isinstance(t, ParseError):
+ raise t
+ else:
+ raise ParseError(self, "unmet requirement")
+
diff --git a/linden/indra/lib/python/indra/llmanifest.py b/linden/indra/lib/python/indra/llmanifest.py
deleted file mode 100644
index 22483b4..0000000
--- a/linden/indra/lib/python/indra/llmanifest.py
+++ /dev/null
@@ -1,580 +0,0 @@
-#!/usr/bin/python
-# @file llmanifest.py
-# @author Ryan Williams
-# @brief Library for specifying operations on a set of files.
-#
-# Copyright (c) 2007-2007, Linden Research, Inc.
-#
-# Second Life Viewer Source Code
-# The source code in this file ("Source Code") is provided by Linden Lab
-# to you under the terms of the GNU General Public License, version 2.0
-# ("GPL"), unless you have obtained a separate licensing agreement
-# ("Other License"), formally executed by you and Linden Lab. Terms of
-# the GPL can be found in doc/GPL-license.txt in this distribution, or
-# online at http://secondlife.com/developers/opensource/gplv2
-#
-# There are special exceptions to the terms and conditions of the GPL as
-# it is applied to this Source Code. View the full text of the exception
-# in the file doc/FLOSS-exception.txt in this software distribution, or
-# online at http://secondlife.com/developers/opensource/flossexception
-#
-# By copying, modifying or distributing this software, you acknowledge
-# that you have read and understood your obligations described above,
-# and agree to abide by those obligations.
-#
-# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
-# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
-# COMPLETENESS OR PERFORMANCE.
-
-import commands
-import filecmp
-import fnmatch
-import getopt
-import glob
-import os
-import os.path
-import re
-import shutil
-import sys
-import tarfile
-
-def path_ancestors(path):
- path = os.path.normpath(path)
- result = []
- while len(path) > 0:
- result.append(path)
- path, sub = os.path.split(path)
- return result
-
-def proper_windows_path(path, current_platform = sys.platform):
- """ This function takes an absolute Windows or Cygwin path and
- returns a path appropriately formatted for the platform it's
- running on (as determined by sys.platform)"""
- path = path.strip()
- drive_letter = None
- rel = None
- match = re.match("/cygdrive/([a-z])/(.*)", path)
- if(not match):
- match = re.match('([a-zA-Z]):\\\(.*)', path)
- if(not match):
- return None # not an absolute path
- drive_letter = match.group(1)
- rel = match.group(2)
- if(current_platform == "cygwin"):
- return "/cygdrive/" + drive_letter.lower() + '/' + rel.replace('\\', '/')
- else:
- return drive_letter.upper() + ':\\' + rel.replace('/', '\\')
-
-def get_default_platform(dummy):
- return {'linux2':'linux',
- 'linux1':'linux',
- 'cygwin':'windows',
- 'win32':'windows',
- 'darwin':'darwin'
- }[sys.platform]
-
-def get_default_version(srctree):
- # look up llversion.h and parse out the version info
- paths = [os.path.join(srctree, x, 'llversion.h') for x in ['llcommon', '../llcommon', '../../indra/llcommon.h']]
- for p in paths:
- if os.path.exists(p):
- contents = open(p, 'r').read()
- major = re.search("LL_VERSION_MAJOR\s=\s([0-9]+)", contents).group(1)
- minor = re.search("LL_VERSION_MINOR\s=\s([0-9]+)", contents).group(1)
- patch = re.search("LL_VERSION_PATCH\s=\s([0-9]+)", contents).group(1)
- build = re.search("LL_VERSION_BUILD\s=\s([0-9]+)", contents).group(1)
- return major, minor, patch, build
-
-DEFAULT_CHANNEL = 'Second Life Release'
-
-ARGUMENTS=[
- dict(name='actions',
- description="""This argument specifies the actions that are to be taken when the
- script is run. The meaningful actions are currently:
- copy - copies the files specified by the manifest into the
- destination directory.
- package - bundles up the files in the destination directory into
- an installer for the current platform
- unpacked - bundles up the files in the destination directory into
- a simple tarball
- Example use: %(name)s --actions="copy unpacked" """,
- default="copy package"),
- dict(name='arch',
- description="""This argument is appended to the platform string for
- determining which manifest class to run.
- Example use: %(name)s --arch=i686
- On Linux this would try to use Linux_i686Manifest.""",
- default=""),
- dict(name='configuration',
- description="""The build configuration used. Only used on OS X for
- now, but it could be used for other platforms as well.""",
- default="Universal"),
- dict(name='grid',
- description="""Which grid the client will try to connect to. Even
- though it's not strictly a grid, 'firstlook' is also an acceptable
- value for this parameter.""",
- default=""),
- dict(name='channel',
- description="""The channel to use for updates.""",
- default=DEFAULT_CHANNEL),
- dict(name='installer_name',
- description=""" The name of the file that the installer should be
- packaged up into. Only used on Linux at the moment.""",
- default=None),
- dict(name='login_url',
- description="""The url that the login screen displays in the client.""",
- default=None),
- dict(name='platform',
- description="""The current platform, to be used for looking up which
- manifest class to run.""",
- default=get_default_platform),
- dict(name='version',
- description="""This specifies the version of Second Life that is
- being packaged up.""",
- default=get_default_version)
- ]
-
-def usage(srctree=""):
- nd = {'name':sys.argv[0]}
- print """Usage:
- %(name)s [options] [destdir]
- Options:
- """ % nd
- for arg in ARGUMENTS:
- default = arg['default']
- if hasattr(default, '__call__'):
- default = "(computed value) \"" + str(default(srctree)) + '"'
- elif default is not None:
- default = '"' + default + '"'
- print "\t--%s Default: %s\n\t%s\n" % (
- arg['name'],
- default,
- arg['description'] % nd)
-
-def main(argv=None, srctree='.', dsttree='./dst'):
- if(argv == None):
- argv = sys.argv
-
- option_names = [arg['name'] + '=' for arg in ARGUMENTS]
- option_names.append('help')
- options, remainder = getopt.getopt(argv[1:], "", option_names)
- if len(remainder) >= 1:
- dsttree = remainder[0]
-
- print "Source tree:", srctree
- print "Destination tree:", dsttree
-
- # convert options to a hash
- args = {}
- for opt in options:
- args[opt[0].replace("--", "")] = opt[1]
-
- # early out for help
- if args.has_key('help'):
- # *TODO: it is a huge hack to pass around the srctree like this
- usage(srctree)
- return
-
- # defaults
- for arg in ARGUMENTS:
- if not args.has_key(arg['name']):
- default = arg['default']
- if hasattr(default, '__call__'):
- default = default(srctree)
- if default is not None:
- args[arg['name']] = default
-
- # fix up version
- if args.has_key('version') and type(args['version']) == str:
- args['version'] = args['version'].split('.')
-
- # default and agni are default
- if args['grid'] in ['default', 'agni']:
- args['grid'] = ''
-
- if args.has_key('actions'):
- args['actions'] = args['actions'].split()
-
- # debugging
- for opt in args:
- print "Option:", opt, "=", args[opt]
-
- wm = LLManifest.for_platform(args['platform'], args.get('arch'))(srctree, dsttree, args)
- wm.do(*args['actions'])
- return 0
-
-class LLManifestRegistry(type):
- def __init__(cls, name, bases, dct):
- super(LLManifestRegistry, cls).__init__(name, bases, dct)
- match = re.match("(\w+)Manifest", name)
- if(match):
- cls.manifests[match.group(1).lower()] = cls
-
-class LLManifest(object):
- __metaclass__ = LLManifestRegistry
- manifests = {}
- def for_platform(self, platform, arch = None):
- if arch:
- platform = platform + '_' + arch
- return self.manifests[platform.lower()]
- for_platform = classmethod(for_platform)
-
- def __init__(self, srctree, dsttree, args):
- super(LLManifest, self).__init__()
- self.args = args
- self.file_list = []
- self.excludes = []
- self.actions = []
- self.src_prefix = [srctree]
- self.dst_prefix = [dsttree]
- self.created_paths = []
-
- def default_grid(self):
- return self.args.get('grid', None) == ''
- def default_channel(self):
- return self.args.get('channel', None) == DEFAULT_CHANNEL
-
- def construct(self):
- """ Meant to be overriden by LLManifest implementors with code that
- constructs the complete destination hierarchy."""
- pass # override this method
-
- def exclude(self, glob):
- """ Excludes all files that match the glob from being included
- in the file list by path()."""
- self.excludes.append(glob)
-
- def prefix(self, src='', dst=None):
- """ Pushes a prefix onto the stack. Until end_prefix is
- called, all relevant method calls (esp. to path()) will prefix
- paths with the entire prefix stack. Source and destination
- prefixes can be different, though if only one is provided they
- are both equal. To specify a no-op, use an empty string, not
- None."""
- if(dst == None):
- dst = src
- self.src_prefix.append(src)
- self.dst_prefix.append(dst)
- return True # so that you can wrap it in an if to get indentation
-
- def end_prefix(self, descr=None):
- """Pops a prefix off the stack. If given an argument, checks
- the argument against the top of the stack. If the argument
- matches neither the source or destination prefixes at the top
- of the stack, then misnesting must have occurred and an
- exception is raised."""
- # as an error-prevention mechanism, check the prefix and see if it matches the source or destination prefix. If not, improper nesting may have occurred.
- src = self.src_prefix.pop()
- dst = self.dst_prefix.pop()
- if descr and not(src == descr or dst == descr):
- raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'"
-
- def get_src_prefix(self):
- """ Returns the current source prefix."""
- return os.path.join(*self.src_prefix)
-
- def get_dst_prefix(self):
- """ Returns the current destination prefix."""
- return os.path.join(*self.dst_prefix)
-
- def src_path_of(self, relpath):
- """Returns the full path to a file or directory specified
- relative to the source directory."""
- return os.path.join(self.get_src_prefix(), relpath)
-
- def dst_path_of(self, relpath):
- """Returns the full path to a file or directory specified
- relative to the destination directory."""
- return os.path.join(self.get_dst_prefix(), relpath)
-
- def ensure_src_dir(self, reldir):
- """Construct the path for a directory relative to the
- source path, and ensures that it exists. Returns the
- full path."""
- path = os.path.join(self.get_src_prefix(), reldir)
- self.cmakedirs(path)
- return path
-
- def ensure_dst_dir(self, reldir):
- """Construct the path for a directory relative to the
- destination path, and ensures that it exists. Returns the
- full path."""
- path = os.path.join(self.get_dst_prefix(), reldir)
- self.cmakedirs(path)
- return path
-
- def run_command(self, command):
- """ Runs an external command, and returns the output. Raises
- an exception if the command reurns a nonzero status code. For
- debugging/informational purpoases, prints out the command's
- output as it is received."""
- print "Running command:", command
- fd = os.popen(command, 'r')
- lines = []
- while True:
- lines.append(fd.readline())
- if(lines[-1] == ''):
- break
- else:
- print lines[-1],
- output = ''.join(lines)
- status = fd.close()
- if(status):
- raise RuntimeError, "Command " + command + " returned non-zero status (" + str(status) + ")"
- return output
-
- def created_path(self, path):
- """ Declare that you've created a path in order to
- a) verify that you really have created it
- b) schedule it for cleanup"""
- if not os.path.exists(path):
- raise RuntimeError, "Should be something at path " + path
- self.created_paths.append(path)
-
- def put_in_file(self, contents, dst):
- # write contents as dst
- f = open(self.dst_path_of(dst), "wb")
- f.write(contents)
- f.close()
-
- def replace_in(self, src, dst=None, searchdict={}):
- if(dst == None):
- dst = src
- # read src
- f = open(self.src_path_of(src), "rbU")
- contents = f.read()
- f.close()
- # apply dict replacements
- for old, new in searchdict.iteritems():
- contents = contents.replace(old, new)
- self.put_in_file(contents, dst)
- self.created_paths.append(dst)
-
- def copy_action(self, src, dst):
- if(src and (os.path.exists(src) or os.path.islink(src))):
- # ensure that destination path exists
- self.cmakedirs(os.path.dirname(dst))
- self.created_paths.append(dst)
- if(not os.path.isdir(src)):
- self.ccopy(src,dst)
- else:
- # src is a dir
- self.ccopytree(src,dst)
- else:
- print "Doesn't exist:", src
-
- def package_action(self, src, dst):
- pass
-
- def copy_finish(self):
- pass
-
- def package_finish(self):
- pass
-
- def unpacked_finish(self):
- unpacked_file_name = "unpacked_%(plat)s_%(vers)s.tar" % {
- 'plat':self.args['platform'],
- 'vers':'_'.join(self.args['version'])}
- print "Creating unpacked file:", unpacked_file_name
- # could add a gz here but that doubles the time it takes to do this step
- tf = tarfile.open(self.src_path_of(unpacked_file_name), 'w:')
- # add the entire installation package, at the very top level
- tf.add(self.get_dst_prefix(), "")
- tf.close()
-
- def cleanup_finish(self):
- """ Delete paths that were specified to have been created by this script"""
- for c in self.created_paths:
- # *TODO is this gonna be useful?
- print "Cleaning up " + c
-
- def process_file(self, src, dst):
- if(self.includes(src, dst)):
-# print src, "=>", dst
- for action in self.actions:
- methodname = action + "_action"
- method = getattr(self, methodname, None)
- if method is not None:
- method(src, dst)
- self.file_list.append([src, dst])
- else:
- print "Excluding: ", src, dst
-
-
- def process_directory(self, src, dst):
- if(not self.includes(src, dst)):
- print "Excluding: ", src, dst
- return
- names = os.listdir(src)
- self.cmakedirs(dst)
- errors = []
- for name in names:
- srcname = os.path.join(src, name)
- dstname = os.path.join(dst, name)
- if os.path.isdir(srcname):
- self.process_directory(srcname, dstname)
- else:
- self.process_file(srcname, dstname)
-
-
-
- def includes(self, src, dst):
- if src:
- for excl in self.excludes:
- if fnmatch.fnmatch(src, excl):
- return False
- return True
-
- def remove(self, *paths):
- for path in paths:
- if(os.path.exists(path)):
- print "Removing path", path
- if(os.path.isdir(path)):
- shutil.rmtree(path)
- else:
- os.remove(path)
-
- def ccopy(self, src, dst):
- """ Copy a single file or symlink. Uses filecmp to skip copying for existing files."""
- if os.path.islink(src):
- linkto = os.readlink(src)
- if(os.path.islink(dst) or os.path.exists(dst)):
- os.remove(dst) # because symlinking over an existing link fails
- os.symlink(linkto, dst)
- else:
- # Don't recopy file if it's up-to-date.
- # If we seem to be not not overwriting files that have been
- # updated, set the last arg to False, but it will take longer.
- if(os.path.exists(dst) and filecmp.cmp(src, dst, True)):
- return
- # only copy if it's not excluded
- if(self.includes(src, dst)):
- shutil.copy2(src, dst)
-
- def ccopytree(self, src, dst):
- """Direct copy of shutil.copytree with the additional
- feature that the destination directory can exist. It
- is so dumb that Python doesn't come with this. Also it
- implements the excludes functionality."""
- if(not self.includes(src, dst)):
- return
- names = os.listdir(src)
- self.cmakedirs(dst)
- errors = []
- for name in names:
- srcname = os.path.join(src, name)
- dstname = os.path.join(dst, name)
- try:
- if os.path.isdir(srcname):
- self.ccopytree(srcname, dstname)
- else:
- self.ccopy(srcname, dstname)
- # XXX What about devices, sockets etc.?
- except (IOError, os.error), why:
- errors.append((srcname, dstname, why))
- if errors:
- raise RuntimeError, errors
-
-
- def cmakedirs(self, path):
- """Ensures that a directory exists, and doesn't throw an exception
- if you call it on an existing directory."""
-# print "making path: ", path
- path = os.path.normpath(path)
- self.created_paths.append(path)
- if not os.path.exists(path):
- os.makedirs(path)
-
- def find_existing_file(self, *list):
- for f in list:
- if(os.path.exists(f)):
- return f
- # didn't find it, return last item in list
- if len(list) > 0:
- return list[-1]
- else:
- return None
-
- def contents_of_tar(self, src_tar, dst_dir):
- """ Extracts the contents of the tarfile (specified
- relative to the source prefix) into the directory
- specified relative to the destination directory."""
- self.check_file_exists(src_tar)
- tf = tarfile.open(self.src_path_of(src_tar), 'r')
- for member in tf.getmembers():
- tf.extract(member, self.ensure_dst_dir(dst_dir))
- # TODO get actions working on these dudes, perhaps we should extract to a temporary directory and then process_directory on it?
- self.file_list.append([src_tar,
- self.dst_path_of(os.path.join(dst_dir,member.name))])
- tf.close()
-
-
- def wildcard_regex(self, src_glob, dst_glob):
- # print "regex_pair:", src_glob, dst_glob
- src_re = re.escape(src_glob)
- src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]+)')
- dst_temp = dst_glob
- i = 1
- while(dst_temp.count("*") > 0):
- dst_temp = dst_temp.replace('*', '\g<' + str(i) + '>', 1)
- i = i+1
- # print "regex_result:", src_re, dst_temp
- return re.compile(src_re), dst_temp
-
- def check_file_exists(self, path):
- if(not os.path.exists(path) and not os.path.islink(path)):
- raise RuntimeError("Path %s doesn't exist" % (
- os.path.normpath(os.path.join(os.getcwd(), path)),))
-
-
- wildcard_pattern = re.compile('\*')
- def expand_globs(self, src, dst):
- def fw_slash(str):
- return str.replace('\\', '/')
- def os_slash(str):
- return str.replace('/', os.path.sep)
- dst = fw_slash(dst)
- src = fw_slash(src)
- src_list = glob.glob(src)
- src_re, d_template = self.wildcard_regex(src, dst)
- for s in src_list:
- s = fw_slash(s)
- d = src_re.sub(d_template, s)
- #print "s:",s, "d_t", d_template, "dst", dst, "d", d
- yield os_slash(s), os_slash(d)
-
- def path(self, src, dst=None):
- print "Processing", src, "=>", dst
- if src == None:
- raise RuntimeError("No source file, dst is " + dst)
- if dst == None:
- dst = src
- dst = os.path.join(self.get_dst_prefix(), dst)
- src = os.path.join(self.get_src_prefix(), src)
-
- # expand globs
- if(self.wildcard_pattern.search(src)):
- for s,d in self.expand_globs(src, dst):
- self.process_file(s, d)
- else:
- # if we're specifying a single path (not a glob),
- # we should error out if it doesn't exist
- self.check_file_exists(src)
- # if it's a directory, recurse through it
- if(os.path.isdir(src)):
- self.process_directory(src, dst)
- else:
- self.process_file(src, dst)
-
-
- def do(self, *actions):
- self.actions = actions
- self.construct()
- # perform finish actions
- for action in self.actions:
- methodname = action + "_finish"
- method = getattr(self, methodname, None)
- if method is not None:
- method()
- return self.file_list
diff --git a/linden/indra/lib/python/indra/llmessage.py b/linden/indra/lib/python/indra/llmessage.py
deleted file mode 100644
index 1d4995d..0000000
--- a/linden/indra/lib/python/indra/llmessage.py
+++ /dev/null
@@ -1,375 +0,0 @@
-# @file llmessage.py
-# @brief Message template parsing and compatiblity
-#
-# Copyright (c) 2007-2007, Linden Research, Inc.
-#
-# Second Life Viewer Source Code
-# The source code in this file ("Source Code") is provided by Linden Lab
-# to you under the terms of the GNU General Public License, version 2.0
-# ("GPL"), unless you have obtained a separate licensing agreement
-# ("Other License"), formally executed by you and Linden Lab. Terms of
-# the GPL can be found in doc/GPL-license.txt in this distribution, or
-# online at http://secondlife.com/developers/opensource/gplv2
-#
-# There are special exceptions to the terms and conditions of the GPL as
-# it is applied to this Source Code. View the full text of the exception
-# in the file doc/FLOSS-exception.txt in this software distribution, or
-# online at http://secondlife.com/developers/opensource/flossexception
-#
-# By copying, modifying or distributing this software, you acknowledge
-# that you have read and understood your obligations described above,
-# and agree to abide by those obligations.
-#
-# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
-# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
-# COMPLETENESS OR PERFORMANCE.
-
-from sets import Set, ImmutableSet
-
-from compatibility import Incompatible, Older, Newer, Same
-from tokenstream import TokenStream
-
-###
-### Message Template
-###
-
-class Template:
- def __init__(self):
- self.messages = { }
-
- def addMessage(self, m):
- self.messages[m.name] = m
-
- def compatibleWithBase(self, base):
- messagenames = (
- ImmutableSet(self.messages.keys())
- | ImmutableSet(base.messages.keys())
- )
-
- compatibility = Same()
- for name in messagenames:
- selfmessage = self.messages.get(name, None)
- basemessage = base.messages.get(name, None)
-
- if not selfmessage:
- c = Older("missing message %s, did you mean to deprecate?" % name)
- elif not basemessage:
- c = Newer("added message %s" % name)
- else:
- c = selfmessage.compatibleWithBase(basemessage)
- c.prefix("in message %s: " % name)
-
- compatibility = compatibility.combine(c)
-
- return compatibility
-
-
-
-class Message:
- HIGH = "High"
- MEDIUM = "Medium"
- LOW = "Low"
- FIXED = "Fixed"
- priorities = [ HIGH, MEDIUM, LOW, FIXED ]
- prioritieswithnumber = [ FIXED ]
-
- TRUSTED = "Trusted"
- NOTTRUSTED = "NotTrusted"
- trusts = [ TRUSTED, NOTTRUSTED ]
-
- UNENCODED = "Unencoded"
- ZEROCODED = "Zerocoded"
- encodings = [ UNENCODED, ZEROCODED ]
-
- NOTDEPRECATED = "NotDeprecated"
- DEPRECATED = "Deprecated"
- UDPDEPRECATED = "UDPDeprecated"
- deprecations = [ NOTDEPRECATED, UDPDEPRECATED, DEPRECATED ]
- # in order of increasing deprecation
-
- def __init__(self, name, number, priority, trust, coding):
- self.name = name
- self.number = number
- self.priority = priority
- self.trust = trust
- self.coding = coding
- self.deprecateLevel = 0
- self.blocks = [ ]
-
- def deprecated(self):
- return self.deprecateLevel != 0
-
- def deprecate(self, deprecation):
- self.deprecateLevel = self.deprecations.index(deprecation)
-
- def addBlock(self, block):
- self.blocks.append(block)
-
- def compatibleWithBase(self, base):
- if self.name != base.name:
- # this should never happen in real life because of the
- # way Template matches up messages by name
- return Incompatible("has different name: %s vs. %s in base"
- % (self.name, base.name))
- if self.priority != base.priority:
- return Incompatible("has different priority: %s vs. %s in base"
- % (self.priority, base.priority))
- if self.trust != base.trust:
- return Incompatible("has different trust: %s vs. %s in base"
- % (self.trust, base.trust))
- if self.coding != base.coding:
- return Incompatible("has different coding: %s vs. %s in base"
- % (self.coding, base.coding))
- if self.number != base.number:
- return Incompatible("has different number: %s vs. %s in base"
- % (self.number, base.number))
-
- compatibility = Same()
-
- if self.deprecateLevel != base.deprecateLevel:
- if self.deprecateLevel < base.deprecateLevel:
- c = Older("is less deprecated: %s vs. %s in base" % (
- self.deprecations[self.deprecateLevel],
- self.deprecations[base.deprecateLevel]))
- else:
- c = Newer("is more deprecated: %s vs. %s in base" % (
- self.deprecations[self.deprecateLevel],
- self.deprecations[base.deprecateLevel]))
- compatibility = compatibility.combine(c)
-
- selflen = len(self.blocks)
- baselen = len(base.blocks)
- samelen = min(selflen, baselen)
-
- for i in xrange(0, samelen):
- selfblock = self.blocks[i]
- baseblock = base.blocks[i]
-
- c = selfblock.compatibleWithBase(baseblock)
- if not c.same():
- c = Incompatible("block %d isn't identical" % i)
- compatibility = compatibility.combine(c)
-
- if selflen > baselen:
- c = Newer("has %d extra blocks" % (selflen - baselen))
- elif selflen < baselen:
- c = Older("missing %d extra blocks" % (baselen - selflen))
- else:
- c = Same()
-
- compatibility = compatibility.combine(c)
- return compatibility
-
-
-
-class Block(object):
- SINGLE = "Single"
- MULTIPLE = "Multiple"
- VARIABLE = "Variable"
- repeats = [ SINGLE, MULTIPLE, VARIABLE ]
- repeatswithcount = [ MULTIPLE ]
-
- def __init__(self, name, repeat, count=None):
- self.name = name
- self.repeat = repeat
- self.count = count
- self.variables = [ ]
-
- def addVariable(self, variable):
- self.variables.append(variable)
-
- def compatibleWithBase(self, base):
- if self.name != base.name:
- return Incompatible("has different name: %s vs. %s in base"
- % (self.name, base.name))
- if self.repeat != base.repeat:
- return Incompatible("has different repeat: %s vs. %s in base"
- % (self.repeat, base.repeat))
- if self.repeat in Block.repeatswithcount:
- if self.count != base.count:
- return Incompatible("has different count: %s vs. %s in base"
- % (self.count, base.count))
-
- compatibility = Same()
-
- selflen = len(self.variables)
- baselen = len(base.variables)
-
- for i in xrange(0, min(selflen, baselen)):
- selfvar = self.variables[i]
- basevar = base.variables[i]
-
- c = selfvar.compatibleWithBase(basevar)
- if not c.same():
- c = Incompatible("variable %d isn't identical" % i)
- compatibility = compatibility.combine(c)
-
- if selflen > baselen:
- c = Newer("has %d extra variables" % (selflen - baselen))
- elif selflen < baselen:
- c = Older("missing %d extra variables" % (baselen - selflen))
- else:
- c = Same()
-
- compatibility = compatibility.combine(c)
- return compatibility
-
-
-
-class Variable:
- U8 = "U8"; U16 = "U16"; U32 = "U32"; U64 = "U64"
- S8 = "S8"; S16 = "S16"; S32 = "S32"; S64 = "S64"
- F32 = "F32"; F64 = "F64"
- LLVECTOR3 = "LLVector3"; LLVECTOR3D = "LLVector3d"; LLVECTOR4 = "LLVector4"
- LLQUATERNION = "LLQuaternion"
- LLUUID = "LLUUID"
- BOOL = "BOOL"
- IPADDR = "IPADDR"; IPPORT = "IPPORT"
- FIXED = "Fixed"
- VARIABLE = "Variable"
- types = [ U8, U16, U32, U64, S8, S16, S32, S64, F32, F64,
- LLVECTOR3, LLVECTOR3D, LLVECTOR4, LLQUATERNION,
- LLUUID, BOOL, IPADDR, IPPORT, FIXED, VARIABLE ]
- typeswithsize = [ FIXED, VARIABLE ]
-
- def __init__(self, name, type, size):
- self.name = name
- self.type = type
- self.size = size
-
- def compatibleWithBase(self, base):
- if self.name != base.name:
- return Incompatible("has different name: %s vs. %s in base"
- % (self.name, base.name))
- if self.type != base.type:
- return Incompatible("has different type: %s vs. %s in base"
- % (self.type, base.type))
- if self.type in Variable.typeswithsize:
- if self.size != base.size:
- return Incompatible("has different size: %s vs. %s in base"
- % (self.size, base.size))
- return Same()
-
-
-
-###
-### Parsing Message Templates
-###
-
-class TemplateParser:
- def __init__(self, tokens):
- self._tokens = tokens
- self._version = 0
- self._numbers = { }
- for p in Message.priorities:
- self._numbers[p] = 0
-
- def parseTemplate(self):
- tokens = self._tokens
- t = Template()
- while True:
- if tokens.want("version"):
- v = float(tokens.require(tokens.wantFloat()))
- self._version = v
- t.version = v
- continue
-
- m = self.parseMessage()
- if m:
- t.addMessage(m)
- continue
-
- if self._version >= 2.0:
- tokens.require(tokens.wantEOF())
- break
- else:
- if tokens.wantEOF():
- break
-
- tokens.consume()
- # just assume (gulp) that this is a comment
- # line 468: "sim -> dataserver"
- return t
-
-
- def parseMessage(self):
- tokens = self._tokens
- if not tokens.want("{"):
- return None
-
- name = tokens.require(tokens.wantSymbol())
- priority = tokens.require(tokens.wantOneOf(Message.priorities))
-
- if self._version >= 2.0 or priority in Message.prioritieswithnumber:
- number = int("+" + tokens.require(tokens.wantInteger()), 0)
- else:
- self._numbers[priority] += 1
- number = self._numbers[priority]
-
- trust = tokens.require(tokens.wantOneOf(Message.trusts))
- coding = tokens.require(tokens.wantOneOf(Message.encodings))
-
- m = Message(name, number, priority, trust, coding)
-
- if self._version >= 2.0:
- d = tokens.wantOneOf(Message.deprecations)
- if d:
- m.deprecate(d)
-
- while True:
- b = self.parseBlock()
- if not b:
- break
- m.addBlock(b)
-
- tokens.require(tokens.want("}"))
-
- return m
-
-
- def parseBlock(self):
- tokens = self._tokens
- if not tokens.want("{"):
- return None
- name = tokens.require(tokens.wantSymbol())
- repeat = tokens.require(tokens.wantOneOf(Block.repeats))
- if repeat in Block.repeatswithcount:
- count = int(tokens.require(tokens.wantInteger()))
- else:
- count = None
-
- b = Block(name, repeat, count)
-
- while True:
- v = self.parseVariable()
- if not v:
- break
- b.addVariable(v)
-
- tokens.require(tokens.want("}"))
- return b
-
-
- def parseVariable(self):
- tokens = self._tokens
- if not tokens.want("{"):
- return None
- name = tokens.require(tokens.wantSymbol())
- type = tokens.require(tokens.wantOneOf(Variable.types))
- if type in Variable.typeswithsize:
- size = tokens.require(tokens.wantInteger())
- else:
- tokens.wantInteger() # in LandStatRequest: "{ ParcelLocalID S32 1 }"
- size = None
- tokens.require(tokens.want("}"))
- return Variable(name, type, size)
-
-def parseTemplateString(s):
- return TemplateParser(TokenStream().fromString(s)).parseTemplate()
-
-def parseTemplateFile(f):
- return TemplateParser(TokenStream().fromFile(f)).parseTemplate()
-
-
-
-
diff --git a/linden/indra/lib/python/indra/tokenstream.py b/linden/indra/lib/python/indra/tokenstream.py
deleted file mode 100644
index 7dab11f..0000000
--- a/linden/indra/lib/python/indra/tokenstream.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# @file tokenstream.py
-# @brief Message template parsing utility class
-#
-# Copyright (c) 2007-2007, Linden Research, Inc.
-#
-# Second Life Viewer Source Code
-# The source code in this file ("Source Code") is provided by Linden Lab
-# to you under the terms of the GNU General Public License, version 2.0
-# ("GPL"), unless you have obtained a separate licensing agreement
-# ("Other License"), formally executed by you and Linden Lab. Terms of
-# the GPL can be found in doc/GPL-license.txt in this distribution, or
-# online at http://secondlife.com/developers/opensource/gplv2
-#
-# There are special exceptions to the terms and conditions of the GPL as
-# it is applied to this Source Code. View the full text of the exception
-# in the file doc/FLOSS-exception.txt in this software distribution, or
-# online at http://secondlife.com/developers/opensource/flossexception
-#
-# By copying, modifying or distributing this software, you acknowledge
-# that you have read and understood your obligations described above,
-# and agree to abide by those obligations.
-#
-# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
-# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
-# COMPLETENESS OR PERFORMANCE.
-
-import re
-
-class _EOF(object):
- pass
-
-EOF = _EOF()
-
-class _LineMarker(int):
- pass
-
-_commentRE = re.compile(r'//.*')
-_symbolRE = re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*')
-_integerRE = re.compile(r'(0x[0-9A-Fa-f]+|0\d*|[1-9]\d*)')
-_floatRE = re.compile(r'\d+(\.\d*)?')
-
-
-class ParseError(Exception):
- def __init__(self, stream, reason):
- self.line = stream.line
- self.context = stream._context()
- self.reason = reason
-
- def _contextString(self):
- c = [ ]
- for t in self.context:
- if isinstance(t, _LineMarker):
- break
- c.append(t)
- return " ".join(c)
-
- def __str__(self):
- return "line %d: %s @ ... %s" % (
- self.line, self.reason, self._contextString())
-
- def __nonzero__(self):
- return False
-
-
-def _optionText(options):
- n = len(options)
- if n == 1:
- return '"%s"' % options[0]
- return '"' + '", "'.join(options[0:(n-1)]) + '" or "' + options[-1] + '"'
-
-
-class TokenStream(object):
- def __init__(self):
- self.line = 0
- self.tokens = [ ]
-
- def fromString(self, string):
- return self.fromLines(string.split('\n'))
-
- def fromFile(self, file):
- return self.fromLines(file)
-
- def fromLines(self, lines):
- i = 0
- for line in lines:
- i += 1
- self.tokens.append(_LineMarker(i))
- self.tokens.extend(_commentRE.sub(" ", line).split())
- self._consumeLines()
- return self
-
- def consume(self):
- if not self.tokens:
- return EOF
- t = self.tokens.pop(0)
- self._consumeLines()
- return t
-
- def _consumeLines(self):
- while self.tokens and isinstance(self.tokens[0], _LineMarker):
- self.line = self.tokens.pop(0)
-
- def peek(self):
- if not self.tokens:
- return EOF
- return self.tokens[0]
-
- def want(self, t):
- if t == self.peek():
- return self.consume()
- return ParseError(self, 'expected "%s"' % t)
-
- def wantOneOf(self, options):
- assert len(options)
- if self.peek() in options:
- return self.consume()
- return ParseError(self, 'expected one of %s' % _optionText(options))
-
- def wantEOF(self):
- return self.want(EOF)
-
- def wantRE(self, re, message=None):
- t = self.peek()
- if t != EOF:
- m = re.match(t)
- if m and m.end() == len(t):
- return self.consume()
- if not message:
- message = "expected match for r'%s'" % re.pattern
- return ParseError(self, message)
-
- def wantSymbol(self):
- return self.wantRE(_symbolRE, "expected symbol")
-
- def wantInteger(self):
- return self.wantRE(_integerRE, "expected integer")
-
- def wantFloat(self):
- return self.wantRE(_floatRE, "expected float")
-
- def _context(self):
- n = min(5, len(self.tokens))
- return self.tokens[0:n]
-
- def require(self, t):
- if t:
- return t
- if isinstance(t, ParseError):
- raise t
- else:
- raise ParseError(self, "unmet requirement")
-
diff --git a/linden/indra/lib/python/indra/util/__init__.py b/linden/indra/lib/python/indra/util/__init__.py
new file mode 100644
index 0000000..3f79d0a
--- /dev/null
+++ b/linden/indra/lib/python/indra/util/__init__.py
@@ -0,0 +1,27 @@
+"""\
+@file __init__.py
+@brief Initialization file for the indra util module.
+
+Copyright (c) 2006-2007, Linden Research, Inc.
+
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlife.com/developers/opensource/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at http://secondlife.com/developers/opensource/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+"""
diff --git a/linden/indra/lib/python/indra/util/llmanifest.py b/linden/indra/lib/python/indra/util/llmanifest.py
new file mode 100644
index 0000000..0e46589
--- /dev/null
+++ b/linden/indra/lib/python/indra/util/llmanifest.py
@@ -0,0 +1,582 @@
+#!/usr/bin/python
+"""\
+@file llmanifest.py
+@author Ryan Williams
+@brief Library for specifying operations on a set of files.
+
+Copyright (c) 2007, Linden Research, Inc.
+
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlife.com/developers/opensource/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at http://secondlife.com/developers/opensource/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+"""
+
+import commands
+import filecmp
+import fnmatch
+import getopt
+import glob
+import os
+import os.path
+import re
+import shutil
+import sys
+import tarfile
+
+def path_ancestors(path):
+ path = os.path.normpath(path)
+ result = []
+ while len(path) > 0:
+ result.append(path)
+ path, sub = os.path.split(path)
+ return result
+
+def proper_windows_path(path, current_platform = sys.platform):
+ """ This function takes an absolute Windows or Cygwin path and
+ returns a path appropriately formatted for the platform it's
+ running on (as determined by sys.platform)"""
+ path = path.strip()
+ drive_letter = None
+ rel = None
+ match = re.match("/cygdrive/([a-z])/(.*)", path)
+ if(not match):
+ match = re.match('([a-zA-Z]):\\\(.*)', path)
+ if(not match):
+ return None # not an absolute path
+ drive_letter = match.group(1)
+ rel = match.group(2)
+ if(current_platform == "cygwin"):
+ return "/cygdrive/" + drive_letter.lower() + '/' + rel.replace('\\', '/')
+ else:
+ return drive_letter.upper() + ':\\' + rel.replace('/', '\\')
+
+def get_default_platform(dummy):
+ return {'linux2':'linux',
+ 'linux1':'linux',
+ 'cygwin':'windows',
+ 'win32':'windows',
+ 'darwin':'darwin'
+ }[sys.platform]
+
+def get_default_version(srctree):
+ # look up llversion.h and parse out the version info
+ paths = [os.path.join(srctree, x, 'llversion.h') for x in ['llcommon', '../llcommon', '../../indra/llcommon.h']]
+ for p in paths:
+ if os.path.exists(p):
+ contents = open(p, 'r').read()
+ major = re.search("LL_VERSION_MAJOR\s=\s([0-9]+)", contents).group(1)
+ minor = re.search("LL_VERSION_MINOR\s=\s([0-9]+)", contents).group(1)
+ patch = re.search("LL_VERSION_PATCH\s=\s([0-9]+)", contents).group(1)
+ build = re.search("LL_VERSION_BUILD\s=\s([0-9]+)", contents).group(1)
+ return major, minor, patch, build
+
+DEFAULT_CHANNEL = 'Second Life Release'
+
+ARGUMENTS=[
+ dict(name='actions',
+ description="""This argument specifies the actions that are to be taken when the
+ script is run. The meaningful actions are currently:
+ copy - copies the files specified by the manifest into the
+ destination directory.
+ package - bundles up the files in the destination directory into
+ an installer for the current platform
+ unpacked - bundles up the files in the destination directory into
+ a simple tarball
+ Example use: %(name)s --actions="copy unpacked" """,
+ default="copy package"),
+ dict(name='arch',
+ description="""This argument is appended to the platform string for
+ determining which manifest class to run.
+ Example use: %(name)s --arch=i686
+ On Linux this would try to use Linux_i686Manifest.""",
+ default=""),
+ dict(name='configuration',
+ description="""The build configuration used. Only used on OS X for
+ now, but it could be used for other platforms as well.""",
+ default="Universal"),
+ dict(name='grid',
+ description="""Which grid the client will try to connect to. Even
+ though it's not strictly a grid, 'firstlook' is also an acceptable
+ value for this parameter.""",
+ default=""),
+ dict(name='channel',
+ description="""The channel to use for updates.""",
+ default=DEFAULT_CHANNEL),
+ dict(name='installer_name',
+ description=""" The name of the file that the installer should be
+ packaged up into. Only used on Linux at the moment.""",
+ default=None),
+ dict(name='login_url',
+ description="""The url that the login screen displays in the client.""",
+ default=None),
+ dict(name='platform',
+ description="""The current platform, to be used for looking up which
+ manifest class to run.""",
+ default=get_default_platform),
+ dict(name='version',
+ description="""This specifies the version of Second Life that is
+ being packaged up.""",
+ default=get_default_version)
+ ]
+
+def usage(srctree=""):
+ nd = {'name':sys.argv[0]}
+ print """Usage:
+ %(name)s [options] [destdir]
+ Options:
+ """ % nd
+ for arg in ARGUMENTS:
+ default = arg['default']
+ if hasattr(default, '__call__'):
+ default = "(computed value) \"" + str(default(srctree)) + '"'
+ elif default is not None:
+ default = '"' + default + '"'
+ print "\t--%s Default: %s\n\t%s\n" % (
+ arg['name'],
+ default,
+ arg['description'] % nd)
+
+def main(argv=None, srctree='.', dsttree='./dst'):
+ if(argv == None):
+ argv = sys.argv
+
+ option_names = [arg['name'] + '=' for arg in ARGUMENTS]
+ option_names.append('help')
+ options, remainder = getopt.getopt(argv[1:], "", option_names)
+ if len(remainder) >= 1:
+ dsttree = remainder[0]
+
+ print "Source tree:", srctree
+ print "Destination tree:", dsttree
+
+ # convert options to a hash
+ args = {}
+ for opt in options:
+ args[opt[0].replace("--", "")] = opt[1]
+
+ # early out for help
+ if args.has_key('help'):
+ # *TODO: it is a huge hack to pass around the srctree like this
+ usage(srctree)
+ return
+
+ # defaults
+ for arg in ARGUMENTS:
+ if not args.has_key(arg['name']):
+ default = arg['default']
+ if hasattr(default, '__call__'):
+ default = default(srctree)
+ if default is not None:
+ args[arg['name']] = default
+
+ # fix up version
+ if args.has_key('version') and type(args['version']) == str:
+ args['version'] = args['version'].split('.')
+
+ # default and agni are default
+ if args['grid'] in ['default', 'agni']:
+ args['grid'] = ''
+
+ if args.has_key('actions'):
+ args['actions'] = args['actions'].split()
+
+ # debugging
+ for opt in args:
+ print "Option:", opt, "=", args[opt]
+
+ wm = LLManifest.for_platform(args['platform'], args.get('arch'))(srctree, dsttree, args)
+ wm.do(*args['actions'])
+ return 0
+
+class LLManifestRegistry(type):
+ def __init__(cls, name, bases, dct):
+ super(LLManifestRegistry, cls).__init__(name, bases, dct)
+ match = re.match("(\w+)Manifest", name)
+ if(match):
+ cls.manifests[match.group(1).lower()] = cls
+
+class LLManifest(object):
+ __metaclass__ = LLManifestRegistry
+ manifests = {}
+ def for_platform(self, platform, arch = None):
+ if arch:
+ platform = platform + '_' + arch
+ return self.manifests[platform.lower()]
+ for_platform = classmethod(for_platform)
+
+ def __init__(self, srctree, dsttree, args):
+ super(LLManifest, self).__init__()
+ self.args = args
+ self.file_list = []
+ self.excludes = []
+ self.actions = []
+ self.src_prefix = [srctree]
+ self.dst_prefix = [dsttree]
+ self.created_paths = []
+
+ def default_grid(self):
+ return self.args.get('grid', None) == ''
+ def default_channel(self):
+ return self.args.get('channel', None) == DEFAULT_CHANNEL
+
+ def construct(self):
+ """ Meant to be overriden by LLManifest implementors with code that
+ constructs the complete destination hierarchy."""
+ pass # override this method
+
+ def exclude(self, glob):
+ """ Excludes all files that match the glob from being included
+ in the file list by path()."""
+ self.excludes.append(glob)
+
+ def prefix(self, src='', dst=None):
+ """ Pushes a prefix onto the stack. Until end_prefix is
+ called, all relevant method calls (esp. to path()) will prefix
+ paths with the entire prefix stack. Source and destination
+ prefixes can be different, though if only one is provided they
+ are both equal. To specify a no-op, use an empty string, not
+ None."""
+ if(dst == None):
+ dst = src
+ self.src_prefix.append(src)
+ self.dst_prefix.append(dst)
+ return True # so that you can wrap it in an if to get indentation
+
+ def end_prefix(self, descr=None):
+ """Pops a prefix off the stack. If given an argument, checks
+ the argument against the top of the stack. If the argument
+ matches neither the source or destination prefixes at the top
+ of the stack, then misnesting must have occurred and an
+ exception is raised."""
+ # as an error-prevention mechanism, check the prefix and see if it matches the source or destination prefix. If not, improper nesting may have occurred.
+ src = self.src_prefix.pop()
+ dst = self.dst_prefix.pop()
+ if descr and not(src == descr or dst == descr):
+ raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'"
+
+ def get_src_prefix(self):
+ """ Returns the current source prefix."""
+ return os.path.join(*self.src_prefix)
+
+ def get_dst_prefix(self):
+ """ Returns the current destination prefix."""
+ return os.path.join(*self.dst_prefix)
+
+ def src_path_of(self, relpath):
+ """Returns the full path to a file or directory specified
+ relative to the source directory."""
+ return os.path.join(self.get_src_prefix(), relpath)
+
+ def dst_path_of(self, relpath):
+ """Returns the full path to a file or directory specified
+ relative to the destination directory."""
+ return os.path.join(self.get_dst_prefix(), relpath)
+
+ def ensure_src_dir(self, reldir):
+ """Construct the path for a directory relative to the
+ source path, and ensures that it exists. Returns the
+ full path."""
+ path = os.path.join(self.get_src_prefix(), reldir)
+ self.cmakedirs(path)
+ return path
+
+ def ensure_dst_dir(self, reldir):
+ """Construct the path for a directory relative to the
+ destination path, and ensures that it exists. Returns the
+ full path."""
+ path = os.path.join(self.get_dst_prefix(), reldir)
+ self.cmakedirs(path)
+ return path
+
+ def run_command(self, command):
+ """ Runs an external command, and returns the output. Raises
+ an exception if the command reurns a nonzero status code. For
+ debugging/informational purpoases, prints out the command's
+ output as it is received."""
+ print "Running command:", command
+ fd = os.popen(command, 'r')
+ lines = []
+ while True:
+ lines.append(fd.readline())
+ if(lines[-1] == ''):
+ break
+ else:
+ print lines[-1],
+ output = ''.join(lines)
+ status = fd.close()
+ if(status):
+ raise RuntimeError, "Command " + command + " returned non-zero status (" + str(status) + ")"
+ return output
+
+ def created_path(self, path):
+ """ Declare that you've created a path in order to
+ a) verify that you really have created it
+ b) schedule it for cleanup"""
+ if not os.path.exists(path):
+ raise RuntimeError, "Should be something at path " + path
+ self.created_paths.append(path)
+
+ def put_in_file(self, contents, dst):
+ # write contents as dst
+ f = open(self.dst_path_of(dst), "wb")
+ f.write(contents)
+ f.close()
+
+ def replace_in(self, src, dst=None, searchdict={}):
+ if(dst == None):
+ dst = src
+ # read src
+ f = open(self.src_path_of(src), "rbU")
+ contents = f.read()
+ f.close()
+ # apply dict replacements
+ for old, new in searchdict.iteritems():
+ contents = contents.replace(old, new)
+ self.put_in_file(contents, dst)
+ self.created_paths.append(dst)
+
+ def copy_action(self, src, dst):
+ if(src and (os.path.exists(src) or os.path.islink(src))):
+ # ensure that destination path exists
+ self.cmakedirs(os.path.dirname(dst))
+ self.created_paths.append(dst)
+ if(not os.path.isdir(src)):
+ self.ccopy(src,dst)
+ else:
+ # src is a dir
+ self.ccopytree(src,dst)
+ else:
+ print "Doesn't exist:", src
+
+ def package_action(self, src, dst):
+ pass
+
+ def copy_finish(self):
+ pass
+
+ def package_finish(self):
+ pass
+
+ def unpacked_finish(self):
+ unpacked_file_name = "unpacked_%(plat)s_%(vers)s.tar" % {
+ 'plat':self.args['platform'],
+ 'vers':'_'.join(self.args['version'])}
+ print "Creating unpacked file:", unpacked_file_name
+ # could add a gz here but that doubles the time it takes to do this step
+ tf = tarfile.open(self.src_path_of(unpacked_file_name), 'w:')
+ # add the entire installation package, at the very top level
+ tf.add(self.get_dst_prefix(), "")
+ tf.close()
+
+ def cleanup_finish(self):
+ """ Delete paths that were specified to have been created by this script"""
+ for c in self.created_paths:
+ # *TODO is this gonna be useful?
+ print "Cleaning up " + c
+
+ def process_file(self, src, dst):
+ if(self.includes(src, dst)):
+# print src, "=>", dst
+ for action in self.actions:
+ methodname = action + "_action"
+ method = getattr(self, methodname, None)
+ if method is not None:
+ method(src, dst)
+ self.file_list.append([src, dst])
+ else:
+ print "Excluding: ", src, dst
+
+
+ def process_directory(self, src, dst):
+ if(not self.includes(src, dst)):
+ print "Excluding: ", src, dst
+ return
+ names = os.listdir(src)
+ self.cmakedirs(dst)
+ errors = []
+ for name in names:
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ if os.path.isdir(srcname):
+ self.process_directory(srcname, dstname)
+ else:
+ self.process_file(srcname, dstname)
+
+
+
+ def includes(self, src, dst):
+ if src:
+ for excl in self.excludes:
+ if fnmatch.fnmatch(src, excl):
+ return False
+ return True
+
+ def remove(self, *paths):
+ for path in paths:
+ if(os.path.exists(path)):
+ print "Removing path", path
+ if(os.path.isdir(path)):
+ shutil.rmtree(path)
+ else:
+ os.remove(path)
+
+ def ccopy(self, src, dst):
+ """ Copy a single file or symlink. Uses filecmp to skip copying for existing files."""
+ if os.path.islink(src):
+ linkto = os.readlink(src)
+ if(os.path.islink(dst) or os.path.exists(dst)):
+ os.remove(dst) # because symlinking over an existing link fails
+ os.symlink(linkto, dst)
+ else:
+ # Don't recopy file if it's up-to-date.
+ # If we seem to be not not overwriting files that have been
+ # updated, set the last arg to False, but it will take longer.
+ if(os.path.exists(dst) and filecmp.cmp(src, dst, True)):
+ return
+ # only copy if it's not excluded
+ if(self.includes(src, dst)):
+ shutil.copy2(src, dst)
+
+ def ccopytree(self, src, dst):
+ """Direct copy of shutil.copytree with the additional
+ feature that the destination directory can exist. It
+ is so dumb that Python doesn't come with this. Also it
+ implements the excludes functionality."""
+ if(not self.includes(src, dst)):
+ return
+ names = os.listdir(src)
+ self.cmakedirs(dst)
+ errors = []
+ for name in names:
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ try:
+ if os.path.isdir(srcname):
+ self.ccopytree(srcname, dstname)
+ else:
+ self.ccopy(srcname, dstname)
+ # XXX What about devices, sockets etc.?
+ except (IOError, os.error), why:
+ errors.append((srcname, dstname, why))
+ if errors:
+ raise RuntimeError, errors
+
+
+ def cmakedirs(self, path):
+ """Ensures that a directory exists, and doesn't throw an exception
+ if you call it on an existing directory."""
+# print "making path: ", path
+ path = os.path.normpath(path)
+ self.created_paths.append(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+ def find_existing_file(self, *list):
+ for f in list:
+ if(os.path.exists(f)):
+ return f
+ # didn't find it, return last item in list
+ if len(list) > 0:
+ return list[-1]
+ else:
+ return None
+
+ def contents_of_tar(self, src_tar, dst_dir):
+ """ Extracts the contents of the tarfile (specified
+ relative to the source prefix) into the directory
+ specified relative to the destination directory."""
+ self.check_file_exists(src_tar)
+ tf = tarfile.open(self.src_path_of(src_tar), 'r')
+ for member in tf.getmembers():
+ tf.extract(member, self.ensure_dst_dir(dst_dir))
+ # TODO get actions working on these dudes, perhaps we should extract to a temporary directory and then process_directory on it?
+ self.file_list.append([src_tar,
+ self.dst_path_of(os.path.join(dst_dir,member.name))])
+ tf.close()
+
+
+ def wildcard_regex(self, src_glob, dst_glob):
+ # print "regex_pair:", src_glob, dst_glob
+ src_re = re.escape(src_glob)
+ src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]+)')
+ dst_temp = dst_glob
+ i = 1
+ while(dst_temp.count("*") > 0):
+ dst_temp = dst_temp.replace('*', '\g<' + str(i) + '>', 1)
+ i = i+1
+ # print "regex_result:", src_re, dst_temp
+ return re.compile(src_re), dst_temp
+
+ def check_file_exists(self, path):
+ if(not os.path.exists(path) and not os.path.islink(path)):
+ raise RuntimeError("Path %s doesn't exist" % (
+ os.path.normpath(os.path.join(os.getcwd(), path)),))
+
+
+ wildcard_pattern = re.compile('\*')
+ def expand_globs(self, src, dst):
+ def fw_slash(str):
+ return str.replace('\\', '/')
+ def os_slash(str):
+ return str.replace('/', os.path.sep)
+ dst = fw_slash(dst)
+ src = fw_slash(src)
+ src_list = glob.glob(src)
+ src_re, d_template = self.wildcard_regex(src, dst)
+ for s in src_list:
+ s = fw_slash(s)
+ d = src_re.sub(d_template, s)
+ #print "s:",s, "d_t", d_template, "dst", dst, "d", d
+ yield os_slash(s), os_slash(d)
+
+ def path(self, src, dst=None):
+ print "Processing", src, "=>", dst
+ if src == None:
+ raise RuntimeError("No source file, dst is " + dst)
+ if dst == None:
+ dst = src
+ dst = os.path.join(self.get_dst_prefix(), dst)
+ src = os.path.join(self.get_src_prefix(), src)
+
+ # expand globs
+ if(self.wildcard_pattern.search(src)):
+ for s,d in self.expand_globs(src, dst):
+ self.process_file(s, d)
+ else:
+ # if we're specifying a single path (not a glob),
+ # we should error out if it doesn't exist
+ self.check_file_exists(src)
+ # if it's a directory, recurse through it
+ if(os.path.isdir(src)):
+ self.process_directory(src, dst)
+ else:
+ self.process_file(src, dst)
+
+
+ def do(self, *actions):
+ self.actions = actions
+ self.construct()
+ # perform finish actions
+ for action in self.actions:
+ methodname = action + "_finish"
+ method = getattr(self, methodname, None)
+ if method is not None:
+ method()
+ return self.file_list
diff --git a/linden/indra/linux_crash_logger/linux_crash_logger.cpp b/linden/indra/linux_crash_logger/linux_crash_logger.cpp
index b950753..f9c03b0 100644
--- a/linden/indra/linux_crash_logger/linux_crash_logger.cpp
+++ b/linden/indra/linux_crash_logger/linux_crash_logger.cpp
@@ -54,10 +54,8 @@ static const char dialog_text[] =
"Second Life appears to have crashed.\n"
"This crash reporter collects information about your computer's hardware, operating system, and some Second Life logs, which are used for debugging purposes only.\n"
"Sending crash reports is the best way to help us improve the quality of Second Life.\n"
-"If you continue to experience this problem, please try one of the following:\n"
-"- Contact support by email at support@EXAMPLE.com\n"
-"- If you can log-in, please contact Live Help by using menu Help > Live Help.\n"
-"- Search the Second Life Knowledge Base at http://secondlife.com/knowledgebase/\n"
+"If you continue to experience this problem, please try:\n"
+"- Contacting support by visiting http://www.secondlife.com/support\n"
"\n"
"Send crash report?";
@@ -474,9 +472,9 @@ LLFileEncoder::LLFileEncoder(const char *form_name, const char *filename, bool i
S32 buf_size = stat_data.st_size;
FILE *fp = fopen(mFilename.c_str(), "rb");
U8 *buf = new U8[buf_size + 1];
- fread(buf, 1, buf_size, fp);
+ size_t nread = fread(buf, 1, buf_size, fp);
fclose(fp);
- buf[buf_size] = 0;
+ buf[nread] = 0;
mBuf = (char *)buf;
diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp
index d5c2a40..4428cea 100644
--- a/linden/indra/llaudio/audioengine.cpp
+++ b/linden/indra/llaudio/audioengine.cpp
@@ -34,7 +34,7 @@
#include
#include
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
#include
#endif
diff --git a/linden/indra/llcharacter/lljoint.cpp b/linden/indra/llcharacter/lljoint.cpp
index 6141cc0..07c34a8 100644
--- a/linden/indra/llcharacter/lljoint.cpp
+++ b/linden/indra/llcharacter/lljoint.cpp
@@ -485,39 +485,6 @@ void LLJoint::setSkinOffset( const LLVector3& offset )
mSkinOffset = offset;
}
-//-----------------------------------------------------------------------------
-// setConstraintSilhouette()
-//-----------------------------------------------------------------------------
-void LLJoint::setConstraintSilhouette(LLDynamicArray& silhouette)
-{
- S32 i;
-
- mConstraintSilhouette.reset();
- for (i = 0; i < silhouette.count(); i++)
- {
- if (i % 2 == 1)
- {
- // skip normals
- continue;
- }
- mConstraintSilhouette[i / 2] = silhouette[i];
- }
- LLQuaternion inv_parent_rotation = LLQuaternion::DEFAULT;
-
- if (getParent())
- {
- inv_parent_rotation = ~getParent()->getWorldRotation();
- }
-
- for (i = 0; i < mConstraintSilhouette.count(); i++)
- {
- LLVector3 vert = mConstraintSilhouette[i];
-
- vert -= getWorldPosition();
- vert.normVec();
- vert = vert * inv_parent_rotation;
- }
-}
//-----------------------------------------------------------------------------
// clampRotation()
diff --git a/linden/indra/llcharacter/lljoint.h b/linden/indra/llcharacter/lljoint.h
index f188968..d1e0107 100644
--- a/linden/indra/llcharacter/lljoint.h
+++ b/linden/indra/llcharacter/lljoint.h
@@ -85,7 +85,6 @@ protected:
public:
U32 mDirtyFlags;
- BOOL mWorldRotationDirty;
BOOL mUpdateXform;
// describes the skin binding pose
@@ -93,8 +92,6 @@ public:
S32 mJointNum;
- LLDynamicArray mConstraintSilhouette;
-
// child joints
typedef std::list child_list_t;
child_list_t mChildren;
@@ -171,8 +168,6 @@ public:
LLXformMatrix *getXform() { return &mXform; }
- void setConstraintSilhouette(LLDynamicArray& silhouette);
-
void clampRotation(LLQuaternion old_rot, LLQuaternion new_rot);
virtual BOOL isAnimatable() { return TRUE; }
diff --git a/linden/indra/llcharacter/llmotion.cpp b/linden/indra/llcharacter/llmotion.cpp
index b13ea60..40a30a4 100644
--- a/linden/indra/llcharacter/llmotion.cpp
+++ b/linden/indra/llcharacter/llmotion.cpp
@@ -126,6 +126,11 @@ void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata )
mDeactivateCallbackUserData = userdata;
}
+BOOL LLMotion::isBlending()
+{
+ return mPose.getWeight() < 1.f;
+}
+
//-----------------------------------------------------------------------------
// activate()
//-----------------------------------------------------------------------------
@@ -142,10 +147,16 @@ void LLMotion::activate()
void LLMotion::deactivate()
{
mActive = FALSE;
+ mPose.setWeight(0.f);
if (mDeactivateCallback) (*mDeactivateCallback)(mDeactivateCallbackUserData);
onDeactivate();
}
+BOOL LLMotion::canDeprecate()
+{
+ return TRUE;
+}
+
// End
diff --git a/linden/indra/llcharacter/llmotion.h b/linden/indra/llcharacter/llmotion.h
index 48d402a..e60b0c0 100644
--- a/linden/indra/llcharacter/llmotion.h
+++ b/linden/indra/llcharacter/llmotion.h
@@ -99,13 +99,14 @@ public:
void setStopped(BOOL stopped) { mStopped = stopped; }
+ BOOL isBlending();
+
void activate();
void deactivate();
BOOL isActive() { return mActive; }
-
public:
//-------------------------------------------------------------------------
// animation callbacks to be implemented by subclasses
@@ -145,6 +146,11 @@ public:
// called when a motion is deactivated
virtual void onDeactivate() = 0;
+ // can we crossfade this motion with a new instance when restarted?
+ // should ultimately always be TRUE, but lack of emote blending, etc
+ // requires this
+ virtual BOOL canDeprecate();
+
// optional callback routine called when animation deactivated.
void setDeactivateCallback( void (*cb)(void *), void* userdata );
diff --git a/linden/indra/llcharacter/llmotioncontroller.cpp b/linden/indra/llcharacter/llmotioncontroller.cpp
index 2427fd8..aebfaf6 100644
--- a/linden/indra/llcharacter/llmotioncontroller.cpp
+++ b/linden/indra/llcharacter/llmotioncontroller.cpp
@@ -194,34 +194,44 @@ void LLMotionController::deleteAllMotions()
//-----------------------------------------------------------------------------
void LLMotionController::addLoadedMotion(LLMotion* motionp)
{
+ std::set motions_to_kill;
+
+ // gather all inactive, loaded motions
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
{
// too many motions active this frame, kill all blenders
mPoseBlender.clearBlenders();
- for (U32 i = 0; i < mLoadedMotions.size(); i++)
+ for (motion_list_t::iterator loaded_motion_it = mLoadedMotions.begin();
+ loaded_motion_it != mLoadedMotions.end();
+ ++loaded_motion_it)
{
- LLMotion* cur_motionp = mLoadedMotions.front();
- mLoadedMotions.pop_front();
+ LLMotion* cur_motionp = *loaded_motion_it;
// motion isn't playing, delete it
if (!isMotionActive(cur_motionp))
{
- mCharacter->requestStopMotion(cur_motionp);
- mAllMotions.erase(cur_motionp->getID());
- delete cur_motionp;
- if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES)
- {
- break;
- }
- }
- else
- {
- // put active motion on back
- mLoadedMotions.push_back(cur_motionp);
+ motions_to_kill.insert(cur_motionp->getID());
}
}
}
+
+ // clean up all inactive, loaded motions
+ for (std::set::iterator motion_it = motions_to_kill.begin();
+ motion_it != motions_to_kill.end();
+ ++motion_it)
+ {
+ // look up the motion again by ID to get canonical instance
+ // and kill it only if that one is inactive
+ LLUUID motion_id = *motion_it;
+ LLMotion* motionp = findMotion(motion_id);
+ if (motionp && !isMotionActive(motionp))
+ {
+ removeMotion(motion_id);
+ }
+ }
+
+ // add new motion to loaded list
mLoadedMotions.push_back(motionp);
}
@@ -280,14 +290,24 @@ BOOL LLMotionController::addMotion( const LLUUID& id, LLMotionConstructor constr
void LLMotionController::removeMotion( const LLUUID& id)
{
LLMotion* motionp = findMotion(id);
+
+ removeMotionInstance(motionp);
+
+ mAllMotions.erase(id);
+}
+
+// removes instance of a motion from all runtime structures, but does
+// not erase entry by ID, as this could be a duplicate instance
+// use removeMotion(id) to remove all references to a given motion by id.
+void LLMotionController::removeMotionInstance(LLMotion* motionp)
+{
if (motionp)
{
- stopMotionLocally(id, TRUE);
+ stopMotionInstance(motionp, TRUE);
mLoadingMotions.erase(motionp);
mLoadedMotions.remove(motionp);
mActiveMotions.remove(motionp);
- mAllMotions.erase(id);
delete motionp;
}
}
@@ -348,28 +368,39 @@ LLMotion* LLMotionController::createMotion( const LLUUID &id )
//-----------------------------------------------------------------------------
BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
{
- // look for motion in our list of created motions
- LLMotion *motion = createMotion(id);
+ // do we have an instance of this motion for this character?
+ LLMotion *motion = findMotion(id);
+
+ // motion that is stopping will be allowed to stop but
+ // replaced by a new instance of that motion
+ if (motion
+ && motion->canDeprecate()
+ && motion->getFadeWeight() > 0.01f // not LOD-ed out
+ && (motion->isBlending() || motion->getStopTime() != 0.f))
+ {
+ deprecateMotionInstance(motion);
+ // force creation of new instance
+ motion = NULL;
+ }
+
+ // create new motion instance
+ if (!motion)
+ {
+ motion = createMotion(id);
+ }
if (!motion)
{
return FALSE;
}
- //if the motion is already active, then we're done
- else if (isMotionActive(motion)) // motion is playing and...
+ //if the motion is already active and allows deprecation, then let it keep playing
+ else if (motion->canDeprecate() && isMotionActive(motion))
{
- if (motion->isStopped()) // motion has been stopped
- {
- deactivateMotion(motion, false);
- }
- else if (mTime < motion->mSendStopTimestamp) // motion is still active
- {
- return TRUE;
- }
+ return TRUE;
}
// llinfos << "Starting motion " << name << llendl;
- return activateMotion(motion, mTime - start_offset);
+ return activateMotionInstance(motion, mTime - start_offset);
}
@@ -380,6 +411,12 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate
{
// if already inactive, return false
LLMotion *motion = findMotion(id);
+
+ return stopMotionInstance(motion, stop_immediate);
+}
+
+BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate)
+{
if (!motion)
{
return FALSE;
@@ -396,7 +433,7 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate
if (stop_immediate)
{
- deactivateMotion(motion, false);
+ deactivateMotionInstance(motion);
}
return TRUE;
}
@@ -492,7 +529,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
{
if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{
- deactivateMotion(motionp, false);
+ deactivateMotionInstance(motionp);
}
else if (motionp->isStopped() && mTime > motionp->getStopTime())
{
@@ -510,7 +547,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
else if (mTime >= motionp->mActivationTimestamp)
@@ -538,7 +575,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -546,7 +583,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
{
if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{
- deactivateMotion(motionp, true);
+ posep->setWeight(0.f);
+ deactivateMotionInstance(motionp);
}
continue;
}
@@ -572,7 +610,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
}
else
{
- deactivateMotion(motionp, true);
+ posep->setWeight(0.f);
+ deactivateMotionInstance(motionp);
continue;
}
}
@@ -617,7 +656,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -661,7 +700,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
// propagate this to the network
// as not all viewers are guaranteed to have access to the same logic
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -733,7 +772,7 @@ void LLMotionController::updateMotion()
// this motion should be playing
if (!motionp->isStopped())
{
- activateMotion(motionp, mTime);
+ activateMotionInstance(motionp, mTime);
}
}
else if (status == LLMotion::STATUS_FAILURE)
@@ -741,6 +780,7 @@ void LLMotionController::updateMotion()
llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
sRegistry.markBad(motionp->getID());
mLoadingMotions.erase(curiter);
+
mAllMotions.erase(motionp->getID());
delete motionp;
}
@@ -773,9 +813,9 @@ void LLMotionController::updateMotion()
//-----------------------------------------------------------------------------
-// activateMotion()
+// activateMotionInstance()
//-----------------------------------------------------------------------------
-BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time)
+BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
{
if (mLoadingMotions.find(motion) != mLoadingMotions.end())
{
@@ -818,23 +858,38 @@ BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time)
}
//-----------------------------------------------------------------------------
-// deactivateMotion()
+// deactivateMotionInstance()
//-----------------------------------------------------------------------------
-BOOL LLMotionController::deactivateMotion(LLMotion *motion, bool remove_weight)
+BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion)
{
- if( remove_weight )
+ motion->deactivate();
+
+ motion_set_t::iterator found_it = mDeprecatedMotions.find(motion);
+ if (found_it != mDeprecatedMotions.end())
{
- // immediately remove pose weighting instead of letting it time out
- LLPose *posep = motion->getPose();
- posep->setWeight(0.f);
+ // deprecated motions need to be completely excised
+ removeMotionInstance(motion);
+ mDeprecatedMotions.erase(found_it);
+ }
+ else
+ {
+ // for motions that we are keeping, simply remove from active queue
+ mActiveMotions.remove(motion);
}
-
- motion->deactivate();
- mActiveMotions.remove(motion);
return TRUE;
}
+void LLMotionController::deprecateMotionInstance(LLMotion* motion)
+{
+ mDeprecatedMotions.insert(motion);
+
+ //fade out deprecated motion
+ stopMotionInstance(motion, FALSE);
+ //no longer canonical
+ mAllMotions.erase(motion->getID());
+}
+
//-----------------------------------------------------------------------------
// isMotionActive()
//-----------------------------------------------------------------------------
@@ -857,7 +912,7 @@ bool LLMotionController::isMotionLoading(LLMotion* motion)
//-----------------------------------------------------------------------------
LLMotion *LLMotionController::findMotion(const LLUUID& id)
{
- return mAllMotions[id];
+ return get_if_there(mAllMotions, id, NULL);
}
//-----------------------------------------------------------------------------
diff --git a/linden/indra/llcharacter/llmotioncontroller.h b/linden/indra/llcharacter/llmotioncontroller.h
index 959a16a..efc12d5 100644
--- a/linden/indra/llcharacter/llmotioncontroller.h
+++ b/linden/indra/llcharacter/llmotioncontroller.h
@@ -179,16 +179,21 @@ public:
LLMotion *findMotion( const LLUUID& id );
protected:
+ // internal operations act on motion instances directly
+ // as there can be duplicate motions per id during blending overlap
void deleteAllMotions();
void addLoadedMotion(LLMotion *motion);
- BOOL activateMotion(LLMotion *motion, F32 time);
- BOOL deactivateMotion(LLMotion *motion, bool remove_weight);
+ BOOL activateMotionInstance(LLMotion *motion, F32 time);
+ BOOL deactivateMotionInstance(LLMotion *motion);
+ void deprecateMotionInstance(LLMotion* motion);
+ BOOL stopMotionInstance(LLMotion *motion, BOOL stop_imemdiate);
+ void removeMotionInstance(LLMotion* motion);
void updateRegularMotions();
void updateAdditiveMotions();
void resetJointSignatures();
void updateMotionsByType(LLMotion::LLMotionBlendType motion_type);
-protected:
+protected:
F32 mTimeFactor;
static LLMotionRegistry sRegistry;
LLPoseBlender mPoseBlender;
@@ -203,11 +208,13 @@ protected:
// Once an animations is loaded, it will be initialized and put on the mLoadedMotions deque.
// Any animation that is currently playing also sits in the mActiveMotions list.
- std::map mAllMotions;
+ typedef std::map motion_map_t;
+ motion_map_t mAllMotions;
motion_set_t mLoadingMotions;
motion_list_t mLoadedMotions;
motion_list_t mActiveMotions;
+ motion_set_t mDeprecatedMotions;
LLFrameTimer mTimer;
F32 mTime;
diff --git a/linden/indra/llcharacter/llpose.cpp b/linden/indra/llcharacter/llpose.cpp
index ccedc1e..a07cd58 100644
--- a/linden/indra/llcharacter/llpose.cpp
+++ b/linden/indra/llcharacter/llpose.cpp
@@ -275,9 +275,9 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
joint_state_index < JSB_NUM_JOINT_STATES && mJointStates[joint_state_index] != NULL;
joint_state_index++)
{
- U32 current_usage = mJointStates[joint_state_index]->getUsage();
- F32 current_weight = mJointStates[joint_state_index]->getWeight();
LLJointState* jsp = mJointStates[joint_state_index];
+ U32 current_usage = jsp->getUsage();
+ F32 current_weight = jsp->getWeight();
if (current_weight == 0.f)
{
@@ -292,17 +292,14 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
// add in pos for this jointstate modulated by weight
added_pos += jsp->getPosition() * (new_weight_sum - sum_weights[POS_WEIGHT]);
- //sum_weights[POS_WEIGHT] = new_weight_sum;
}
- // now do scale
if(current_usage & LLJointState::SCALE)
{
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
// add in scale for this jointstate modulated by weight
added_scale += jsp->getScale() * (new_weight_sum - sum_weights[SCALE_WEIGHT]);
- //sum_weights[SCALE_WEIGHT] = new_weight_sum;
}
if (current_usage & LLJointState::ROT)
@@ -311,7 +308,6 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
// add in rotation for this jointstate modulated by weight
added_rot = nlerp((new_weight_sum - sum_weights[ROT_WEIGHT]), added_rot, jsp->getRotation()) * added_rot;
- //sum_weights[ROT_WEIGHT] = new_weight_sum;
}
}
else
@@ -326,13 +322,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);
// blend positions from both
- blended_pos = lerp(mJointStates[joint_state_index]->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
+ blended_pos = lerp(jsp->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
sum_weights[POS_WEIGHT] = new_weight_sum;
}
else
{
// copy position from current
- blended_pos = mJointStates[joint_state_index]->getPosition();
+ blended_pos = jsp->getPosition();
sum_weights[POS_WEIGHT] = current_weight;
}
}
@@ -345,13 +341,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
// blend scales from both
- blended_scale = lerp(mJointStates[joint_state_index]->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
+ blended_scale = lerp(jsp->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
sum_weights[SCALE_WEIGHT] = new_weight_sum;
}
else
{
// copy scale from current
- blended_scale = mJointStates[joint_state_index]->getScale();
+ blended_scale = jsp->getScale();
sum_weights[SCALE_WEIGHT] = current_weight;
}
}
@@ -364,13 +360,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]);
// blend rotations from both
- blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, mJointStates[joint_state_index]->getRotation(), blended_rot);
+ blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, jsp->getRotation(), blended_rot);
sum_weights[ROT_WEIGHT] = new_weight_sum;
}
else
{
// copy rotation from current
- blended_rot = mJointStates[joint_state_index]->getRotation();
+ blended_rot = jsp->getRotation();
sum_weights[ROT_WEIGHT] = current_weight;
}
}
diff --git a/linden/indra/llcharacter/llpose.h b/linden/indra/llcharacter/llpose.h
index f57f7de..4e1bb64 100644
--- a/linden/indra/llcharacter/llpose.h
+++ b/linden/indra/llcharacter/llpose.h
@@ -81,7 +81,7 @@ public:
S32 getNumJointStates() const;
};
-const S32 JSB_NUM_JOINT_STATES = 4;
+const S32 JSB_NUM_JOINT_STATES = 6;
class LLJointStateBlender
{
diff --git a/linden/indra/llcommon/indra_constants.h b/linden/indra/llcommon/indra_constants.h
index 9024b12..21635b5 100644
--- a/linden/indra/llcommon/indra_constants.h
+++ b/linden/indra/llcommon/indra_constants.h
@@ -130,10 +130,12 @@ const char CLOUD_LAYER_CODE = '8';
// keys
// Bit masks for various keyboard modifier keys.
-const MASK MASK_NONE = 0x0000;
-const MASK MASK_CONTROL = 0x0001;
-const MASK MASK_ALT = 0x0002;
-const MASK MASK_SHIFT = 0x0004;
+const MASK MASK_NONE = 0x0000;
+const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
+const MASK MASK_ALT = 0x0002;
+const MASK MASK_SHIFT = 0x0004;
+const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
+const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
// Special keys go into >128
const KEY KEY_SPECIAL = 0x80; // special keys start here
diff --git a/linden/indra/llcommon/llapr.h b/linden/indra/llcommon/llapr.h
index e7b12d5..6edfc18 100644
--- a/linden/indra/llcommon/llapr.h
+++ b/linden/indra/llcommon/llapr.h
@@ -31,7 +31,7 @@
#ifndef LL_LLAPR_H
#define LL_LLAPR_H
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
#include // Need PATH_MAX in APR headers...
#endif
diff --git a/linden/indra/llcommon/llcommon.vcproj b/linden/indra/llcommon/llcommon.vcproj
index 399dae3..5557f94 100644
--- a/linden/indra/llcommon/llcommon.vcproj
+++ b/linden/indra/llcommon/llcommon.vcproj
@@ -445,9 +445,6 @@
RelativePath=".\llnametable.h">
-
-
2)
+ s << std::right ;
+#else
+ s.setf(ios::right);
+#endif
+ std::string day = weekdays[exp_time.tm_wday];
+ std::string month = months[exp_time.tm_mon];
+
+ s << std::setw(day.length()) << (day)
+ << ", " << std::setw(2) << (exp_time.tm_mday)
+ << ' ' << std::setw(month.length()) << (month)
+ << ' ' << std::setw(4) << (exp_time.tm_year + 1900)
+ << ' ' << std::setw(2) << (exp_time.tm_hour)
+ << ':' << std::setw(2) << (exp_time.tm_min)
+ << ':' << std::setw(2) << (exp_time.tm_sec)
+ << " GMT";
+
+ // RFC 1123 date does not use microseconds
+ llinfos << "Date in RFC 1123 format is " << s << llendl;
+}
+
void LLDate::toStream(std::ostream& s) const
{
apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
diff --git a/linden/indra/llcommon/lldate.h b/linden/indra/llcommon/lldate.h
index f8bd625..5d90a54 100644
--- a/linden/indra/llcommon/lldate.h
+++ b/linden/indra/llcommon/lldate.h
@@ -77,7 +77,9 @@ public:
* @return A string representation of the date.
*/
std::string asString() const;
+ std::string asRFC1123() const;
void toStream(std::ostream&) const;
+ void toHTTPDateStream(std::ostream&) const;
/**
* @brief Set the date from an ISO-8601 string.
*
@@ -119,4 +121,8 @@ std::ostream& operator<<(std::ostream& s, const LLDate& date);
std::istream& operator>>(std::istream& s, LLDate& date);
+const static std::string weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+
+const static std::string months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
#endif // LL_LLDATE_H
diff --git a/linden/indra/llcommon/llfasttimer.cpp b/linden/indra/llcommon/llfasttimer.cpp
index 2b1d58f..6c0f9ac 100644
--- a/linden/indra/llcommon/llfasttimer.cpp
+++ b/linden/indra/llcommon/llfasttimer.cpp
@@ -33,7 +33,7 @@
#if LL_WINDOWS
#include
-#elif LL_LINUX
+#elif LL_LINUX || LL_SOLARIS
#include
#include
#include
@@ -91,7 +91,7 @@ U64 get_cpu_clock_count()
#endif // LL_WINDOWS
-#if LL_LINUX
+#if (LL_LINUX || LL_SOLARIS) && (defined(__i386__) || defined(__amd64__))
U64 get_cpu_clock_count()
{
U64 x;
@@ -100,7 +100,7 @@ U64 get_cpu_clock_count()
}
#endif
-#if LL_DARWIN
+#if LL_DARWIN || (LL_SOLARIS && defined(__sparc__))
//
// Mac implementation of CPU clock
//
@@ -115,7 +115,7 @@ U64 get_cpu_clock_count()
//////////////////////////////////////////////////////////////////////////////
//static
-#if LL_LINUX || LL_DARWIN
+#if LL_LINUX || LL_DARWIN || LL_SOLARIS
// Both Linux and Mac use gettimeofday for accurate time
U64 LLFastTimer::countsPerSecond()
{
diff --git a/linden/indra/llcommon/llfixedbuffer.cpp b/linden/indra/llcommon/llfixedbuffer.cpp
index 397fcfd..6defd92 100644
--- a/linden/indra/llcommon/llfixedbuffer.cpp
+++ b/linden/indra/llcommon/llfixedbuffer.cpp
@@ -82,7 +82,7 @@ void LLFixedBuffer::setMaxLines(S32 max_lines)
void LLFixedBuffer::removeExtraLines()
{
- while ((S32)mLines.size() > llmax(0, (S32)(mMaxLines - 1)))
+ while ((S32)mLines.size() > llmax((S32)0, (S32)(mMaxLines - 1)))
{
mLines.pop_front();
mAddTimes.pop_front();
diff --git a/linden/indra/llcommon/llhash.h b/linden/indra/llcommon/llhash.h
index c3c4ec9..793783f 100644
--- a/linden/indra/llcommon/llhash.h
+++ b/linden/indra/llcommon/llhash.h
@@ -42,6 +42,8 @@
# else
# include
# endif
+#elif LL_SOLARIS
+#include
#else
#error Please define your platform.
#endif
@@ -53,7 +55,7 @@ template inline size_t llhash(T value)
#elif ( (defined _STLPORT_VERSION) || ((LL_LINUX) && (__GNUC__ <= 2)) )
std::hash H;
return H(value);
-#elif LL_DARWIN || LL_LINUX
+#elif LL_DARWIN || LL_LINUX || LL_SOLARIS
__gnu_cxx::hash H;
return H(value);
#else
diff --git a/linden/indra/llcommon/llmemory.cpp b/linden/indra/llcommon/llmemory.cpp
index 284c8e7..65f3409 100644
--- a/linden/indra/llcommon/llmemory.cpp
+++ b/linden/indra/llcommon/llmemory.cpp
@@ -69,6 +69,7 @@ S32 LLMemType::sCurType = LLMemType::MTYPE_INIT;
S32 LLMemType::sType[LLMemType::MTYPE_MAX_DEPTH];
S32 LLMemType::sMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
S32 LLMemType::sMaxMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
+S32 LLMemType::sNewCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
S32 LLMemType::sOverheadMem = 0;
const char* LLMemType::sTypeDesc[LLMemType::MTYPE_NUM_TYPES] =
@@ -133,7 +134,7 @@ void LLMemType::printMem()
{
if (sMemCount[i])
{
- llinfos << llformat("MEM: % 20s %03d MB (%03d MB)",sTypeDesc[i],sMemCount[i]>>20,sMaxMemCount[i]>>20) << llendl;
+ llinfos << llformat("MEM: % 20s %03d MB (%03d MB) in %06d News",sTypeDesc[i],sMemCount[i]>>20,sMaxMemCount[i]>>20, sNewCount[i]) << llendl;
}
misc_mem -= sMemCount[i];
}
@@ -180,6 +181,7 @@ void* ll_allocate (size_t size)
{
LLMemType::sMaxMemCount[LLMemType::sCurType] = LLMemType::sMemCount[LLMemType::sCurType];
}
+ LLMemType::sNewCount[LLMemType::sCurType]++;
#endif
return (void*)p;
}
@@ -205,6 +207,7 @@ void ll_release (void *pin)
#if MEM_TRACK_TYPE
LLMemType::sMemCount[type] -= size;
LLMemType::sOverheadMem -= 4;
+ LLMemType::sNewCount[type]--;
#endif
LLMemType::sTotalMem -= size;
free(p);
diff --git a/linden/indra/llcommon/llmemtype.h b/linden/indra/llcommon/llmemtype.h
index 501b5f5..9bab72e 100644
--- a/linden/indra/llcommon/llmemtype.h
+++ b/linden/indra/llcommon/llmemtype.h
@@ -41,6 +41,7 @@ extern void ll_release (void *p);
#define MEM_TRACK_TYPE (1 && MEM_TRACK_MEM)
#if MEM_TRACK_TYPE
+#define MEM_DUMP_DATA 1
#define MEM_TYPE_NEW(T) \
static void* operator new(size_t s) { LLMemType mt(T); return ll_allocate(s); } \
static void operator delete(void* p) { ll_release(p); }
@@ -143,6 +144,7 @@ public:
static S32 sType[MTYPE_MAX_DEPTH];
static S32 sMemCount[MTYPE_NUM_TYPES];
static S32 sMaxMemCount[MTYPE_NUM_TYPES];
+ static S32 sNewCount[MTYPE_NUM_TYPES];
static S32 sOverheadMem;
static const char* sTypeDesc[MTYPE_NUM_TYPES];
#endif
diff --git a/linden/indra/llcommon/llpagemem.h b/linden/indra/llcommon/llpagemem.h
deleted file mode 100644
index f3d6061..0000000
--- a/linden/indra/llcommon/llpagemem.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/**
- * @file llpagemem.h
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- */
-#ifndef LL_LLPAGEMEM_H
-#define LL_LLPAGEMEM_H
-
-#if !LL_DARWIN
-#include "malloc.h"
-#endif
-
-#include "llrand.h"
-
-
-#ifndef __GNUC__
-template
-class LLPageMemory
-{
-private:
-
- union XObject
- {
- XObject *mNextFreeObject;
- U8 mObject[sizeof(Object)];
- };
-
- template struct Page
- {
- XObject *mFirstFreeObject;
- U32 mObjectCount;
- U8 mObjects[mPageSize-8];
-
- void init(U32 mObjPerPage)
- {
- XObject *o = (XObject*)&mObjects;
- mObjectCount = 0;
- mFirstFreeObject = o;
-
- for (U32 i = 0; i < mObjPerPage-1; i++)
- {
- o->mNextFreeObject = o+1;
- o++;
- }
- o->mNextFreeObject = NULL;
- };
-
- Object* alloc()
- {
- if (mFirstFreeObject)
- {
- XObject *ret = mFirstFreeObject;
- mFirstFreeObject = mFirstFreeObject->mNextFreeObject;
- ret->mNextFreeObject = NULL;
- mObjectCount++;
- return (Object*)&ret->mObject;
- };
- return NULL;
- }
- };
-
- U32 mObjPerPage;
- U32 mMaxPages;
- U32 mObjectCount;
-
- Page* mPageMemory;
- Page* mFirstPage;
-
-public:
- U32 precise, anywhere, fail;
-
- void init()
- {
- Page *p = mFirstPage;
- for (U32 i = 0; i < mMaxPages; i++)
- {
- p[i].init(mObjPerPage);
- }
-
- precise = 0;
- anywhere = 0;
- fail = 0;
- };
-
-public:
-
- Page* pageof(Object *object)
- {
- return (Page*) ((((U32)object - 8) / mPageSize) * mPageSize );
- }
-
- LLPageMemory(U32 maxObjects)
- {
- mObjPerPage = (mPageSize-8) / sizeof(Object);
- mMaxPages = (maxObjects / mObjPerPage) + 1;
- mObjectCount= 0;
-
- //printf("%d objects per page, %d pages total, %d/%d objects\n",
- // mObjPerPage, mMaxPages, mMaxPages * mObjPerPage,maxObjects);
-
- mPageMemory = (Page*)calloc(mPageSize,mMaxPages+1);
- mFirstPage = mPageMemory;
- U32 fix = ((U32)mPageMemory % mPageSize);
- if (fix) mFirstPage = (Page*)((U32)mPageMemory+mPageSize-fix);
-
- //printf("fix = %d\n",fix);
-
- init();
- };
-
- LLPageMemory(void *pageMem, U32 bytes)
- {
- }
-
- ~LLPageMemory()
- {
- if (mPageMemory)
- {
- free(mPageMemory);
- }
- }
-
- Object* alloc(Object *after=NULL)
- {
- Page * p = mFirstPage;
- Object * o = NULL;
- U32 i = mMaxPages;
-
- if (after)
- {
- o = pageof(after)->alloc();
- if (o)
- {
- precise++;
- return o;
- }
- return NULL;
- }
-
- F32 frac = 1.0f / (F32)mMaxPages;
- F32 thresh = 0.0f;
- for (i = 0; i < mMaxPages; i++)
- {
- if (thresh > ((F32)p[i].mObjectCount / (F32)mObjPerPage))
- {
- o = p[i].alloc();
- if (o)
- {
- //printf("allocating page %x obj %x\n",p, o);
- anywhere++;
- return o;
- }
- }
- thresh += frac;
- }
-
- fail++;
- return NULL;
- };
-
- void free(Object *o)
- {
- if (!o) return;
-
- Page *page = pageof(o);
- XObject *obj = (XObject*)o;
-
- //printf("freeing %x\n",obj);
-
- obj->mNextFreeObject = page->mFirstFreeObject;
- page->mFirstFreeObject = obj;
- page->mObjectCount--;
-
- //printf("freeing page %x %d\n",page, page->mObjectCount);
- };
-
- U32 indexof(Object *object)
- {
- if (!object) return -1;
-
- return ((((U32)object-8) % mPageSize) / sizeof(Object)) +
- ((pageof(object) - mFirstPage) * mObjPerPage);
- }
-
-
- void dump()
- {
-
- for (U32 i=0;i < mMaxPages;i++)
- {
- //printf("page %d %d/%d objects\n",i,mFirstPage[i].mObjectCount,mObjPerPage);
- }
- //printf("precise = %d anywhere %d ratio = %f\n",precise,anywhere,(F32)precise/(F32)(anywhere+precise));
- //printf("fail = %d\n",fail);
-
- }
-
- static void test()
- {
- struct Foo
- {
- U32 ord;
- U32 foo[8];
- };
-
- const U32 count = 100;
- U32 i,c;
- U32 mix = 50;
-
- LLPageMemory mem(count);
- LLRand rand(LLUUID::getRandomSeed());
-
- Foo *obj[count];
-
- for (i=0;i 0) obj[i] = mem.alloc(obj[i-1]);
- else obj[i] = mem.alloc();
- if (obj[i]) obj[i]->ord = x++;
- }
- }
- }
-
- for (i = 0; i< count; i++)
- {
- //printf("obj[%2d] = %08x %02d %4d\n",i,obj[i],mem.indexof(obj[i]),(obj[i] ? obj[i]->ord : -1));
- }
-
- mem.dump();
- }
-};
-
-
-template
-class LLObjectPool
-{
-private:
-
- class XObject
- {
- public:
- Object mObject;
- U32 mNextFreeObject;
-
- XObject() { mObject = NULL; mNextFreeObject = 0; }
- };
-
- U32 mNumObjects;
- U32 mMaxObjects;
- XObject* mObjects;
- U32 mFirstFreeObject;
-
- U32 indexof(XObject *xobj) { return (xobj - mObjects); }
-
-public:
- LLObjectPool(U32 maxObjects)
- {
- mMaxObjects = maxObjects;
- mFirstFreeObject = 0;
-
- mObjects = new XObject[mMaxObjects];
-
- //printf("objectpool allocated %d bytes\n",sizeof(XObject) * mMaxObjects);
-
- for (U32 i=0;imNextFreeObject;
- if (mFirstFreeObject >= mMaxObjects)
- {
- llerrs << "Attempted to allocate too many objects out of pool\n" << llendl;
- llassert(0);
- }
- return &obj->mObject;
- };
-
- void free(Object *obj)
- {
- if (!obj) return;
- XObject *xobj = (XObject*)obj;
- xobj->mNextFreeObject = mFirstFreeObject;
- mFirstFreeObject = indexof(xobj);
- };
-
- static void test()
- {
- struct Foo
- {
- U32 ord;
- U32 foo[8];
- };
-
- const U32 count = 100;
- U32 i,c;
- U32 mix = 50;
-
- LLPageMemory mem(count);
- LLRand rand(LLUUID::getRandomSeed());
-
- Foo *obj[count];
-
- for (i=0;i 0) obj[i] = mem.alloc(obj[i-1]);
- else obj[i] = mem.alloc();
- if (obj[i]) obj[i]->ord = x++;
- }
- }
- }
-
- for (i = 0; i< count; i++)
- {
- //printf("obj[%2d] = %08x %02d %4d\n",i,obj[i],mem.indexof(obj[i]),(obj[i] ? obj[i]->ord : -1));
- }
- }
-};
-#endif // !defined __GNUC__
-
-#endif
diff --git a/linden/indra/llcommon/llpreprocessor.h b/linden/indra/llcommon/llpreprocessor.h
index 495b9e8..f19d5a0 100644
--- a/linden/indra/llcommon/llpreprocessor.h
+++ b/linden/indra/llcommon/llpreprocessor.h
@@ -62,6 +62,11 @@
#ifndef LL_LIBXUL_ENABLED
#define LL_LIBXUL_ENABLED 1
#endif // def LL_LIBXUL_ENABLED
+#elif LL_SOLARIS
+ #define LL_QUICKTIME_ENABLED 0
+ #ifndef LL_LIBXUL_ENABLED
+ #define LL_LIBXUL_ENABLED 0
+ #endif // def LL_LIBXUL_ENABLED
#endif
#if LL_LIBXUL_ENABLED && !defined(MOZILLA_INTERNAL_API)
@@ -71,12 +76,22 @@
#define MOZILLA_INTERNAL_API 1
#endif
-// Deal with minor differences on Unixy OSes.
-#if LL_DARWIN || LL_LINUX
+// Figure out differences between compilers
+#if defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
+ #ifndef LL_GNUC
+ #define LL_GNUC 1
+ #endif
+#elif defined(__MSVC_VER__) || defined(_MSC_VER)
+ #ifndef LL_MSVC
+ #define LL_MSVC 1
+ #endif
+#endif
+// Deal with minor differences on Unixy OSes.
+#if LL_DARWIN || LL_LINUX
// Different name, same functionality.
#define stricmp strcasecmp
#define strnicmp strncasecmp
@@ -89,9 +104,9 @@
#endif
// Deal with the differeneces on Windows
-#if LL_WINDOWS
+#if LL_MSVC
#define snprintf safe_snprintf /* Flawfinder: ignore */
-#endif // LL_WINDOWS
+#endif // LL_MSVC
// Static linking with apr on windows needs to be declared.
#ifdef LL_WINDOWS
@@ -110,7 +125,7 @@
// Deal with VC6 problems
-#if defined(LL_WINDOWS)
+#if LL_MSVC
#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4.
#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
@@ -121,6 +136,6 @@
#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
#pragma warning( disable : 4996 ) // warning: deprecated
-#endif // LL_WINDOWS
+#endif // LL_MSVC
#endif // not LL_LINDEN_PREPROCESSOR_H
diff --git a/linden/indra/llcommon/llprocessor.cpp b/linden/indra/llcommon/llprocessor.cpp
index bd21351..4d00ab5 100644
--- a/linden/indra/llcommon/llprocessor.cpp
+++ b/linden/indra/llcommon/llprocessor.cpp
@@ -58,7 +58,7 @@
# include
#endif
-#if !LL_DARWIN
+#if !LL_DARWIN && !LL_SOLARIS
#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
// We need the QueryPerformanceCounter and Sleep functions
@@ -255,24 +255,24 @@ bool CProcessor::AnalyzeIntelProcessor()
/* 0x03 */ "0.13 micron Intel Celeron",
/* 0x04 */ "0.13 micron Intel Pentium III",
/* 0x05 */ "",
- /* 0x06 */ "0.13 micron Intel Pentium III mobile",
- /* 0x07 */ "0.13 micron Intel Celeron mobile",
+ /* 0x06 */ "0.13 micron Intel Pentium III Mobile",
+ /* 0x07 */ "0.13 micron Intel Celeron Mobile",
/* 0x08 */ "0.18 micron Intel Pentium 4",
/* 0x09 */ "0.13 micron Intel Pentium 4",
- /* 0x0A */ "0.13 micron Intel Pentium 4",
+ /* 0x0A */ "0.13 micron Intel Celeron",
/* 0x0B */ "0.13 micron Intel Pentium 4 Xeon",
- /* 0x0C */ "",
+ /* 0x0C */ "Intel Xeon MP",
/* 0x0D */ "",
/* 0x0E */ "0.18 micron Intel Pentium 4 Xeon",
- /* 0x0F */ "",
+ /* 0x0F */ "Mobile Intel Celeron",
/* 0x10 */ "",
- /* 0x11 */ "",
+ /* 0x11 */ "Mobile Genuine Intel",
/* 0x12 */ "Intel Celeron M",
- /* 0x13 */ "mobile Intel Celeron",
+ /* 0x13 */ "Mobile Intel Celeron",
/* 0x14 */ "Intel Celeron",
- /* 0x15 */ "mobile Intel",
+ /* 0x15 */ "Mobile Genuine Intel",
/* 0x16 */ "Intel Pentium M",
- /* 0x17 */ "mobile Intel Celeron",
+ /* 0x17 */ "Mobile Intel Celeron",
};
// Only override the brand if we have it in the lookup table. We should
@@ -300,7 +300,7 @@ bool CProcessor::AnalyzeIntelProcessor()
strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */
break;
case 6: // Family = 6: Pentium Pro (80686) processor family
- strcpy(CPUInfo.strFamily, "Intel Pentium Pro"); /* Flawfinder: ignore */
+ strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */
break;
case 15: // Family = 15: Extended family specific
// Masking the extended family
@@ -447,17 +447,21 @@ bool CProcessor::AnalyzeIntelProcessor()
case 1: // Model = 8, Brand id = 1: Celeron (on-die L2 cache) processor model
strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
- case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-))
+ case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-))
strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 3: // Model = 8, Brand id = 3: Pentium III Xeon (on-die L2 cache) processor model
- strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
default: // ...
strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
+ case 9: // Model = 9: Intel Pentium M processor, Intel Celeron M processor, model 9
+ strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ break;
case 0xA: // Model = 0xA: Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model
strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/
// Exact detection:
@@ -466,11 +470,11 @@ bool CProcessor::AnalyzeIntelProcessor()
case 1: // Model = 0xA, Brand id = 1: Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model
strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
- case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
+ case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 3: // Model = 0xA, Brand id = 3: Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model
- strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
default: // Getting bored of this............
strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
@@ -485,20 +489,32 @@ bool CProcessor::AnalyzeIntelProcessor()
case 3: // Model = 0xB, Brand id = 3: Celeron (Tualatin core) processor model
strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
- case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model
+ case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model
strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
case 7: // Model = 0xB, Brand id = 7: Celeron mobile (Tualatin core) processor model
- strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
default: // *bored*
strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
+ case 0xD: // Model = 0xD: Intel Pentium M processor, Intel Celeron M processor, model D
+ strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ break;
+ case 0xE: // Model = 0xE: Intel Core Duo processor, Intel Core Solo processor, model E
+ strcpy(CPUInfo.strModel, "Intel Core Series Processor"); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ break;
+ case 0xF: // Model = 0xF: Intel Core 2 Duo processor, model F
+ strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor"); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ break;
default: // *more bored*
- strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium Pro (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
+ strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/
+ strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
break;
}
break;
@@ -1538,6 +1554,7 @@ void CProcessor::GetStandardProcessorExtensions()
CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24);
CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25);
CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26);
+ CPUInfo._Ext.Altivec_Extensions = false;
CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27);
CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28);
CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF;
@@ -1643,6 +1660,125 @@ const ProcessorInfo *CProcessor::GetCPUInfo()
return (&CPUInfo);
}
+#elif LL_SOLARIS
+#include
+
+// ======================
+// Class constructor:
+/////////////////////////
+CProcessor::CProcessor()
+{
+ uqwFrequency = 0;
+ strCPUName[0] = 0;
+ memset(&CPUInfo, 0, sizeof(CPUInfo));
+}
+
+// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
+// =========================================================================
+// Function to query the current CPU frequency
+////////////////////////////////////////////////////////////////////////////
+F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
+{
+ if(uqwFrequency == 0){
+ GetCPUInfo();
+ }
+
+ return uqwFrequency;
+}
+
+// const ProcessorInfo *CProcessor::GetCPUInfo()
+// =============================================
+// Calls all the other detection function to create an detailed
+// processor information
+///////////////////////////////////////////////////////////////
+const ProcessorInfo *CProcessor::GetCPUInfo()
+{
+ // In Solaris the CPU info is in the kstats
+ // try "psrinfo" or "kstat cpu_info" to see all
+ // that's available
+ int ncpus=0, i;
+ kstat_ctl_t *kc;
+ kstat_t *ks;
+ kstat_named_t *ksinfo, *ksi;
+ kstat_t *CPU_stats_list;
+
+ kc = kstat_open();
+
+ if((int)kc == -1){
+ llwarns << "kstat_open(0 failed!" << llendl;
+ return (&CPUInfo);
+ }
+
+ for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) {
+ if (strncmp(ks->ks_module, "cpu_info", 8) == 0 &&
+ strncmp(ks->ks_name, "cpu_info", 8) == 0)
+ ncpus++;
+ }
+
+ if(ncpus < 1){
+ llwarns << "No cpus found in kstats!" << llendl;
+ return (&CPUInfo);
+ }
+
+ for (ks = kc->kc_chain; ks; ks = ks->ks_next) {
+ if (strncmp(ks->ks_module, "cpu_info", 8) == 0
+ && strncmp(ks->ks_name, "cpu_info", 8) == 0
+ && kstat_read(kc, ks, NULL) != -1){
+ CPU_stats_list = ks; // only looking at the first CPU
+
+ break;
+ }
+ }
+
+ if(ncpus > 1)
+ snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus);
+
+ kstat_read(kc, CPU_stats_list, NULL);
+ ksinfo = (kstat_named_t *)CPU_stats_list->ks_data;
+ for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need
+ ksi = ksinfo++;
+ if(!strcmp(ksi->name, "brand")){
+ strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi),
+ sizeof(strCPUName)-strlen(strCPUName)-1);
+ strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi),
+ sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
+ strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);
+ CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
+ // DEBUG llinfos << "CPU brand: " << strCPUName << llendl;
+ continue;
+ }
+
+ if(!strcmp(ksi->name, "clock_MHz")){
+#if defined(__sparc)
+ llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl;
+ uqwFrequency = (F64)(ksi->value.l * 1000000);
+#else
+ uqwFrequency = (F64)(ksi->value.i64 * 1000000);
+#endif
+ //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl;
+ continue;
+ }
+
+#if defined(__i386)
+ if(!strcmp(ksi->name, "vendor_id")){
+ strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1);
+ // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl;
+ continue;
+ }
+#endif
+ }
+
+ kstat_close(kc);
+
+#if defined(__sparc) // SPARC does not define a vendor string in kstat
+ strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1);
+#endif
+
+ // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " << uqwFrequency << "MHz." << llendl;
+
+ return (&CPUInfo);
+}
+
#else
// LL_DARWIN
@@ -1891,11 +2027,12 @@ const ProcessorInfo *CProcessor::GetCPUInfo()
break;
}
- // It's kinda like MMX or SSE...
CPUInfo._Ext.EMMX_MultimediaExtensions =
CPUInfo._Ext.MMX_MultimediaExtensions =
CPUInfo._Ext.SSE_StreamingSIMD_Extensions =
- CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.altivec");
+ CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false;
+
+ CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec");
#endif
@@ -1912,6 +2049,7 @@ const ProcessorInfo *CProcessor::GetCPUInfo()
CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx");
CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse");
CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2");
+ CPUInfo._Ext.Altivec_Extensions = false;
CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64");
#endif
@@ -2015,6 +2153,7 @@ bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
{
COPYADD("Processor Serial: Disabled\n");
}
+#if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent
COPYADD("\n\n// CPU Configuration\n////////////////////\n");
FORMATADD("L1 instruction cache: %s\n", CPUInfo._L1.Instruction.strCache);
@@ -2065,12 +2204,13 @@ bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
BOOLADD("SS Self Snoop: ", CPUInfo._Ext.SS_SelfSnoop);
BOOLADD("SSE Streaming SIMD Extensions: ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions);
BOOLADD("SSE2 Streaming SIMD 2 Extensions: ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions);
+ BOOLADD("ALTVEC Altivec Extensions: ", CPUInfo._Ext.Altivec_Extensions);
BOOLADD("TM Thermal Monitor: ", CPUInfo._Ext.TM_ThermalMonitor);
BOOLADD("TSC Time Stamp Counter: ", CPUInfo._Ext.TSC_TimeStampCounter);
BOOLADD("VME Virtual 8086 Mode Enhancements: ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements);
BOOLADD("3DNow! Instructions: ", CPUInfo._Ext._3DNOW_InstructionExtensions);
BOOLADD("Enhanced 3DNow! Instructions: ", CPUInfo._Ext._E3DNOW_InstructionExtensions);
-
+#endif
// Yippie!!!
return true;
}
diff --git a/linden/indra/llcommon/llprocessor.h b/linden/indra/llcommon/llprocessor.h
index fd9a5da..79dd1e8 100644
--- a/linden/indra/llcommon/llprocessor.h
+++ b/linden/indra/llcommon/llprocessor.h
@@ -40,6 +40,20 @@
#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
#endif
+#if LL_MSVC && _M_X64
+# define LL_X86_64 1
+# define LL_X86 1
+#elif LL_MSVC && _M_IX86
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
+# define LL_X86_64 1
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__i386__) )
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
+# define LL_PPC 1
+#endif
+
typedef struct ProcessorExtensions
{
@@ -71,6 +85,7 @@ typedef struct ProcessorExtensions
bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore;
bool SSE_StreamingSIMD_Extensions;
bool SSE2_StreamingSIMD2_Extensions;
+ bool Altivec_Extensions;
bool SS_SelfSnoop;
bool HT_HyperThreading;
unsigned int HT_HyterThreadingSiblings;
diff --git a/linden/indra/llcommon/llsdserialize_xml.cpp b/linden/indra/llcommon/llsdserialize_xml.cpp
index 85d3883..6d2f583 100644
--- a/linden/indra/llcommon/llsdserialize_xml.cpp
+++ b/linden/indra/llcommon/llsdserialize_xml.cpp
@@ -36,7 +36,11 @@
extern "C"
{
-#include "expat/expat.h"
+#ifdef LL_STANDALONE
+# include
+#else
+# include "expat/expat.h"
+#endif
}
/**
diff --git a/linden/indra/llcommon/llsdutil.cpp b/linden/indra/llcommon/llsdutil.cpp
index e8b3ac5..0e23054 100644
--- a/linden/indra/llcommon/llsdutil.cpp
+++ b/linden/indra/llcommon/llsdutil.cpp
@@ -35,7 +35,7 @@
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include // for htonl
-#elif LL_LINUX
+#elif LL_LINUX || LL_SOLARIS
# include
#elif LL_DARWIN
# include
diff --git a/linden/indra/llcommon/llskiplist.h b/linden/indra/llcommon/llskiplist.h
index be3385d..40d0c8a 100644
--- a/linden/indra/llcommon/llskiplist.h
+++ b/linden/indra/llcommon/llskiplist.h
@@ -28,11 +28,10 @@
#ifndef LL_LLSKIPLIST_H
#define LL_LLSKIPLIST_H
-#include "llerror.h"
-//#include "vmath.h"
+#include "llrand.h"
// NOTA BENE: Insert first needs to be < NOT <=
-
+// Binary depth must be >= 2
template
class LLSkipList
{
@@ -144,14 +143,11 @@ private:
// Implementation
//
+
+// Binary depth must be >= 2
template
inline void LLSkipList::init()
{
- if (BINARY_DEPTH < 2)
- {
- llerrs << "Trying to create skip list with too little depth, "
- "must be 2 or greater" << llendl;
- }
S32 i;
for (i = 0; i < BINARY_DEPTH; i++)
{
diff --git a/linden/indra/llcommon/llstring.h b/linden/indra/llcommon/llstring.h
index adfdfb8..5f48580 100644
--- a/linden/indra/llcommon/llstring.h
+++ b/linden/indra/llcommon/llstring.h
@@ -40,7 +40,7 @@
#include
#include
#include /* for vsnprintf */
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
#include
#include
#endif
@@ -54,7 +54,7 @@ class LLUUID;
class LLColor4;
class LLColor4U;
-#if (LL_DARWIN || (LL_LINUX && __GNUC__ > 2))
+#if (LL_DARWIN || LL_SOLARIS || (LL_LINUX && __GNUC__ > 2))
// Template specialization of char_traits for U16s. Only necessary on Mac for now (exists on Windows, unused/broken on Linux/gcc2.95)
namespace std
{
@@ -205,7 +205,7 @@ public:
LLStringBase(const T* s, size_type n);
LLStringBase(const T* s, size_type pos, size_type n );
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
void clear() { assign(null); }
LLStringBase& assign(const T* s);
@@ -700,7 +700,7 @@ LLStringBase::LLStringBase(const T* s, size_type pos, size_type n ) : std::ba
}
}
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
template
LLStringBase& LLStringBase::assign(const T* s)
{
@@ -1095,7 +1095,7 @@ BOOL LLStringBase::read(std::basic_string& string, const char* filename)
template
BOOL LLStringBase::write(std::basic_string& string, const char* filename)
{
-#ifdef LL_LINUX
+#if LL_LINUX || LL_SOLARIS
printf("STUBBED: LLStringBase::write at %s:%d\n", __FILE__, __LINE__);
#else
llofstream ofs(filename, llofstream::binary);
diff --git a/linden/indra/llcommon/llsys.cpp b/linden/indra/llcommon/llsys.cpp
index 48f2474..25749e1 100644
--- a/linden/indra/llcommon/llsys.cpp
+++ b/linden/indra/llcommon/llsys.cpp
@@ -31,9 +31,13 @@
#include "llsys.h"
#include
-#include
+#ifdef LL_STANDALONE
+# include
+#else
+# include "zlib/zlib.h"
+#endif
-#include "processor.h"
+#include "llprocessor.h"
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
@@ -44,6 +48,8 @@
# include
#elif LL_LINUX
# include
+# include
+# include
const char MEMINFO_FILE[] = "/proc/meminfo";
const char CPUINFO_FILE[] = "/proc/cpuinfo";
#endif
@@ -182,7 +188,7 @@ LLOSInfo::LLOSInfo() :
}
#else
struct utsname un;
- if(0==uname(&un))
+ if(uname(&un) != -1)
{
mOSString.append(un.sysname);
mOSString.append(" ");
@@ -252,13 +258,12 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
#if LL_WINDOWS
#endif
#if LL_LINUX
- FILE* status_filep = LLFile::fopen("/proc/self/status", "r"); /* Flawfinder: ignore */
+ FILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
S32 numRead = 0;
char buff[STATUS_SIZE]; /* Flawfinder: ignore */
- bzero(buff, STATUS_SIZE);
- rewind(status_filep);
- fread(buff, 1, STATUS_SIZE-2, status_filep);
+ size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
+ buff[nbytes] = '\0';
// All these guys return numbers in KB
char *memp = strstr(buff, "VmSize:");
@@ -267,6 +272,24 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
numRead += sscanf(memp, "%*s %u", &virtual_size);
}
fclose(status_filep);
+#elif LL_SOLARIS
+ char proc_ps[LL_MAX_PATH];
+ sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
+ int proc_fd = -1;
+ if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
+ llwarns << "unable to open " << proc_ps << llendl;
+ return 0;
+ }
+ psinfo_t proc_psinfo;
+ if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
+ llwarns << "Unable to read " << proc_ps << llendl;
+ close(proc_fd);
+ return 0;
+ }
+
+ close(proc_fd);
+
+ virtual_size = proc_psinfo.pr_size;
#endif
return virtual_size;
}
@@ -278,15 +301,14 @@ U32 LLOSInfo::getProcessResidentSizeKB()
#if LL_WINDOWS
#endif
#if LL_LINUX
- FILE* status_filep = LLFile::fopen("/proc/self/status", "r"); /* Flawfinder: ignore */
+ FILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
if (status_filep != NULL)
{
S32 numRead = 0;
char buff[STATUS_SIZE]; /* Flawfinder: ignore */
- bzero(buff, STATUS_SIZE);
- rewind(status_filep);
- fread(buff, 1, STATUS_SIZE-2, status_filep);
+ size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
+ buff[nbytes] = '\0';
// All these guys return numbers in KB
char *memp = strstr(buff, "VmRSS:");
@@ -296,47 +318,126 @@ U32 LLOSInfo::getProcessResidentSizeKB()
}
fclose(status_filep);
}
+#elif LL_SOLARIS
+ char proc_ps[LL_MAX_PATH];
+ sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
+ int proc_fd = -1;
+ if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
+ llwarns << "unable to open " << proc_ps << llendl;
+ return 0;
+ }
+ psinfo_t proc_psinfo;
+ if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
+ llwarns << "Unable to read " << proc_ps << llendl;
+ close(proc_fd);
+ return 0;
+ }
+
+ close(proc_fd);
+
+ resident_size = proc_psinfo.pr_rssize;
#endif
return resident_size;
}
LLCPUInfo::LLCPUInfo()
{
+ std::ostringstream out;
CProcessor proc;
const ProcessorInfo* info = proc.GetCPUInfo();
- mHasSSE = (info->_Ext.SSE_StreamingSIMD_Extensions != 0);
- mHasSSE2 = (info->_Ext.SSE2_StreamingSIMD2_Extensions != 0);
+ // proc.WriteInfoTextFile("procInfo.txt");
+ mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
+ mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
+ mHasAltivec = info->_Ext.Altivec_Extensions;
mCPUMhz = (S32)(proc.GetCPUFrequency(50)/1000000.0);
mFamily.assign( info->strFamily );
+ mCPUString = "Unknown";
+
+#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
+ out << proc.strCPUName;
+ if (200 < mCPUMhz && mCPUMhz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
+ {
+ out << " (" << mCPUMhz << " MHz)";
+ }
+ mCPUString = out.str();
+
+#elif LL_LINUX
+ std::map< LLString, LLString > cpuinfo;
+ FILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
+ if(cpuinfo_fp)
+ {
+ char line[MAX_STRING];
+ memset(line, 0, MAX_STRING);
+ while(fgets(line, MAX_STRING, cpuinfo_fp))
+ {
+ // /proc/cpuinfo on Linux looks like:
+ // name\t*: value\n
+ char* tabspot = strchr( line, '\t' );
+ if (tabspot == NULL)
+ continue;
+ char* colspot = strchr( tabspot, ':' );
+ if (colspot == NULL)
+ continue;
+ char* spacespot = strchr( colspot, ' ' );
+ if (spacespot == NULL)
+ continue;
+ char* nlspot = strchr( line, '\n' );
+ if (nlspot == NULL)
+ nlspot = line + strlen( line ); // Fallback to terminating NUL
+ std::string linename( line, tabspot );
+ LLString llinename(linename);
+ LLString::toLower(llinename);
+ std::string lineval( spacespot + 1, nlspot );
+ cpuinfo[ llinename ] = lineval;
+ }
+ fclose(cpuinfo_fp);
+ }
+# if LL_X86
+ LLString flags = " " + cpuinfo["flags"] + " ";
+ LLString::toLower(flags);
+ mHasSSE = ( flags.find( " sse " ) != std::string::npos );
+ mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos );
+
+ F64 mhz;
+ if (LLString::convertToF64(cpuinfo["cpu mhz"], mhz)
+ && 200.0 < mhz && mhz < 10000.0)
+ {
+ mCPUMhz = (S32)llrint(mhz);
+ }
+ if (!cpuinfo["model name"].empty())
+ mCPUString = cpuinfo["model name"];
+# endif // LL_X86
+#endif // LL_LINUX
}
+bool LLCPUInfo::hasAltivec() const
+{
+ return mHasAltivec;
+}
-std::string LLCPUInfo::getCPUString() const
+bool LLCPUInfo::hasSSE() const
{
-#if LL_WINDOWS || LL_DARWIN
- std::ostringstream out;
+ return mHasSSE;
+}
- CProcessor proc;
- (void) proc.GetCPUInfo();
- out << proc.strCPUName << " ";
-
- F32 freq = (F32)(proc.GetCPUFrequency(50) / 1000000.0);
+bool LLCPUInfo::hasSSE2() const
+{
+ return mHasSSE2;
+}
- // cpu speed is often way wrong, do a sanity check
- if (200.f < freq && freq < 10000.f)
- {
- out << "(" << (S32)(freq) << " MHz)";
- }
+S32 LLCPUInfo::getMhz() const
+{
+ return mCPUMhz;
+}
- return out.str();
-#else
- return "Can't get terse CPU information";
-#endif
+std::string LLCPUInfo::getCPUString() const
+{
+ return mCPUString;
}
void LLCPUInfo::stream(std::ostream& s) const
{
-#if LL_WINDOWS || LL_DARWIN
+#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
// gather machine information.
char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */
CProcessor proc;
@@ -346,38 +447,41 @@ void LLCPUInfo::stream(std::ostream& s) const
}
else
{
- s << "Unable to collect processor info";
+ s << "Unable to collect processor information" << std::endl;
}
#else
// *NOTE: This works on linux. What will it do on other systems?
- FILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "r"); /* Flawfinder: ignore */
+ FILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
if(cpuinfo)
{
- char line[MAX_STRING]; /* Flawfinder: ignore */
+ char line[MAX_STRING];
memset(line, 0, MAX_STRING);
while(fgets(line, MAX_STRING, cpuinfo))
{
- line[strlen(line)-1] = ' '; /*Flawfinder: ignore*/
+ line[strlen(line)-1] = ' ';
s << line;
}
fclose(cpuinfo);
+ s << std::endl;
}
else
{
- s << "Unable to collect memory information";
+ s << "Unable to collect processor information" << std::endl;
}
#endif
+ // These are interesting as they reflect our internal view of the
+ // CPU's attributes regardless of platform
+ s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
+ s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl;
+ s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
+ s << "->mCPUMhz: " << mCPUMhz << std::endl;
+ s << "->mCPUString: " << mCPUString << std::endl;
}
LLMemoryInfo::LLMemoryInfo()
{
}
-#if LL_LINUX
-#include
-#include
-#endif
-
U32 LLMemoryInfo::getPhysicalMemory() const
{
#if LL_WINDOWS
@@ -399,7 +503,8 @@ U32 LLMemoryInfo::getPhysicalMemory() const
#elif LL_LINUX
return getpagesize() * get_phys_pages();
-
+#elif LL_SOLARIS
+ return getpagesize() * sysconf(_SC_PHYS_PAGES);
#else
return 0;
@@ -433,10 +538,15 @@ void LLMemoryInfo::stream(std::ostream& s) const
{
s << "Unable to collect memory information";
}
-
+#elif LL_SOLARIS
+ U64 phys = 0;
+
+ phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024);
+
+ s << "Total Physical Kb: " << phys << std::endl;
#else
// *NOTE: This works on linux. What will it do on other systems?
- FILE* meminfo = LLFile::fopen(MEMINFO_FILE,"r"); /* Flawfinder: ignore */
+ FILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb");
if(meminfo)
{
char line[MAX_STRING]; /* Flawfinder: ignore */
@@ -491,7 +601,11 @@ BOOL gunzip_file(const char *srcfile, const char *dstfile)
do
{
bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE);
- fwrite(buffer, sizeof(U8), bytes, dst);
+ size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
+ if (nwrit < (size_t) bytes)
+ {
+ llerrs << "Short write on " << tmpfile << llendl;
+ }
} while(gzeof(src) == 0);
fclose(dst);
dst = NULL;
diff --git a/linden/indra/llcommon/llsys.h b/linden/indra/llcommon/llsys.h
index 2047d9a..416bd54 100644
--- a/linden/indra/llcommon/llsys.h
+++ b/linden/indra/llcommon/llsys.h
@@ -72,18 +72,21 @@ public:
std::string getCPUString() const;
- BOOL hasSSE() const { return mHasSSE; }
- BOOL hasSSE2() const { return mHasSSE2; }
- S32 getMhz() const { return mCPUMhz; }
+ bool hasAltivec() const;
+ bool hasSSE() const;
+ bool hasSSE2() const;
+ S32 getMhz() const;
// Family is "AMD Duron" or "Intel Pentium Pro"
const std::string& getFamily() const { return mFamily; }
private:
- BOOL mHasSSE;
- BOOL mHasSSE2;
+ bool mHasSSE;
+ bool mHasSSE2;
+ bool mHasAltivec;
S32 mCPUMhz;
std::string mFamily;
+ std::string mCPUString;
};
class LLMemoryInfo
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp
index 0f833ab..d261c8b 100644
--- a/linden/indra/llcommon/llthread.cpp
+++ b/linden/indra/llcommon/llthread.cpp
@@ -32,7 +32,7 @@
#include "lltimer.h"
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
#include
#endif
@@ -226,7 +226,7 @@ void LLThread::setQuitting()
// static
void LLThread::yield()
{
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
#else
apr_thread_yield();
diff --git a/linden/indra/llcommon/lltimer.cpp b/linden/indra/llcommon/lltimer.cpp
index 21fbf0e..6077063 100644
--- a/linden/indra/llcommon/lltimer.cpp
+++ b/linden/indra/llcommon/lltimer.cpp
@@ -37,7 +37,7 @@
# include
# include
# include
-#elif LL_LINUX
+#elif LL_LINUX || LL_SOLARIS
# include
# include
# include
@@ -90,7 +90,7 @@ void llyield()
{
SleepEx(0, TRUE); // Relinquishes time slice to any thread of equal priority, can be woken up by extended IO functions
}
-#elif LL_LINUX
+#elif LL_LINUX || LL_SOLARIS
void ms_sleep(long ms)
{
struct timespec t;
@@ -150,7 +150,7 @@ F64 calc_clock_frequency(U32 uiMeasureMSecs)
#endif // LL_WINDOWS
-#if LL_LINUX || LL_DARWIN
+#if LL_LINUX || LL_DARWIN || LL_SOLARIS
// Both Linux and Mac use gettimeofday for accurate time
F64 calc_clock_frequency(unsigned int uiMeasureMSecs)
{
@@ -169,7 +169,7 @@ U64 get_clock_count()
void update_clock_frequencies()
{
- gClockFrequency = calc_clock_frequency(50);
+ gClockFrequency = calc_clock_frequency(50U);
gClockFrequencyInv = 1.0/gClockFrequency;
gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
}
@@ -512,7 +512,7 @@ void secondsToTimecodeString(F32 current_time, char *tcstring)
std::list LLEventTimer::sActiveList;
LLEventTimer::LLEventTimer(F32 period)
-: mTimer()
+: mEventTimer()
{
mPeriod = period;
sActiveList.push_back(this);
@@ -528,9 +528,9 @@ void LLEventTimer::updateClass()
for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); )
{
LLEventTimer* timer = *iter++;
- F32 et = timer->mTimer.getElapsedTimeF32();
+ F32 et = timer->mEventTimer.getElapsedTimeF32();
if (et > timer->mPeriod) {
- timer->mTimer.reset();
+ timer->mEventTimer.reset();
timer->tick();
}
}
diff --git a/linden/indra/llcommon/lltimer.h b/linden/indra/llcommon/lltimer.h
index 94dcbb9..37917d0 100644
--- a/linden/indra/llcommon/lltimer.h
+++ b/linden/indra/llcommon/lltimer.h
@@ -151,7 +151,7 @@ public:
static void updateClass();
protected:
- LLTimer mTimer;
+ LLTimer mEventTimer;
F32 mPeriod;
private:
diff --git a/linden/indra/llcommon/lluri.cpp b/linden/indra/llcommon/lluri.cpp
index 83de022..43d2147 100644
--- a/linden/indra/llcommon/lluri.cpp
+++ b/linden/indra/llcommon/lluri.cpp
@@ -295,9 +295,10 @@ LLURI LLURI::buildHTTP(const std::string& prefix,
const LLSD& query)
{
LLURI uri = buildHTTP(prefix, path);
- uri.mEscapedQuery = mapToQueryString(query);
// break out and escape each query component
- uri.mEscapedOpaque += "?" + uri.mEscapedQuery ;
+ uri.mEscapedQuery = mapToQueryString(query);
+ uri.mEscapedOpaque += uri.mEscapedQuery ;
+ uri.mEscapedQuery.erase(0,1); // trim the leading '?'
return uri;
}
@@ -601,20 +602,30 @@ LLSD LLURI::queryMap(std::string escaped_query_string)
std::string LLURI::mapToQueryString(const LLSD& queryMap)
{
std::string query_string;
-
if (queryMap.isMap())
{
- for (LLSD::map_const_iterator iter = queryMap.beginMap();
- iter != queryMap.endMap();
- iter++)
+ bool first_element = true;
+ LLSD::map_const_iterator iter = queryMap.beginMap();
+ LLSD::map_const_iterator end = queryMap.endMap();
+ std::ostringstream ostr;
+ for (; iter != end; ++iter)
{
- query_string += escapeQueryVariable(iter->first) +
- (iter->second.isUndefined() ? "" : "=" + escapeQueryValue(iter->second.asString())) + "&" ;
+ if(first_element)
+ {
+ ostr << "?";
+ first_element = false;
+ }
+ else
+ {
+ ostr << "&";
+ }
+ ostr << escapeQueryVariable(iter->first);
+ if(iter->second.isDefined())
+ {
+ ostr << "=" << escapeQueryValue(iter->second.asString());
+ }
}
- //if (queryMap.size() > 0)
- //{
- // query_string += "?" + query_string ;
- //}
+ query_string = ostr.str();
}
return query_string;
}
diff --git a/linden/indra/llcommon/lluri.h b/linden/indra/llcommon/lluri.h
index 3f24799..1044c48 100644
--- a/linden/indra/llcommon/lluri.h
+++ b/linden/indra/llcommon/lluri.h
@@ -58,34 +58,42 @@ public:
// construct from escaped string, as would be transmitted on the net
- ~LLURI();
+ ~LLURI();
- static LLURI buildHTTP(const std::string& prefix,
- const LLSD& path);
- static LLURI buildHTTP(const std::string& prefix,
- const LLSD& path,
- const LLSD& query);
- // prefix is either a full URL prefix of the form "http://example.com:8080",
- // or it can be simply a host and optional port like "example.com" or
- // "example.com:8080", in these cases, the "http://" will be added
+ static LLURI buildHTTP(
+ const std::string& prefix,
+ const LLSD& path);
- static LLURI buildHTTP(const std::string& host,
- const U32& port,
- const LLSD& path);
- static LLURI buildHTTP(const std::string& host,
- const U32& port,
- const LLSD& path,
- const LLSD& query);
- std::string asString() const;
- // the whole URI, escaped as needed
+ static LLURI buildHTTP(
+ const std::string& prefix,
+ const LLSD& path,
+ const LLSD& query);
+ ///< prefix is either a full URL prefix of the form
+ /// "http://example.com:8080", or it can be simply a host and
+ /// optional port like "example.com" or "example.com:8080", in
+ /// these cases, the "http://" will be added
+
+ static LLURI buildHTTP(
+ const std::string& host,
+ const U32& port,
+ const LLSD& path);
+ static LLURI buildHTTP(
+ const std::string& host,
+ const U32& port,
+ const LLSD& path,
+ const LLSD& query);
+
+ std::string asString() const;
+ ///< the whole URI, escaped as needed
- // Parts of a URI
- // These functions return parts of the decoded URI. The returned
- // strings are un-escaped as needed
+ /** @name Parts of a URI */
+ //@{
+ // These functions return parts of the decoded URI. The returned
+ // strings are un-escaped as needed
- // for all schemes
- std::string scheme() const; // ex.: "http", note lack of colon
- std::string opaque() const; // everything after the colon
+ // for all schemes
+ std::string scheme() const; ///< ex.: "http", note lack of colon
+ std::string opaque() const; ///< everything after the colon
// for schemes that follow path like syntax (http, https, ftp)
std::string authority() const; // ex.: "host.com:80"
@@ -101,27 +109,34 @@ public:
const std::string& escapedQuery() const { return mEscapedQuery; }
LLSD queryMap() const; // above decoded into a map
static LLSD queryMap(std::string escaped_query_string);
- static std::string mapToQueryString(const LLSD& queryMap);
- // Escaping Utilities
- // Escape a string by urlencoding all the characters that aren't in the allowed string.
- static std::string escape(const std::string& str);
- static std::string escape(const std::string& str, const std::string & allowed);
- static std::string unescape(const std::string& str);
+ /**
+ * @brief given a name value map, return a serialized query string.
+ *
+
+ * @param query_map a map of name value. every value must be
+ * representable as a string.
+ * @return Returns an url query string of '?n1=v1&n2=v2&...'
+ */
+ static std::string mapToQueryString(const LLSD& query_map);
- // Functions for building specific URIs for web services
- // *NOTE: DEPRECATED. use the service builder instead.
- //static LLURI buildBulkAgentNamesURI(LLApp* app);
- //static LLURI buildAgentSessionURI(const LLUUID& agent_id, LLApp* app);
- //static LLURI buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& dataserver);
- //static LLURI buildAgentNameURI(const LLUUID& agent_id, LLApp* app);
+ /** @name Escaping Utilities */
+ //@{
+ // Escape a string by urlencoding all the characters that aren't
+ // in the allowed string.
+ static std::string escape(const std::string& str);
+ static std::string escape(
+ const std::string& str,
+ const std::string & allowed);
+ static std::string unescape(const std::string& str);
+ //@}
private:
- std::string mScheme;
- std::string mEscapedOpaque;
- std::string mEscapedAuthority;
- std::string mEscapedPath;
- std::string mEscapedQuery;
+ std::string mScheme;
+ std::string mEscapedOpaque;
+ std::string mEscapedAuthority;
+ std::string mEscapedPath;
+ std::string mEscapedQuery;
};
#endif // LL_LLURI_H
diff --git a/linden/indra/llcommon/llversion.h b/linden/indra/llcommon/llversion.h
index 9739d04..555698d 100644
--- a/linden/indra/llcommon/llversion.h
+++ b/linden/indra/llcommon/llversion.h
@@ -31,7 +31,7 @@
const S32 LL_VERSION_MAJOR = 1;
const S32 LL_VERSION_MINOR = 18;
-const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 6;
+const S32 LL_VERSION_PATCH = 1;
+const S32 LL_VERSION_BUILD = 2;
#endif
diff --git a/linden/indra/llcommon/llworkerthread.cpp b/linden/indra/llcommon/llworkerthread.cpp
index aa0bedf..b4d9485 100644
--- a/linden/indra/llcommon/llworkerthread.cpp
+++ b/linden/indra/llcommon/llworkerthread.cpp
@@ -104,6 +104,8 @@ S32 LLWorkerThread::update(U32 max_time_ms)
}
delete *iter;
}
+ // delete and aborted entries mean there's still work to do
+ res += delete_list.size() + abort_list.size();
return res;
}
diff --git a/linden/indra/llcommon/stdtypes.h b/linden/indra/llcommon/stdtypes.h
index 16b57fa..118278f 100644
--- a/linden/indra/llcommon/stdtypes.h
+++ b/linden/indra/llcommon/stdtypes.h
@@ -31,18 +31,18 @@
#include
#include
-typedef signed char S8;
+typedef signed char S8;
typedef unsigned char U8;
typedef signed short S16;
typedef unsigned short U16;
-typedef signed int S32;
+typedef signed int S32;
typedef unsigned int U32;
#if LL_WINDOWS
// Windows wchar_t is 16-bit
-typedef U32 llwchar;
+typedef U32 llwchar;
#else
-typedef wchar_t llwchar;
+typedef wchar_t llwchar;
#endif
#if LL_WINDOWS
@@ -53,20 +53,20 @@ typedef unsigned __int64 U64;
#define U64L(a) (a)
#else
typedef long long int S64;
-typedef long long unsigned int U64;
-#if LL_DARWIN || LL_LINUX
-#define S64L(a) (a##LL)
-#define U64L(a) (a##ULL)
+typedef long long unsigned int U64;
+#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+#define S64L(a) (a##LL)
+#define U64L(a) (a##ULL)
#endif
#endif
-typedef float F32;
-typedef double F64;
+typedef float F32;
+typedef double F64;
typedef S32 BOOL;
typedef U8 KEY;
typedef U32 MASK;
-typedef U32 TPACKETID;
+typedef U32 TPACKETID;
// Use #define instead of consts to avoid conversion headaches
#define S8_MAX (SCHAR_MAX)
diff --git a/linden/indra/llcommon/timing.h b/linden/indra/llcommon/timing.h
index 662d22b..b799001 100644
--- a/linden/indra/llcommon/timing.h
+++ b/linden/indra/llcommon/timing.h
@@ -31,7 +31,7 @@
#include
-#if LL_LINUX || LL_DARWIN
+#if LL_LINUX || LL_DARWIN || LL_SOLARIS
# include
#endif
diff --git a/linden/indra/llimage/llimagejpeg.h b/linden/indra/llimage/llimagejpeg.h
index aca780d..34b3f76 100644
--- a/linden/indra/llimage/llimagejpeg.h
+++ b/linden/indra/llimage/llimagejpeg.h
@@ -34,8 +34,13 @@
#include "llimage.h"
extern "C" {
-#include "jpeglib/jpeglib.h"
-#include "jpeglib/jerror.h"
+#ifdef LL_STANDALONE
+# include
+# include
+#else
+# include "jpeglib/jpeglib.h"
+# include "jpeglib/jerror.h"
+#endif
}
class LLImageJPEG : public LLImageFormatted
diff --git a/linden/indra/llinventory/llinventory.cpp b/linden/indra/llinventory/llinventory.cpp
index 93c480e..3800de2 100644
--- a/linden/indra/llinventory/llinventory.cpp
+++ b/linden/indra/llinventory/llinventory.cpp
@@ -535,7 +535,11 @@ BOOL LLInventoryItem::importFile(FILE* fp)
mAssetUUID.setNull();
while(success && (!feof(fp)))
{
- fgets(buffer, MAX_STRING, fp);
+ if (fgets(buffer, MAX_STRING, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
if(0 == strcmp("{",keyword))
{
@@ -1391,7 +1395,11 @@ BOOL LLInventoryCategory::importFile(FILE* fp)
valuestr[0] = '\0';
while(!feof(fp))
{
- fgets(buffer, MAX_STRING, fp);
+ if (fgets(buffer, MAX_STRING, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf( /* Flawfinder: ignore */
buffer,
" %254s %254s",
diff --git a/linden/indra/llinventory/llpermissions.cpp b/linden/indra/llinventory/llpermissions.cpp
index ae4360a..925b68f 100644
--- a/linden/indra/llinventory/llpermissions.cpp
+++ b/linden/indra/llinventory/llpermissions.cpp
@@ -526,7 +526,11 @@ BOOL LLPermissions::importFile(FILE* fp)
while (!feof(fp))
{
- fgets(buffer, BUFSIZE, fp);
+ if (fgets(buffer, BUFSIZE, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf( /* Flawfinder: ignore */
buffer,
" %255s %255s",
diff --git a/linden/indra/llinventory/llsaleinfo.cpp b/linden/indra/llinventory/llsaleinfo.cpp
index debb092..0258259 100644
--- a/linden/indra/llinventory/llsaleinfo.cpp
+++ b/linden/indra/llinventory/llsaleinfo.cpp
@@ -170,7 +170,11 @@ BOOL LLSaleInfo::importFile(FILE* fp, BOOL& has_perm_mask, U32& perm_mask)
valuestr[0] = '\0';
while(success && (!feof(fp)))
{
- fgets(buffer, MAX_STRING, fp);
+ if (fgets(buffer, MAX_STRING, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf( /* Flawfinder: ignore */
buffer,
" %254s %254s",
diff --git a/linden/indra/llmath/llcrc.cpp b/linden/indra/llmath/llcrc.cpp
index cc0f955..5b3ab4b 100644
--- a/linden/indra/llmath/llcrc.cpp
+++ b/linden/indra/llmath/llcrc.cpp
@@ -154,11 +154,11 @@ void LLCRC::update(U8 next_byte)
mCurrent = UPDC32(next_byte, mCurrent);
}
-void LLCRC::update(const U8* buffer, U32 buffer_size)
+void LLCRC::update(const U8* buffer, size_t buffer_size)
{
- for ( ; buffer_size; --buffer_size, ++buffer)
+ for (size_t i = 0; i < buffer_size; i++)
{
- mCurrent = UPDC32(*buffer, mCurrent);
+ mCurrent = UPDC32(buffer[i], mCurrent);
}
}
@@ -175,17 +175,24 @@ void LLCRC::update(const char* filename)
if (fp)
{
fseek(fp, 0, SEEK_END);
- U32 size = ftell(fp);
+ long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (size > 0)
{
U8* data = new U8[size];
- fread(data, size, 1, fp);
+ size_t nread;
+
+ nread = fread(data, 1, size, fp);
fclose(fp);
+
+ if (nread < (size_t) size)
+ {
+ llwarns << "Short read on " << filename << llendl;
+ }
- update(data, size);
+ update(data, nread);
delete[] data;
}
}
diff --git a/linden/indra/llmath/llcrc.h b/linden/indra/llmath/llcrc.h
index 06ddac2..9f71fcc 100644
--- a/linden/indra/llmath/llcrc.h
+++ b/linden/indra/llmath/llcrc.h
@@ -56,7 +56,7 @@ public:
U32 getCRC() const;
void update(U8 next_byte);
- void update(const U8* buffer, U32 buffer_size);
+ void update(const U8* buffer, size_t buffer_size);
void update(const char *filename);
#ifdef _DEBUG
diff --git a/linden/indra/llmath/llmath.h b/linden/indra/llmath/llmath.h
index dd44e0c..9be2524 100644
--- a/linden/indra/llmath/llmath.h
+++ b/linden/indra/llmath/llmath.h
@@ -42,6 +42,9 @@
#elif (LL_LINUX && __GNUC__ <= 2)
#define llisnan(val) isnan(val)
#define llfinite(val) isfinite(val)
+#elif LL_SOLARIS
+#define llisnan(val) isnan(val)
+#define llfinite(val) (val <= std::numeric_limits::max())
#else
#define llisnan(val) std::isnan(val)
#define llfinite(val) std::isfinite(val)
diff --git a/linden/indra/llmath/llmath.vcproj b/linden/indra/llmath/llmath.vcproj
index 4876065..bdc8ded 100644
--- a/linden/indra/llmath/llmath.vcproj
+++ b/linden/indra/llmath/llmath.vcproj
@@ -272,6 +272,18 @@
RelativePath=".\lluuid.h">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linden/indra/llmath/llmd5.cpp b/linden/indra/llmath/llmd5.cpp
index aad4617..1a8630c 100644
--- a/linden/indra/llmath/llmd5.cpp
+++ b/linden/indra/llmath/llmd5.cpp
@@ -83,6 +83,9 @@ documentation and/or software.
#include
#include
+// how many bytes to grab at a time when checking files
+const int LLMD5::BLOCK_LEN = 4096;
+
// LLMD5 simple initialization method
@@ -156,10 +159,10 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
void LLMD5::update(FILE* file){
- unsigned char buffer[1024]; /* Flawfinder: ignore */
+ unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
int len;
- while ( (len=(int)fread(buffer, 1, 1024, file)) )
+ while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) )
update(buffer, len);
fclose (file);
@@ -176,11 +179,11 @@ void LLMD5::update(FILE* file){
void LLMD5::update(std::istream& stream){
- unsigned char buffer[1024]; /* Flawfinder: ignore */
+ unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
int len;
while (stream.good()){
- stream.read( (char*)buffer, 1024); /* Flawfinder: ignore */ // note that return value of read is unusable.
+ stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
len=stream.gcount();
update(buffer, len);
}
@@ -366,11 +369,48 @@ void LLMD5::init(){
#define S43 15
#define S44 21
+// #defines are faster then inline, etc because the compiler is not required to inline.
+// Timing tests prove that this works ~40% faster on win with msvc++2k3 over using static inline.
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (U32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (U32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (U32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (U32)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
// LLMD5 basic transformation. Transforms state based on block.
-void LLMD5::transform (const uint1 block[64]){
+void LLMD5::transform (const U8 block[64]){
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
@@ -489,64 +529,3 @@ void LLMD5::decode (uint4 *output, const uint1 *input, const uint4 len){
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
}
-
-
-
-
-
-// ROTATE_LEFT rotates x left n bits.
-
-inline unsigned int LLMD5::rotate_left (uint4 x, uint4 n){
- return (x << n) | (x >> (32-n)) ;
-}
-
-
-
-
-// F, G, H and I are basic MD5 functions.
-
-inline unsigned int LLMD5::F (uint4 x, uint4 y, uint4 z){
- return (x & y) | (~x & z);
-}
-
-inline unsigned int LLMD5::G (uint4 x, uint4 y, uint4 z){
- return (x & z) | (y & ~z);
-}
-
-inline unsigned int LLMD5::H (uint4 x, uint4 y, uint4 z){
- return x ^ y ^ z;
-}
-
-inline unsigned int LLMD5::I (uint4 x, uint4 y, uint4 z){
- return y ^ (x | ~z);
-}
-
-
-
-// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-// Rotation is separate from addition to prevent recomputation.
-
-
-inline void LLMD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac){
- a += F(b, c, d) + x + ac;
- a = rotate_left (a, s) +b;
-}
-
-inline void LLMD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac){
- a += G(b, c, d) + x + ac;
- a = rotate_left (a, s) +b;
-}
-
-inline void LLMD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac){
- a += H(b, c, d) + x + ac;
- a = rotate_left (a, s) +b;
-}
-
-inline void LLMD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac){
- a += I(b, c, d) + x + ac;
- a = rotate_left (a, s) +b;
-}
diff --git a/linden/indra/llmath/llmd5.h b/linden/indra/llmath/llmd5.h
index 20c32ed..5df98bf 100644
--- a/linden/indra/llmath/llmd5.h
+++ b/linden/indra/llmath/llmd5.h
@@ -85,6 +85,9 @@ class LLMD5 {
typedef unsigned short int uint2; // assumes short integer is 2 words long
typedef unsigned char uint1; // assumes char is 1 word long
+// how many bytes to grab at a time when checking files
+ static const int BLOCK_LEN;
+
public:
// methods for controlled operation:
LLMD5 (); // simple initializer
@@ -125,20 +128,6 @@ private:
static void encode (uint1 *dest, const uint4 *src, const uint4 length);
static void decode (uint4 *dest, const uint1 *src, const uint4 length);
- static inline uint4 rotate_left (uint4 x, uint4 n);
- static inline uint4 F (uint4 x, uint4 y, uint4 z);
- static inline uint4 G (uint4 x, uint4 y, uint4 z);
- static inline uint4 H (uint4 x, uint4 y, uint4 z);
- static inline uint4 I (uint4 x, uint4 y, uint4 z);
- static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac);
- static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac);
- static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac);
- static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
- uint4 s, uint4 ac);
-
};
#endif // LL_LLMD5_H
diff --git a/linden/indra/llmath/lloctree.h b/linden/indra/llmath/lloctree.h
index 004b0a2..2395f0f 100644
--- a/linden/indra/llmath/lloctree.h
+++ b/linden/indra/llmath/lloctree.h
@@ -95,34 +95,34 @@ public:
}
}
- virtual ~LLOctreeNode() { BaseType::destroyListeners(); delete this->mState; }
-
- virtual const BaseType* getParent() const { return mParent; }
- virtual void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
- virtual const LLVector3d& getCenter() const { return mCenter; }
- virtual const LLVector3d& getSize() const { return mSize; }
- virtual void setCenter(LLVector3d center) { mCenter = center; }
- virtual void setSize(LLVector3d size) { mSize = size; }
- virtual bool balance() { return getOctState()->balance(); }
- virtual void validate() { getOctState()->validate(); }
- virtual U32 getChildCount() const { return getOctState()->getChildCount(); }
- virtual oct_node* getChild(U32 index) { return getOctState()->getChild(index); }
- virtual const oct_node* getChild(U32 index) const { return getOctState()->getChild(index); }
- virtual U32 getElementCount() const { return getOctState()->getElementCount(); }
- virtual void removeByAddress(T* data) { getOctState()->removeByAddress(data); }
- virtual bool hasLeafState() const { return getOctState()->isLeaf(); }
- virtual void destroy() { getOctState()->destroy(); }
- virtual oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
- virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); }
- virtual U8 getOctant() const { return mOctant; }
- virtual void setOctant(U8 octant) { mOctant = octant; }
- virtual const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; }
- virtual oct_state* getOctState() { return (oct_state*) BaseType::mState; }
- virtual const oct_node* getOctParent() const { return (const oct_node*) getParent(); }
- virtual oct_node* getOctParent() { return (oct_node*) getParent(); }
- virtual void deleteChild(oct_node* child) { getOctState()->deleteChild(child); }
-
- virtual U8 getOctant(const F64 pos[]) const //get the octant pos is in
+ ~LLOctreeNode() { BaseType::destroyListeners(); delete this->mState; }
+
+ inline const BaseType* getParent() const { return mParent; }
+ inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
+ inline const LLVector3d& getCenter() const { return mCenter; }
+ inline const LLVector3d& getSize() const { return mSize; }
+ inline void setCenter(LLVector3d center) { mCenter = center; }
+ inline void setSize(LLVector3d size) { mSize = size; }
+ inline bool balance() { return getOctState()->balance(); }
+ inline void validate() { getOctState()->validate(); }
+ inline U32 getChildCount() const { return getOctState()->getChildCount(); }
+ inline oct_node* getChild(U32 index) { return getOctState()->getChild(index); }
+ inline const oct_node* getChild(U32 index) const { return getOctState()->getChild(index); }
+ inline U32 getElementCount() const { return getOctState()->getElementCount(); }
+ inline void removeByAddress(T* data) { getOctState()->removeByAddress(data); }
+ inline bool hasLeafState() const { return getOctState()->isLeaf(); }
+ inline void destroy() { getOctState()->destroy(); }
+ inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
+ inline oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); }
+ inline U8 getOctant() const { return mOctant; }
+ inline void setOctant(U8 octant) { mOctant = octant; }
+ inline const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; }
+ inline oct_state* getOctState() { return (oct_state*) BaseType::mState; }
+ inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); }
+ inline oct_node* getOctParent() { return (oct_node*) getParent(); }
+ inline void deleteChild(oct_node* child) { getOctState()->deleteChild(child); }
+
+ U8 getOctant(const F64 pos[]) const //get the octant pos is in
{
U8 ret = 0;
@@ -142,17 +142,17 @@ public:
return ret;
}
- virtual bool isInside(const LLVector3d& pos, const F64& rad) const
+ inline bool isInside(const LLVector3d& pos, const F64& rad) const
{
return rad <= mSize.mdV[0]*2.0 && isInside(pos);
}
- virtual bool isInside(T* data) const
+ inline bool isInside(T* data) const
{
return isInside(data->getPositionGroup(), data->getBinRadius());
}
- virtual bool isInside(const LLVector3d& pos) const
+ bool isInside(const LLVector3d& pos) const
{
const F64& x = pos.mdV[0];
const F64& y = pos.mdV[1];
@@ -168,7 +168,7 @@ public:
return true;
}
- virtual void updateMinMax()
+ void updateMinMax()
{
for (U32 i = 0; i < 3; i++)
{
@@ -178,12 +178,12 @@ public:
}
}
- virtual oct_listener* getOctListener(U32 index)
+ inline oct_listener* getOctListener(U32 index)
{
return (oct_listener*) BaseType::getListener(index);
}
- bool contains(T* xform)
+ inline bool contains(T* xform)
{
return contains(xform->getBinRadius());
}
diff --git a/linden/indra/llmath/llrect.h b/linden/indra/llmath/llrect.h
index a17ab39..38a4983 100644
--- a/linden/indra/llmath/llrect.h
+++ b/linden/indra/llmath/llrect.h
@@ -213,47 +213,28 @@ public:
mBottom = llmin(mBottom, mTop);
}
- friend const LLRectBase& operator|=(LLRectBase &a, const LLRectBase &b) // Return rect including a & b
+ void unionWith(const LLRectBase &other)
{
- a.mLeft = llmin(a.mLeft, b.mLeft);
- a.mRight = llmax(a.mRight, b.mRight);
- a.mBottom = llmin(a.mBottom, b.mBottom);
- a.mTop = llmax(a.mTop, b.mTop);
- return a;
+ mLeft = llmin(mLeft, other.mLeft);
+ mRight = llmax(mRight, other.mRight);
+ mBottom = llmin(mBottom, other.mBottom);
+ mTop = llmax(mTop, other.mTop);
}
- friend LLRectBase operator|(const LLRectBase &a, const LLRectBase &b) // Return rect including a & b
+ void intersectWith(const LLRectBase &other)
{
- LLRectBase result;
- result.mLeft = llmin(a.mLeft, b.mLeft);
- result.mRight = llmax(a.mRight, b.mRight);
- result.mBottom = llmin(a.mBottom, b.mBottom);
- result.mTop = llmax(a.mTop, b.mTop);
- return result;
- }
-
- friend const LLRectBase& operator&=(LLRectBase &a, const LLRectBase &b) // set a to rect where a intersects b
- {
- a.mLeft = llmax(a.mLeft, b.mLeft);
- a.mRight = llmin(a.mRight, b.mRight);
- a.mBottom = llmax(a.mBottom, b.mBottom);
- a.mTop = llmin(a.mTop, b.mTop);
- if (a.mLeft > a.mRight)
+ mLeft = llmax(mLeft, other.mLeft);
+ mRight = llmin(mRight, other.mRight);
+ mBottom = llmax(mBottom, other.mBottom);
+ mTop = llmin(mTop, other.mTop);
+ if (mLeft > mRight)
{
- a.mLeft = a.mRight;
+ mLeft = mRight;
}
- if (a.mBottom > a.mTop)
+ if (mBottom > mTop)
{
- a.mBottom = a.mTop;
+ mBottom = mTop;
}
- return a;
- }
-
- friend LLRectBase operator&(const LLRectBase &a, const LLRectBase &b) // Return rect where a intersects b
- {
- LLRectBase result = a;
- result &= b;
- return result;
}
friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
diff --git a/linden/indra/llmath/lltreenode.h b/linden/indra/llmath/lltreenode.h
index a47795d..8a8710f 100644
--- a/linden/indra/llmath/lltreenode.h
+++ b/linden/indra/llmath/lltreenode.h
@@ -69,17 +69,17 @@ class LLTreeNode
public:
LLTreeNode(LLTreeState* state) { setState(state); }
virtual ~LLTreeNode();
- virtual LLTreeState* getState() { return mState; }
- virtual const LLTreeState* getState() const { return mState; }
-
- virtual void setState(LLTreeState* state);
- virtual void insert(T* data);
- virtual bool remove(T* data);
- virtual void notifyRemoval(T* data);
- virtual U32 getListenerCount() { return mListeners.size(); }
- virtual LLTreeListener* getListener(U32 index) const { return mListeners[index]; }
- virtual void addListener(LLTreeListener* listener) { mListeners.push_back(listener); }
- virtual void removeListener(U32 index) { mListeners.erase(mListeners.begin()+index); }
+ LLTreeState* getState() { return mState; }
+ const LLTreeState* getState() const { return mState; }
+
+ void setState(LLTreeState* state);
+ void insert(T* data);
+ bool remove(T* data);
+ void notifyRemoval(T* data);
+ inline U32 getListenerCount() { return mListeners.size(); }
+ inline LLTreeListener* getListener(U32 index) const { return mListeners[index]; }
+ inline void addListener(LLTreeListener* listener) { mListeners.push_back(listener); }
+ inline void removeListener(U32 index) { mListeners.erase(mListeners.begin()+index); }
protected:
void destroyListeners()
diff --git a/linden/indra/llmath/lluuid.cpp b/linden/indra/llmath/lluuid.cpp
index 0fed6b3..97d8c1c 100644
--- a/linden/indra/llmath/lluuid.cpp
+++ b/linden/indra/llmath/lluuid.cpp
@@ -613,7 +613,9 @@ S32 LLUUID::getNodeID(unsigned char *node_id)
#define HAVE_NETINET_IN_H
#ifdef HAVE_NETINET_IN_H
#include
-#if !LL_DARWIN
+#if LL_SOLARIS
+#include
+#elif !LL_DARWIN
#include
#endif
#endif
diff --git a/linden/indra/llmath/llv4math.h b/linden/indra/llmath/llv4math.h
new file mode 100644
index 0000000..2853ab6
--- /dev/null
+++ b/linden/indra/llmath/llv4math.h
@@ -0,0 +1,143 @@
+/**
+ * @file llv4math.h
+ * @brief LLV4* class header file - vector processor enabled math
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#ifndef LL_LLV4MATH_H
+#define LL_LLV4MATH_H
+
+// *NOTE: We do not support SSE acceleration on Windows builds.
+// Our minimum specification for the viewer includes 1 GHz Athlon processors,
+// which covers the Athlon Thunderbird series that does not support SSE.
+//
+// Our header files include statements like this
+// const F32 HAVOK_TIMESTEP = 1.f / 45.f;
+// This creates "globals" that are included in each .obj file. If a single
+// .cpp file has SSE code generation turned on (eg, llviewerjointmesh_sse.cpp)
+// these globals will be initialized using SSE instructions. This causes SL
+// to crash before main() on processors without SSE. Untangling all these
+// headers/variables is too much work for the small performance gains of
+// vectorization.
+//
+// Therefore we only support vectorization on builds where the everything is
+// built with SSE or Altivec. See https://jira.secondlife.com/browse/VWR-1610
+// and https://jira.lindenlab.com/browse/SL-47720 for details.
+//
+// Sorry the code is such a mess. JC
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4MATH - GNUC
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if LL_GNUC && __GNUC__ >= 4 && __SSE__
+
+#define LL_VECTORIZE 1
+
+#if LL_DARWIN
+
+#include
+#include
+typedef vFloat V4F32;
+
+#else
+
+#include
+typedef float V4F32 __attribute__((vector_size(16)));
+
+#endif
+
+#endif
+#if LL_GNUC
+
+#define LL_LLV4MATH_ALIGN_PREFIX
+#define LL_LLV4MATH_ALIGN_POSTFIX __attribute__((aligned(16)))
+
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4MATH - MSVC
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+// Only vectorize if the entire Windows build uses SSE.
+// _M_IX86_FP is set when SSE code generation is turned on, and I have
+// confirmed this in VS2003, VS2003 SP1, and VS2005. JC
+#if LL_MSVC && _M_IX86_FP
+
+#define LL_VECTORIZE 1
+
+#include
+
+typedef __m128 V4F32;
+
+#endif
+#if LL_MSVC
+
+#define LL_LLV4MATH_ALIGN_PREFIX __declspec(align(16))
+#define LL_LLV4MATH_ALIGN_POSTFIX
+
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4MATH - default - no vectorization
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if !LL_VECTORIZE
+
+#define LL_VECTORIZE 0
+
+struct V4F32 { F32 __pad__[4]; };
+
+inline F32 llv4lerp(F32 a, F32 b, F32 w) { return ( b - a ) * w + a; }
+
+#endif
+
+#ifndef LL_LLV4MATH_ALIGN_PREFIX
+# define LL_LLV4MATH_ALIGN_PREFIX
+#endif
+#ifndef LL_LLV4MATH_ALIGN_POSTFIX
+# define LL_LLV4MATH_ALIGN_POSTFIX
+#endif
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4MATH
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+
+#define LLV4_NUM_AXIS 4
+
+class LLV4Vector3;
+class LLV4Matrix3;
+class LLV4Matrix4;
+
+#endif
diff --git a/linden/indra/llmath/llv4matrix3.h b/linden/indra/llmath/llv4matrix3.h
new file mode 100644
index 0000000..0811338
--- /dev/null
+++ b/linden/indra/llmath/llv4matrix3.h
@@ -0,0 +1,222 @@
+/**
+ * @file llviewerjointmesh.cpp
+ * @brief LLV4* class header file - vector processor enabled math
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#ifndef LL_LLV4MATRIX3_H
+#define LL_LLV4MATRIX3_H
+
+#include "llv4math.h"
+#include "llv4vector3.h"
+#include "m3math.h" // for operator LLMatrix3()
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix3
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+LL_LLV4MATH_ALIGN_PREFIX
+
+class LLV4Matrix3
+{
+public:
+ union {
+ F32 mMatrix[LLV4_NUM_AXIS][LLV4_NUM_AXIS];
+ V4F32 mV[LLV4_NUM_AXIS];
+ };
+
+ void lerp(const LLV4Matrix3 &a, const LLV4Matrix3 &b, const F32 &w);
+ void multiply(const LLVector3 &a, LLVector3& out) const;
+ void multiply(const LLVector4 &a, LLV4Vector3& out) const;
+ void multiply(const LLVector3 &a, LLV4Vector3& out) const;
+
+ const LLV4Matrix3& transpose();
+ const LLV4Matrix3& operator=(const LLMatrix3& a);
+
+ operator LLMatrix3() const { return (reinterpret_cast(const_cast(&mMatrix[0][0])))->getMat3(); }
+
+ friend LLVector3 operator*(const LLVector3& a, const LLV4Matrix3& b);
+}
+
+LL_LLV4MATH_ALIGN_POSTFIX;
+
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix3 - SSE
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if LL_VECTORIZE
+
+inline void LLV4Matrix3::lerp(const LLV4Matrix3 &a, const LLV4Matrix3 &b, const F32 &w)
+{
+ __m128 vw = _mm_set1_ps(w);
+ mV[VX] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VX], a.mV[VX]), vw), a.mV[VX]); // ( b - a ) * w + a
+ mV[VY] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VY], a.mV[VY]), vw), a.mV[VY]);
+ mV[VZ] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VZ], a.mV[VZ]), vw), a.mV[VZ]);
+}
+
+inline void LLV4Matrix3::multiply(const LLVector3 &a, LLVector3& o) const
+{
+ LLV4Vector3 j;
+ j.v = _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX]); // ( ax * vx ) + ...
+ j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
+ j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
+ o.setVec(j.mV);
+}
+
+inline void LLV4Matrix3::multiply(const LLVector4 &a, LLV4Vector3& o) const
+{
+ o.v = _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX]); // ( ax * vx ) + ...
+ o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
+ o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
+}
+
+inline void LLV4Matrix3::multiply(const LLVector3 &a, LLV4Vector3& o) const
+{
+ o.v = _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX]); // ( ax * vx ) + ...
+ o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
+ o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix3
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#else
+
+inline void LLV4Matrix3::lerp(const LLV4Matrix3 &a, const LLV4Matrix3 &b, const F32 &w)
+{
+ mMatrix[VX][VX] = llv4lerp(a.mMatrix[VX][VX], b.mMatrix[VX][VX], w);
+ mMatrix[VX][VY] = llv4lerp(a.mMatrix[VX][VY], b.mMatrix[VX][VY], w);
+ mMatrix[VX][VZ] = llv4lerp(a.mMatrix[VX][VZ], b.mMatrix[VX][VZ], w);
+
+ mMatrix[VY][VX] = llv4lerp(a.mMatrix[VY][VX], b.mMatrix[VY][VX], w);
+ mMatrix[VY][VY] = llv4lerp(a.mMatrix[VY][VY], b.mMatrix[VY][VY], w);
+ mMatrix[VY][VZ] = llv4lerp(a.mMatrix[VY][VZ], b.mMatrix[VY][VZ], w);
+
+ mMatrix[VZ][VX] = llv4lerp(a.mMatrix[VZ][VX], b.mMatrix[VZ][VX], w);
+ mMatrix[VZ][VY] = llv4lerp(a.mMatrix[VZ][VY], b.mMatrix[VZ][VY], w);
+ mMatrix[VZ][VZ] = llv4lerp(a.mMatrix[VZ][VZ], b.mMatrix[VZ][VZ], w);
+}
+
+inline void LLV4Matrix3::multiply(const LLVector3 &a, LLVector3& o) const
+{
+ o.setVec( a.mV[VX] * mMatrix[VX][VX] +
+ a.mV[VY] * mMatrix[VY][VX] +
+ a.mV[VZ] * mMatrix[VZ][VX],
+
+ a.mV[VX] * mMatrix[VX][VY] +
+ a.mV[VY] * mMatrix[VY][VY] +
+ a.mV[VZ] * mMatrix[VZ][VY],
+
+ a.mV[VX] * mMatrix[VX][VZ] +
+ a.mV[VY] * mMatrix[VY][VZ] +
+ a.mV[VZ] * mMatrix[VZ][VZ]);
+}
+
+inline void LLV4Matrix3::multiply(const LLVector4 &a, LLV4Vector3& o) const
+{
+ o.setVec( a.mV[VX] * mMatrix[VX][VX] +
+ a.mV[VY] * mMatrix[VY][VX] +
+ a.mV[VZ] * mMatrix[VZ][VX],
+
+ a.mV[VX] * mMatrix[VX][VY] +
+ a.mV[VY] * mMatrix[VY][VY] +
+ a.mV[VZ] * mMatrix[VZ][VY],
+
+ a.mV[VX] * mMatrix[VX][VZ] +
+ a.mV[VY] * mMatrix[VY][VZ] +
+ a.mV[VZ] * mMatrix[VZ][VZ]);
+}
+
+inline void LLV4Matrix3::multiply(const LLVector3 &a, LLV4Vector3& o) const
+{
+ o.setVec( a.mV[VX] * mMatrix[VX][VX] +
+ a.mV[VY] * mMatrix[VY][VX] +
+ a.mV[VZ] * mMatrix[VZ][VX],
+
+ a.mV[VX] * mMatrix[VX][VY] +
+ a.mV[VY] * mMatrix[VY][VY] +
+ a.mV[VZ] * mMatrix[VZ][VY],
+
+ a.mV[VX] * mMatrix[VX][VZ] +
+ a.mV[VY] * mMatrix[VY][VZ] +
+ a.mV[VZ] * mMatrix[VZ][VZ]);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix3
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#endif
+
+inline const LLV4Matrix3& LLV4Matrix3::transpose()
+{
+#if LL_VECTORIZE && defined(_MM_TRANSPOSE4_PS)
+ _MM_TRANSPOSE4_PS(mV[VX], mV[VY], mV[VZ], mV[VW]);
+ return *this;
+#else
+ F32 temp;
+ temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp;
+ temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp;
+ temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp;
+#endif
+ return *this;
+}
+
+inline const LLV4Matrix3& LLV4Matrix3::operator=(const LLMatrix3& a)
+{
+ memcpy(mMatrix[VX], a.mMatrix[VX], sizeof(F32) * 3 );
+ memcpy(mMatrix[VY], a.mMatrix[VY], sizeof(F32) * 3 );
+ memcpy(mMatrix[VZ], a.mMatrix[VZ], sizeof(F32) * 3 );
+ return *this;
+}
+
+inline LLVector3 operator*(const LLVector3& a, const LLV4Matrix3& b)
+{
+ return LLVector3(
+ a.mV[VX] * b.mMatrix[VX][VX] +
+ a.mV[VY] * b.mMatrix[VY][VX] +
+ a.mV[VZ] * b.mMatrix[VZ][VX],
+
+ a.mV[VX] * b.mMatrix[VX][VY] +
+ a.mV[VY] * b.mMatrix[VY][VY] +
+ a.mV[VZ] * b.mMatrix[VZ][VY],
+
+ a.mV[VX] * b.mMatrix[VX][VZ] +
+ a.mV[VY] * b.mMatrix[VY][VZ] +
+ a.mV[VZ] * b.mMatrix[VZ][VZ] );
+}
+
+#endif
diff --git a/linden/indra/llmath/llv4matrix4.h b/linden/indra/llmath/llv4matrix4.h
new file mode 100644
index 0000000..38280a2
--- /dev/null
+++ b/linden/indra/llmath/llv4matrix4.h
@@ -0,0 +1,251 @@
+/**
+ * @file llviewerjointmesh.cpp
+ * @brief LLV4* class header file - vector processor enabled math
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#ifndef LL_LLV4MATRIX4_H
+#define LL_LLV4MATRIX4_H
+
+#include "llv4math.h"
+#include "llv4matrix3.h" // just for operator LLV4Matrix3()
+#include "llv4vector3.h"
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix4
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+LL_LLV4MATH_ALIGN_PREFIX
+
+class LLV4Matrix4
+{
+public:
+ union {
+ F32 mMatrix[LLV4_NUM_AXIS][LLV4_NUM_AXIS];
+ V4F32 mV[LLV4_NUM_AXIS];
+ };
+
+ void lerp(const LLV4Matrix4 &a, const LLV4Matrix4 &b, const F32 &w);
+ void multiply(const LLVector3 &a, LLVector3& o) const;
+ void multiply(const LLVector3 &a, LLV4Vector3& o) const;
+
+ const LLV4Matrix4& transpose();
+ const LLV4Matrix4& translate(const LLVector3 &vec);
+ const LLV4Matrix4& translate(const LLV4Vector3 &vec);
+ const LLV4Matrix4& operator=(const LLMatrix4& a);
+
+ operator LLMatrix4() const { return *(reinterpret_cast(const_cast(&mMatrix[0][0]))); }
+ operator LLV4Matrix3() const { return *(reinterpret_cast(const_cast(&mMatrix[0][0]))); }
+
+ friend LLVector3 operator*(const LLVector3 &a, const LLV4Matrix4 &b);
+}
+
+LL_LLV4MATH_ALIGN_POSTFIX;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix4 - SSE
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#if LL_VECTORIZE
+
+inline void LLV4Matrix4::lerp(const LLV4Matrix4 &a, const LLV4Matrix4 &b, const F32 &w)
+{
+ __m128 vw = _mm_set1_ps(w);
+ mV[VX] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VX], a.mV[VX]), vw), a.mV[VX]); // ( b - a ) * w + a
+ mV[VY] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VY], a.mV[VY]), vw), a.mV[VY]);
+ mV[VZ] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VZ], a.mV[VZ]), vw), a.mV[VZ]);
+ mV[VW] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VW], a.mV[VW]), vw), a.mV[VW]);
+}
+
+inline void LLV4Matrix4::multiply(const LLVector3 &a, LLVector3& o) const
+{
+ LLV4Vector3 j;
+ j.v = _mm_add_ps(mV[VW], _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX])); // ( ax * vx ) + vw
+ j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
+ j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
+ o.setVec(j.mV);
+}
+
+inline void LLV4Matrix4::multiply(const LLVector3 &a, LLV4Vector3& o) const
+{
+ o.v = _mm_add_ps(mV[VW], _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX])); // ( ax * vx ) + vw
+ o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
+ o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
+}
+
+inline const LLV4Matrix4& LLV4Matrix4::translate(const LLV4Vector3 &vec)
+{
+ mV[VW] = _mm_add_ps(mV[VW], vec.v);
+ return (*this);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix4
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#else
+
+inline void LLV4Matrix4::lerp(const LLV4Matrix4 &a, const LLV4Matrix4 &b, const F32 &w)
+{
+ mMatrix[VX][VX] = llv4lerp(a.mMatrix[VX][VX], b.mMatrix[VX][VX], w);
+ mMatrix[VX][VY] = llv4lerp(a.mMatrix[VX][VY], b.mMatrix[VX][VY], w);
+ mMatrix[VX][VZ] = llv4lerp(a.mMatrix[VX][VZ], b.mMatrix[VX][VZ], w);
+
+ mMatrix[VY][VX] = llv4lerp(a.mMatrix[VY][VX], b.mMatrix[VY][VX], w);
+ mMatrix[VY][VY] = llv4lerp(a.mMatrix[VY][VY], b.mMatrix[VY][VY], w);
+ mMatrix[VY][VZ] = llv4lerp(a.mMatrix[VY][VZ], b.mMatrix[VY][VZ], w);
+
+ mMatrix[VZ][VX] = llv4lerp(a.mMatrix[VZ][VX], b.mMatrix[VZ][VX], w);
+ mMatrix[VZ][VY] = llv4lerp(a.mMatrix[VZ][VY], b.mMatrix[VZ][VY], w);
+ mMatrix[VZ][VZ] = llv4lerp(a.mMatrix[VZ][VZ], b.mMatrix[VZ][VZ], w);
+
+ mMatrix[VW][VX] = llv4lerp(a.mMatrix[VW][VX], b.mMatrix[VW][VX], w);
+ mMatrix[VW][VY] = llv4lerp(a.mMatrix[VW][VY], b.mMatrix[VW][VY], w);
+ mMatrix[VW][VZ] = llv4lerp(a.mMatrix[VW][VZ], b.mMatrix[VW][VZ], w);
+}
+
+inline void LLV4Matrix4::multiply(const LLVector3 &a, LLVector3& o) const
+{
+ o.setVec( a.mV[VX] * mMatrix[VX][VX] +
+ a.mV[VY] * mMatrix[VY][VX] +
+ a.mV[VZ] * mMatrix[VZ][VX] +
+ mMatrix[VW][VX],
+
+ a.mV[VX] * mMatrix[VX][VY] +
+ a.mV[VY] * mMatrix[VY][VY] +
+ a.mV[VZ] * mMatrix[VZ][VY] +
+ mMatrix[VW][VY],
+
+ a.mV[VX] * mMatrix[VX][VZ] +
+ a.mV[VY] * mMatrix[VY][VZ] +
+ a.mV[VZ] * mMatrix[VZ][VZ] +
+ mMatrix[VW][VZ]);
+}
+
+inline void LLV4Matrix4::multiply(const LLVector3 &a, LLV4Vector3& o) const
+{
+ o.setVec( a.mV[VX] * mMatrix[VX][VX] +
+ a.mV[VY] * mMatrix[VY][VX] +
+ a.mV[VZ] * mMatrix[VZ][VX] +
+ mMatrix[VW][VX],
+
+ a.mV[VX] * mMatrix[VX][VY] +
+ a.mV[VY] * mMatrix[VY][VY] +
+ a.mV[VZ] * mMatrix[VZ][VY] +
+ mMatrix[VW][VY],
+
+ a.mV[VX] * mMatrix[VX][VZ] +
+ a.mV[VY] * mMatrix[VY][VZ] +
+ a.mV[VZ] * mMatrix[VZ][VZ] +
+ mMatrix[VW][VZ]);
+}
+
+inline const LLV4Matrix4& LLV4Matrix4::translate(const LLV4Vector3 &vec)
+{
+ mMatrix[3][0] += vec.mV[0];
+ mMatrix[3][1] += vec.mV[1];
+ mMatrix[3][2] += vec.mV[2];
+ return (*this);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Matrix4
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+#endif
+
+inline const LLV4Matrix4& LLV4Matrix4::operator=(const LLMatrix4& a)
+{
+ memcpy(mMatrix, a.mMatrix, sizeof(F32) * 16 );
+ return *this;
+}
+
+inline const LLV4Matrix4& LLV4Matrix4::transpose()
+{
+#if LL_VECTORIZE && defined(_MM_TRANSPOSE4_PS)
+ _MM_TRANSPOSE4_PS(mV[VX], mV[VY], mV[VZ], mV[VW]);
+#else
+ LLV4Matrix4 mat;
+ mat.mMatrix[0][0] = mMatrix[0][0];
+ mat.mMatrix[1][0] = mMatrix[0][1];
+ mat.mMatrix[2][0] = mMatrix[0][2];
+ mat.mMatrix[3][0] = mMatrix[0][3];
+
+ mat.mMatrix[0][1] = mMatrix[1][0];
+ mat.mMatrix[1][1] = mMatrix[1][1];
+ mat.mMatrix[2][1] = mMatrix[1][2];
+ mat.mMatrix[3][1] = mMatrix[1][3];
+
+ mat.mMatrix[0][2] = mMatrix[2][0];
+ mat.mMatrix[1][2] = mMatrix[2][1];
+ mat.mMatrix[2][2] = mMatrix[2][2];
+ mat.mMatrix[3][2] = mMatrix[2][3];
+
+ mat.mMatrix[0][3] = mMatrix[3][0];
+ mat.mMatrix[1][3] = mMatrix[3][1];
+ mat.mMatrix[2][3] = mMatrix[3][2];
+ mat.mMatrix[3][3] = mMatrix[3][3];
+
+ *this = mat;
+#endif
+ return *this;
+}
+
+inline const LLV4Matrix4& LLV4Matrix4::translate(const LLVector3 &vec)
+{
+ mMatrix[3][0] += vec.mV[0];
+ mMatrix[3][1] += vec.mV[1];
+ mMatrix[3][2] += vec.mV[2];
+ return (*this);
+}
+
+inline LLVector3 operator*(const LLVector3 &a, const LLV4Matrix4 &b)
+{
+ return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
+ a.mV[VY] * b.mMatrix[VY][VX] +
+ a.mV[VZ] * b.mMatrix[VZ][VX] +
+ b.mMatrix[VW][VX],
+
+ a.mV[VX] * b.mMatrix[VX][VY] +
+ a.mV[VY] * b.mMatrix[VY][VY] +
+ a.mV[VZ] * b.mMatrix[VZ][VY] +
+ b.mMatrix[VW][VY],
+
+ a.mV[VX] * b.mMatrix[VX][VZ] +
+ a.mV[VY] * b.mMatrix[VY][VZ] +
+ a.mV[VZ] * b.mMatrix[VZ][VZ] +
+ b.mMatrix[VW][VZ]);
+}
+
+
+#endif
diff --git a/linden/indra/llmath/llv4vector3.h b/linden/indra/llmath/llv4vector3.h
new file mode 100644
index 0000000..994e7f5
--- /dev/null
+++ b/linden/indra/llmath/llv4vector3.h
@@ -0,0 +1,82 @@
+/**
+ * @file llviewerjointmesh.cpp
+ * @brief LLV4* class header file - vector processor enabled math
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#ifndef LL_LLV4VECTOR3_H
+#define LL_LLV4VECTOR3_H
+
+#include "llv4math.h"
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Vector3
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+LL_LLV4MATH_ALIGN_PREFIX
+
+class LLV4Vector3
+{
+public:
+ union {
+ F32 mV[LLV4_NUM_AXIS];
+ V4F32 v;
+ };
+
+ enum {
+ ALIGNMENT = 16
+ };
+
+ void setVec(F32 x, F32 y, F32 z);
+ void setVec(F32 a);
+}
+
+LL_LLV4MATH_ALIGN_POSTFIX;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// LLV4Vector3
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+inline void LLV4Vector3::setVec(F32 x, F32 y, F32 z)
+{
+ mV[VX] = x;
+ mV[VY] = y;
+ mV[VZ] = z;
+}
+
+inline void LLV4Vector3::setVec(F32 a)
+{
+#if LL_VECTORIZE
+ v = _mm_set1_ps(a);
+#else
+ setVec(a, a, a);
+#endif
+}
+
+#endif
diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp
index 5764c38..c0a33c7 100644
--- a/linden/indra/llmath/llvolume.cpp
+++ b/linden/indra/llmath/llvolume.cpp
@@ -750,7 +750,11 @@ BOOL LLProfileParams::importFile(FILE *fp)
while (!feof(fp))
{
- fgets(buffer, BUFSIZE, fp);
+ if (fgets(buffer, BUFSIZE, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf( /* Flawfinder: ignore */
buffer,
" %255s %255s",
@@ -1251,7 +1255,11 @@ BOOL LLPathParams::importFile(FILE *fp)
while (!feof(fp))
{
- fgets(buffer, BUFSIZE, fp);
+ if (fgets(buffer, BUFSIZE, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf( /* Flawfinder: ignore */
buffer,
" %255s %255s",
@@ -3582,7 +3590,11 @@ BOOL LLVolumeParams::importFile(FILE *fp)
while (!feof(fp))
{
- fgets(buffer, BUFSIZE, fp);
+ if (fgets(buffer, BUFSIZE, fp) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */
if (!strcmp("{", keyword))
{
diff --git a/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h
index 8292d0c..ee28057 100644
--- a/linden/indra/llmath/llvolume.h
+++ b/linden/indra/llmath/llvolume.h
@@ -783,7 +783,7 @@ public:
FLAT_MASK = 0x0100,
TOP_MASK = 0x0200,
BOTTOM_MASK = 0x0400
- } TypeMask;
+ };
public:
S32 mID;
diff --git a/linden/indra/llmedia/files.lst b/linden/indra/llmedia/files.lst
index 35ae5ab..bda6459 100644
--- a/linden/indra/llmedia/files.lst
+++ b/linden/indra/llmedia/files.lst
@@ -1,4 +1,7 @@
llmedia/llmediabase.cpp
llmedia/llmediaengine.cpp
+llmedia/llmediaimplgstreamer.cpp
+llmedia/llmediaimplgstreamer_syms.cpp
+llmedia/llmediaimplgstreamervidplug.cpp
llmedia/llmediaimplquicktime.cpp
llmedia/llmediamoviebase.cpp
diff --git a/linden/indra/llmedia/llmedia_vc8.vcproj b/linden/indra/llmedia/llmedia_vc8.vcproj
index 12fa817..2bc8014 100644
--- a/linden/indra/llmedia/llmedia_vc8.vcproj
+++ b/linden/indra/llmedia/llmedia_vc8.vcproj
@@ -1,297 +1,297 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linden/indra/llmedia/llmediabase.cpp b/linden/indra/llmedia/llmediabase.cpp
index 7abf960..17bb563 100644
--- a/linden/indra/llmedia/llmediabase.cpp
+++ b/linden/indra/llmedia/llmediabase.cpp
@@ -30,6 +30,7 @@
#include "llmediabase.h"
#include "llmediaimplquicktime.h"
+#include "llmediaimplgstreamer.h"
LLMediaBase::LLMediaBase() :
mBufferChangeCount ( 1 ),
@@ -60,6 +61,13 @@ LLMediaBase* LLMediaBase::make( const MediaType mediaTypeIn, S32 width_pixels, S
}
else
#endif
+#if LL_GSTREAMER_ENABLED
+ if ( mediaTypeIn == QuickTime )
+ {
+ return new LLMediaImplGStreamer ();
+ }
+ else
+#endif
return 0;
}
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.cpp b/linden/indra/llmedia/llmediaimplgstreamer.cpp
new file mode 100644
index 0000000..f8b4c74
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer.cpp
@@ -0,0 +1,715 @@
+/**
+ * @file llmediaimplgstreamer.cpp
+ * @brief implementation that supports various media through GStreamer.
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#include "linden_common.h"
+
+#if LL_GSTREAMER_ENABLED
+
+extern "C" {
+#include
+}
+
+#include "llmediaimplgstreamer.h"
+
+#include "llmediaimplgstreamervidplug.h"
+
+#ifdef LL_GST_SOUNDSINK
+#include "llmediaimplgstreamersndplug.h"
+#endif // LL_GST_SOUNDSINK
+
+#include "llmediaimplgstreamer_syms.h"
+
+#include "llgl.h"
+#include "llglheaders.h" // For gl texture modes
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLMediaImplGStreamer::
+LLMediaImplGStreamer () :
+ mediaData ( NULL ),
+ ownBuffer ( TRUE ),
+ mVolume ( 1.0f ),
+ currentMode ( ModeIdle ),
+ mPump ( NULL ),
+ mPlaybin ( NULL ),
+ mVideoSink ( NULL )
+#ifdef LL_GST_SOUNDSINK
+ ,mAudioSink ( NULL )
+#endif // LL_GST_SOUNDSINK
+{
+ mMediaDepthBytes = 4;
+ mTextureDepth = 4;
+ mTextureFormatInternal = GL_RGB8;
+ mTextureFormatPrimary = GL_BGRA;
+ mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLMediaImplGStreamer::
+~LLMediaImplGStreamer ()
+{
+ unload();
+}
+
+void UnloadGStreamer()
+{
+ ungrab_gst_syms();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+setBuffer ( U8* bufferIn )
+{
+ // Since we've pointed GStreamer at the old media data buffer
+ // directly, we need to be somewhat careful deleting it...
+ U8* oldMediaData = mediaData;
+ BOOL ownedMediaData = ownBuffer;
+
+ if(bufferIn == NULL)
+ {
+ // Passing NULL to this function requests that the object
+ // allocate its own buffer.
+ mediaData = new unsigned char[ mMediaHeight * mMediaRowbytes ];
+ ownBuffer = TRUE;
+ }
+ else
+ {
+ // Use the supplied buffer.
+ mediaData = bufferIn;
+ ownBuffer = FALSE;
+ }
+
+ if(mediaData == NULL)
+ {
+ // This is bad - probably out of memory.
+ llerrs << "LLMediaImplGStreamer::setBuffer: mediaData is NULL" << llendl;
+ // NOTE: This case doesn't clean up properly. This assert is fatal, so this isn't a huge problem,
+ // but if this assert is ever removed the code should be fixed to clean up correctly.
+ return FALSE;
+ }
+
+ // [..]
+
+ // Delete the old media data buffer iff we owned it.
+ if ( ownedMediaData )
+ {
+ if ( oldMediaData )
+ {
+ delete [] oldMediaData;
+ }
+ }
+
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+init ()
+{
+ static bool done_init = false;
+ if (!done_init)
+ {
+ // Get symbols!
+ if (! grab_gst_syms("libgstreamer-0.10.so.0",
+ "libgstvideo-0.10.so.0",
+ "libgstaudio-0.10.so.0") )
+ {
+ llwarns << "Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled." << llendl;
+ return FALSE;
+ }
+
+ if (llgst_segtrap_set_enabled)
+ llgst_segtrap_set_enabled(FALSE);
+ else
+ llwarns << "gst_segtrap_set_enabled() is not available; Second Life automated crash-reporter may cease to function until next restart." << llendl;
+
+ if (0 == llgst_init_check(NULL, NULL, NULL))
+ {
+ return FALSE;
+ }
+
+ // Init our custom plugins - only really need do this once.
+ gst_slvideo_init_class();
+#if 0
+ gst_slsound_init_class();
+#endif
+
+ done_init = true;
+ }
+
+ // Create a pumpable main-loop for this media
+ mPump = g_main_loop_new (NULL, FALSE);
+ if (!mPump)
+ {
+ return FALSE;
+ }
+
+ // instantiate a playbin element to do the hard work
+ mPlaybin = llgst_element_factory_make ("playbin", "play");
+ if (!mPlaybin)
+ {
+ // todo: cleanup pump
+ return FALSE;
+ }
+
+ if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
+ // instantiate and connect a custom video sink
+ mVideoSink =
+ GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo"));
+ if (!mVideoSink)
+ {
+ llwarns << "Could not instantiate private-slvideo element."
+ << llendl;
+ // todo: cleanup.
+ return FALSE;
+ }
+
+ g_object_set(mPlaybin, "video-sink", mVideoSink, NULL);
+
+#ifdef LL_GST_SOUNDSINK
+ // instantiate and connect a custom audio sink
+ mAudioSink =
+ GST_SLSOUND(llgst_element_factory_make ("private-slsound", "slsound"));
+ if (!mAudioSink)
+ {
+ llwarns << "Could not instantiate private-slsound element."
+ << llendl;
+ // todo: cleanup.
+ return FALSE;
+ }
+
+ g_object_set(mPlaybin, "audio-sink", mAudioSink, NULL);
+#endif
+ }
+
+ return LLMediaMovieBase::init();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//#define LL_GST_REPORT_STATE_CHANGES
+#ifdef LL_GST_REPORT_STATE_CHANGES
+static char* get_gst_state_name(GstState state)
+{
+ switch (state) {
+ case GST_STATE_VOID_PENDING: return "VOID_PENDING";
+ case GST_STATE_NULL: return "NULL";
+ case GST_STATE_READY: return "READY";
+ case GST_STATE_PAUSED: return "PAUSED";
+ case GST_STATE_PLAYING: return "PLAYING";
+ }
+ return "(unknown)";
+}
+#endif // LL_GST_REPORT_STATE_CHANGES
+
+static gboolean
+my_bus_callback (GstBus *bus,
+ GstMessage *message,
+ gpointer data)
+{
+ if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
+ GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
+ {
+ llinfos << "Got GST message type: "
+ << LLGST_MESSAGE_TYPE_NAME (message)
+ << llendl;
+ }
+ else
+ {
+ lldebugs << "Got GST message type: "
+ << LLGST_MESSAGE_TYPE_NAME (message)
+ << llendl;
+ }
+
+ LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_BUFFERING: {
+ // NEEDS GST 0.10.11+
+ if (llgst_message_parse_buffering)
+ {
+ gint percent = 0;
+ llgst_message_parse_buffering(message, &percent);
+ llinfos << "GST buffering: " << percent
+ << "%" << llendl;
+ // ModeBuffering seems to do nothing except make
+ // the UI worse
+ /*if (percent < 100) impl->setCurrentMode(LLMediaImplGStreamer::ModeBuffering);*/
+ }
+ break;
+ }
+ case GST_MESSAGE_STATE_CHANGED: {
+ GstState old_state;
+ GstState new_state;
+ GstState pending_state;
+ llgst_message_parse_state_changed(message,
+ &old_state,
+ &new_state,
+ &pending_state);
+#ifdef LL_GST_REPORT_STATE_CHANGES
+ // not generally very useful, and rather spammy.
+ llinfos << "state change (old,,pending): "
+ << get_gst_state_name(old_state) << ", <"
+ << get_gst_state_name(new_state) << ">, "
+ << get_gst_state_name(pending_state) <<
+ llendl;
+#endif // LL_GST_REPORT_STATE_CHANGES
+
+ switch (new_state) {
+ case GST_STATE_VOID_PENDING:
+ impl->setCurrentMode(LLMediaImplGStreamer::ModeNone);
+ break;
+ case GST_STATE_NULL:
+ impl->setCurrentMode(LLMediaImplGStreamer::ModeNone);
+ break;
+ case GST_STATE_READY:
+ impl->setCurrentMode(LLMediaImplGStreamer::ModeStopped);
+ break;
+ case GST_STATE_PAUSED:
+ impl->setCurrentMode(LLMediaImplGStreamer::ModePaused);
+ break;
+ case GST_STATE_PLAYING:
+ impl->setCurrentMode(LLMediaImplGStreamer::ModePlaying);
+ break;
+ }
+ break;
+ }
+ case GST_MESSAGE_ERROR: {
+ GError *err;
+ gchar *debug;
+
+ llgst_message_parse_error (message, &err, &debug);
+ llinfos << "GST error: " << err->message << llendl;
+ g_error_free (err);
+ g_free (debug);
+
+ impl->setCurrentMode(LLMediaImplGStreamer::ModeError);
+
+ impl->stop();
+
+ break;
+ }
+ case GST_MESSAGE_INFO: {
+ if (llgst_message_parse_info)
+ {
+ GError *err;
+ gchar *debug;
+
+ llgst_message_parse_info (message, &err, &debug);
+ llinfos << "GST info: " << err->message << llendl;
+ g_error_free (err);
+ g_free (debug);
+ }
+ break;
+ }
+ case GST_MESSAGE_WARNING: {
+ GError *err;
+ gchar *debug;
+
+ llgst_message_parse_warning (message, &err, &debug);
+ llinfos << "GST warning: " << err->message << llendl;
+ g_error_free (err);
+ g_free (debug);
+
+ break;
+ }
+ case GST_MESSAGE_EOS:
+ /* end-of-stream */
+ llinfos << "GST EOS." << llendl;
+ impl->setCurrentMode(LLMediaImplGStreamer::ModeStopped);//?
+ impl->stop();
+ break;
+ default:
+ /* unhandled message */
+ break;
+ }
+
+ /* we want to be notified again the next time there is a message
+ * on the bus, so returning TRUE (FALSE means we want to stop watching
+ * for messages on the bus and our callback should not be called again)
+ */
+ return TRUE;
+}
+
+BOOL
+LLMediaImplGStreamer::
+load ( const LLString& urlIn )
+{
+ llinfos << "Setting media URI: " << urlIn << llendl;
+
+ // set URI
+ g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
+ //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL);
+
+ // get playbin's bus - perhaps this can/should be done at init()
+ GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
+ if (!bus)
+ {
+ return FALSE;
+ }
+ llgst_bus_add_watch (bus, my_bus_callback, this);
+ llgst_object_unref (bus);
+
+ if (true) // dummy values
+ {
+ const int fixedsize = 2;
+ mMediaRowbytes = mMediaDepthBytes * fixedsize;
+ mMediaWidth = fixedsize;
+ mMediaHeight = fixedsize;
+ mTextureWidth = fixedsize;
+ mTextureHeight = fixedsize;
+ }
+
+ BOOL rtn = LLMediaMovieBase::load(urlIn);
+ llinfos << "load returns " << int(rtn) << llendl;
+ return rtn;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+unload ()
+{
+ if (mPlaybin)
+ {
+ llgst_element_set_state (mPlaybin, GST_STATE_NULL);
+ llgst_object_unref (GST_OBJECT (mPlaybin));
+ mPlaybin = NULL;
+ }
+
+ if (mPump)
+ {
+ g_main_loop_quit(mPump);
+ mPump = NULL;
+ }
+
+ if (mediaData)
+ {
+ if (ownBuffer)
+ {
+ delete mediaData;
+ mediaData = NULL;
+ }
+ }
+
+ mVideoSink = NULL;
+
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+S32
+LLMediaImplGStreamer::
+updateMedia ()
+{
+ //llinfos << "updating media..." << llendl;
+ if (g_main_context_pending(g_main_loop_get_context(mPump)))
+ {
+ g_main_context_iteration(g_main_loop_get_context(mPump), FALSE);
+ }
+
+ if (mVideoSink)
+ {
+ GST_OBJECT_LOCK(mVideoSink);
+ if (mVideoSink->retained_frame_ready)
+ {
+ //llinfos << "NEW FRAME " << llendl;
+ if (mVideoSink->retained_frame_width != mMediaWidth ||
+ mVideoSink->retained_frame_height != mMediaHeight)
+ // *TODO: also check for change in format
+ {
+ // just resize container
+ mMediaWidth = mVideoSink->retained_frame_width;
+ mMediaHeight = mVideoSink->retained_frame_height;
+ mTextureWidth = mMediaWidth;
+ mTextureHeight = mMediaHeight;
+ mMediaDepthBytes = mTextureDepth =
+ SLVPixelFormatBytes[mVideoSink->retained_frame_format];
+ if (SLV_PF_RGBX == mVideoSink->retained_frame_format)
+ {
+ mTextureFormatPrimary = GL_RGBA;
+ mTextureFormatType=GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+ else
+ {
+ mTextureFormatPrimary = GL_BGRA;
+ mTextureFormatType=GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+ mMediaRowbytes = mMediaWidth * mMediaDepthBytes;
+ llinfos << "video container resized to " <<
+ mMediaWidth << "x" << mMediaHeight << llendl;
+
+ if (ownBuffer)
+ {
+ // we manage the buffer, so we need to realloc
+ delete[] mediaData;
+ mediaData = new U8[mMediaRowbytes *
+ mMediaHeight];
+ }
+
+ GST_OBJECT_UNLOCK(mVideoSink);
+ return updateMediaNeedsSizeChange;
+ }
+
+ // we're gonna totally consume this frame - reset 'ready' flag
+ mVideoSink->retained_frame_ready = FALSE;
+ memcpy(mediaData, mVideoSink->retained_frame_data,
+ mMediaRowbytes * mMediaHeight);
+
+ GST_OBJECT_UNLOCK(mVideoSink);
+ return updateMediaNeedsUpdate;
+ }
+ else
+ {
+ // nothing to do yet.
+ GST_OBJECT_UNLOCK(mVideoSink);
+ return updateMediaNoChanges;
+ }
+ }
+
+ return updateMediaNoChanges;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+void
+LLMediaImplGStreamer::
+setAutoScaled ( BOOL autoScaledIn )
+{
+ autoScaled = autoScaledIn;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+stop ()
+{
+ llinfos << "stopping media..." << llendl;
+ // todo: error-check this?
+ llgst_element_set_state(mPlaybin, GST_STATE_READY);
+
+ BOOL rtn = LLMediaMovieBase::stop();
+ setCurrentMode(LLMediaImplGStreamer::ModeStopped);//?
+ return rtn;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+play ()
+{
+ llinfos << "playing media..." << llendl;
+ // todo: error-check this?
+ llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
+
+ return LLMediaMovieBase::play();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+loop ( S32 howMany )
+{
+ llinfos << "looping media... " << howMany << llendl;
+ // todo: implement this
+ if (!play())
+ return FALSE;
+
+ return LLMediaMovieBase::loop(howMany);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+pause ()
+{
+ llinfos << "pausing media..." << llendl;
+ // todo: error-check this?
+ llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
+
+ return LLMediaMovieBase::pause();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+setVolume ( F32 volumeIn )
+{
+ mVolume = volumeIn;
+ g_object_set(mPlaybin, "volume", mVolume, NULL);
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+F32
+LLMediaImplGStreamer::
+getVolume ()
+{
+ return mVolume;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isIdle () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModeIdle;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isError () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModeError;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isBuffering () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModeBuffering;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isLoaded () const
+{
+ // todo: probably semantically decouple from currentMode
+ //return currentMode == ModeLoaded;
+ return (mPump != NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isPlaying () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModePlaying;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isLooping () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModeLooping;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isPaused () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModePaused;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+isStopped () const
+{
+ // todo: probably semantically decouple from currentMode
+ return currentMode == ModeStopped;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+U8*
+LLMediaImplGStreamer::
+getMediaData ()
+{
+ return mediaData;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL
+LLMediaImplGStreamer::
+seek ( F64 time )
+{
+ // todo: implement this
+ llinfos << "Tried to seek to time " << time
+ << " - faking it" << llendl;
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+F64
+LLMediaImplGStreamer::
+getTime () const
+{
+ // todo: implement this
+ F64 result = 0;
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+F64
+LLMediaImplGStreamer::
+getMediaDuration () const
+{
+ // todo: implement this
+ F64 result = 0;
+ return result;
+}
+
+#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.h b/linden/indra/llmedia/llmediaimplgstreamer.h
new file mode 100644
index 0000000..52a5c84
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer.h
@@ -0,0 +1,126 @@
+/**
+ * @file llmediaimplgstreamer.h
+ * @brief implementation that supports media playback via GStreamer.
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+// header guard
+#ifndef llmediaimplgstreamer_h
+#define llmediaimplgstreamer_h
+
+#if LL_GSTREAMER_ENABLED
+
+extern "C" {
+#include
+
+#include
+#include
+}
+
+#include "stdtypes.h"
+
+#include "llmediamoviebase.h"
+
+#include "llmediaimplgstreamervidplug.h"
+#ifdef LL_GST_SOUNDSINK
+#include "llmediaimplgstreamersndplug.h"
+#endif // LL_GST_SOUNDSINK
+
+///////////////////////////////////////////////////////////////////////////
+class LLMediaImplGStreamer:
+ public LLMediaMovieBase
+{
+ public:
+ LLMediaImplGStreamer ();
+ virtual ~LLMediaImplGStreamer ();
+
+ ////////////////////////////////////////////////////////
+ // implementation of the media public interface
+
+ // housekeeping
+ virtual BOOL setBuffer ( U8* bufferIn );
+ virtual BOOL init ();
+ virtual BOOL load ( const LLString& urlIn );
+ virtual BOOL unload ();
+
+ // transport controls
+ virtual BOOL stop ();
+ virtual BOOL play ();
+ virtual BOOL loop ( S32 howMany );
+ virtual BOOL pause ();
+ virtual BOOL seek ( F64 time );
+
+ // audio levels
+ virtual BOOL setVolume ( F32 volumeIn );
+ virtual F32 getVolume ();
+
+ // status
+ virtual BOOL isIdle () const;
+ virtual BOOL isBuffering () const;
+ virtual BOOL isError () const;
+ virtual BOOL isLoaded () const;
+ virtual BOOL isStopped () const;
+ virtual BOOL isPaused () const;
+ virtual BOOL isPlaying () const;
+ virtual BOOL isLooping () const;
+ virtual F64 getTime () const;
+
+ // media data
+ virtual S32 updateMedia ();
+ virtual void setAutoScaled ( BOOL autoScaledIn );
+ virtual U8* getMediaData ();
+ virtual F64 getMediaDuration () const;
+
+ // class-specific
+ GMainLoop *getPump() {return mPump;};
+ typedef enum { ModeNone, ModeIdle, ModeError, ModeBuffering, ModeStopped, ModePaused, ModePlaying, ModeLooping } llGstMode;
+ llGstMode getCurrentMode() {return currentMode;};
+ void setCurrentMode(llGstMode mode) {currentMode = mode;};
+
+ private:
+ // misc
+ U8* mediaData;
+ BOOL ownBuffer;
+ BOOL autoScaled;
+ F32 mVolume;
+
+ llGstMode currentMode;
+
+ // GStreamer-specific
+ GMainLoop *mPump; // event pump for this media
+ GstElement *mPlaybin;
+ GstSLVideo *mVideoSink;
+#ifdef LL_GST_SOUNDSINK
+ GstSLSound *mAudioSink;
+#endif // LL_GST_SOUNDSINK
+};
+
+// called during shutdown when no instances may exist
+void UnloadGStreamer();
+
+
+#endif // LL_GSTREAMER_ENABLED
+
+#endif // llmediaimplgstreamer_h
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp b/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp
new file mode 100644
index 0000000..76f62e1
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp
@@ -0,0 +1,189 @@
+/**
+ * @file llmediaimplgstreamer_syms.cpp
+ * @brief dynamic GStreamer symbol-grabbing code
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#include "linden_common.h"
+
+#if LL_GSTREAMER_ENABLED
+
+extern "C" {
+#include
+
+#include
+#include
+}
+
+#include "llmediaimplgstreamer.h"
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL
+#include "llmediaimplgstreamer_syms_raw.inc"
+#include "llmediaimplgstreamer_syms_rawa.inc"
+#include "llmediaimplgstreamer_syms_rawv.inc"
+#undef LL_GST_SYM
+
+
+static bool sSymsGrabbed = false;
+static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
+static apr_dso_handle_t *sSymGSTDSOHandleG = NULL;
+static apr_dso_handle_t *sSymGSTDSOHandleV = NULL;
+static apr_dso_handle_t *sSymGSTDSOHandleA = NULL;
+
+
+bool grab_gst_syms(std::string gst_dso_name,
+ std::string gst_dso_name_vid,
+ std::string gst_dso_name_aud)
+{
+ if (sSymsGrabbed)
+ {
+ // already have grabbed good syms
+ return TRUE;
+ }
+
+ bool sym_error = false;
+ bool rtn = false;
+ apr_status_t rv;
+ apr_dso_handle_t *sSymGSTDSOHandle = NULL;
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {llwarns << "Failed to grab symbol: " << #GSTSYM << llendl; if (REQ) sym_error = true;} else llinfos << "grabbed symbol: " << #GSTSYM << " from " << (void*)ll##GSTSYM << llendl;}while(0)
+
+ //attempt to load the shared libraries
+ apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
+
+ if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
+ gst_dso_name.c_str(),
+ sSymGSTDSOMemoryPool) ))
+ {
+ llinfos << "Found DSO: " << gst_dso_name << llendl;
+#include "llmediaimplgstreamer_syms_raw.inc"
+
+ if ( sSymGSTDSOHandle )
+ {
+ sSymGSTDSOHandleG = sSymGSTDSOHandle;
+ sSymGSTDSOHandle = NULL;
+ }
+
+ if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
+ gst_dso_name_aud.c_str(),
+ sSymGSTDSOMemoryPool) ))
+ {
+ llinfos << "Found DSO: " << gst_dso_name_aud << llendl;
+#include "llmediaimplgstreamer_syms_rawa.inc"
+
+ if ( sSymGSTDSOHandle )
+ {
+ sSymGSTDSOHandleA = sSymGSTDSOHandle;
+ sSymGSTDSOHandle = NULL;
+ }
+
+ if ( APR_SUCCESS ==
+ (rv = apr_dso_load(&sSymGSTDSOHandle,
+ gst_dso_name_vid.c_str(),
+ sSymGSTDSOMemoryPool) ))
+ {
+ llinfos << "Found DSO: " << gst_dso_name_vid << llendl;
+#include "llmediaimplgstreamer_syms_rawv.inc"
+ }
+ else
+ {
+ llwarns << "Couldn't load DSO: "
+ << gst_dso_name_vid << llendl;
+ rtn = false; // failure
+ }
+ }
+ else
+ {
+ llwarns << "Couldn't load DSO: "
+ << gst_dso_name_aud << llendl;
+ rtn = false; // failure
+ }
+
+ rtn = !sym_error;
+ }
+ else
+ {
+ llwarns << "Couldn't load DSO: " << gst_dso_name << llendl;
+ rtn = false; // failure
+ }
+
+ if (sym_error)
+ {
+ llwarns << "Failed to find necessary symbols in GStreamer libraries." << llendl;
+ }
+
+ if ( sSymGSTDSOHandle )
+ {
+ sSymGSTDSOHandleV = sSymGSTDSOHandle;
+ sSymGSTDSOHandle = NULL;
+ }
+#undef LL_GST_SYM
+
+ sSymsGrabbed = !!rtn;
+ return rtn;
+}
+
+
+void ungrab_gst_syms()
+{
+ // should be safe to call regardless of whether we've
+ // actually grabbed syms.
+
+ if ( sSymGSTDSOHandleG )
+ {
+ apr_dso_unload(sSymGSTDSOHandleG);
+ sSymGSTDSOHandleG = NULL;
+ }
+
+ if ( sSymGSTDSOHandleA )
+ {
+ apr_dso_unload(sSymGSTDSOHandleA);
+ sSymGSTDSOHandleA = NULL;
+ }
+
+ if ( sSymGSTDSOHandleV )
+ {
+ apr_dso_unload(sSymGSTDSOHandleV);
+ sSymGSTDSOHandleV = NULL;
+ }
+
+ if ( sSymGSTDSOMemoryPool )
+ {
+ apr_pool_destroy(sSymGSTDSOMemoryPool);
+ sSymGSTDSOMemoryPool = NULL;
+ }
+
+ // NULL-out all of the symbols we'd grabbed
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0)
+#include "llmediaimplgstreamer_syms_raw.inc"
+#include "llmediaimplgstreamer_syms_rawa.inc"
+#include "llmediaimplgstreamer_syms_rawv.inc"
+#undef LL_GST_SYM
+
+ sSymsGrabbed = false;
+}
+
+
+#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms.h b/linden/indra/llmedia/llmediaimplgstreamer_syms.h
new file mode 100644
index 0000000..6dec2a2
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer_syms.h
@@ -0,0 +1,75 @@
+/**
+ * @file llmediaimplgstreamer_syms.h
+ * @brief dynamic GStreamer symbol-grabbing code
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#include "linden_common.h"
+
+#if LL_GSTREAMER_ENABLED
+
+extern "C" {
+#include
+}
+
+bool grab_gst_syms(std::string gst_dso_name,
+ std::string gst_dso_name_vid,
+ std::string gst_dso_name_aud);
+void ungrab_gst_syms();
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__)
+#include "llmediaimplgstreamer_syms_raw.inc"
+#include "llmediaimplgstreamer_syms_rawa.inc"
+#include "llmediaimplgstreamer_syms_rawv.inc"
+#undef LL_GST_SYM
+
+// regrettable hacks to give us better runtime compatibility with older systems
+#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
+#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
+
+// regrettable hacks because GStreamer was not designed for runtime loading
+#undef GST_TYPE_MESSAGE
+#define GST_TYPE_MESSAGE (llgst_message_get_type())
+#undef GST_TYPE_OBJECT
+#define GST_TYPE_OBJECT (llgst_object_get_type())
+#undef GST_TYPE_PIPELINE
+#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
+#undef GST_TYPE_ELEMENT
+#define GST_TYPE_ELEMENT (llgst_element_get_type())
+#undef GST_TYPE_AUDIO_SINK
+#define GST_TYPE_AUDIO_SINK (llgst_audio_sink_get_type())
+#undef GST_TYPE_VIDEO_SINK
+#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
+#undef _gst_debug_register_funcptr
+#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
+#undef _gst_debug_category_new
+#define _gst_debug_category_new ll_gst_debug_category_new
+#undef __gst_debug_enabled
+#define __gst_debug_enabled (0)
+
+// more hacks
+#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
+
+#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
new file mode 100644
index 0000000..c00947f
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
@@ -0,0 +1,42 @@
+
+// required symbols to grab
+LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err);
+LL_GST_SYM(true, gst_message_get_type, GType, void);
+LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type);
+LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug);
+LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug);
+LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending);
+LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state);
+LL_GST_SYM(true, gst_object_unref, void, gpointer object);
+LL_GST_SYM(true, gst_object_get_type, GType, void);
+LL_GST_SYM(true, gst_pipeline_get_type, GType, void);
+LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline);
+LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data);
+LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name);
+LL_GST_SYM(true, gst_element_get_type, GType, void);
+LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template);
+LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp);
+LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details);
+LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps);
+LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps);
+LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname);
+LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description);
+LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps);
+LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string);
+LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps);
+LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index);
+LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps);
+LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2);
+LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type);
+LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc);
+LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value);
+LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname);
+LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value);
+LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value);
+LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure);
+
+// optional symbols to grab
+LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled);
+LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent);
+LL_GST_SYM(false, expected_to_be_missing, void, gboolean enabled);
+LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug);
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc
new file mode 100644
index 0000000..0be99b5
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawa.inc
@@ -0,0 +1,5 @@
+
+// required symbols to grab
+LL_GST_SYM(true, gst_audio_sink_get_type, GType, void);
+
+// optional symbols to grab
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc
new file mode 100644
index 0000000..14fbcb4
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc
@@ -0,0 +1,5 @@
+
+// required symbols to grab
+LL_GST_SYM(true, gst_video_sink_get_type, GType, void);
+
+// optional symbols to grab
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
new file mode 100644
index 0000000..dade946
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
@@ -0,0 +1,461 @@
+/**
+ * @file llmediaimplgstreamervidplug.h
+ * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#if LL_GSTREAMER_ENABLED
+
+#include
+
+#include
+#include
+#include
+
+#include "llmediaimplgstreamer_syms.h"
+
+#include "llthread.h"
+
+#include "llmediaimplgstreamervidplug.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug);
+#define GST_CAT_DEFAULT gst_slvideo_debug
+
+/* Filter signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0
+};
+
+#define SLV_SIZECAPS ", width=(int){1,2,4,8,16,32,64,128,256,512,1024}, height=(int){1,2,4,8,16,32,64,128,256,512,1024} "
+#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE (
+ "sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SLV_ALLCAPS)
+ );
+
+GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink,
+ GST_TYPE_VIDEO_SINK);
+
+static void gst_slvideo_set_property (GObject * object, guint prop_id,
+ const GValue * value,
+ GParamSpec * pspec);
+static void gst_slvideo_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static void
+gst_slvideo_base_init (gpointer gclass)
+{
+ static GstElementDetails element_details = {
+ "PluginTemplate",
+ "Generic/PluginTemplate",
+ "Generic Template Element",
+ "Linden Lab"
+ };
+ GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+ llgst_element_class_add_pad_template (element_class,
+ llgst_static_pad_template_get (&sink_factory));
+ llgst_element_class_set_details (element_class, &element_details);
+}
+
+
+static void
+gst_slvideo_finalize (GObject * object)
+{
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO (object);
+ if (slvideo->caps)
+ {
+ llgst_caps_unref(slvideo->caps);
+ }
+
+ G_OBJECT_CLASS(parent_class)->finalize (object);
+}
+
+
+static GstFlowReturn
+gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
+{
+ GstSLVideo *slvideo;
+ llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+
+ slvideo = GST_SLVIDEO(bsink);
+
+#if 0
+ fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n",
+ slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
+ slvideo->format);
+#endif
+ if (GST_BUFFER_DATA(buf))
+ {
+ // copy frame and frame info into neutral territory
+ GST_OBJECT_LOCK(slvideo);
+ slvideo->retained_frame_ready = TRUE;
+ slvideo->retained_frame_width = slvideo->width;
+ slvideo->retained_frame_height = slvideo->height;
+ slvideo->retained_frame_format = slvideo->format;
+ int rowbytes =
+ SLVPixelFormatBytes[slvideo->retained_frame_format] *
+ slvideo->retained_frame_width;
+ int needbytes = rowbytes * slvideo->retained_frame_width;
+ // resize retained frame hunk only if necessary
+ if (needbytes != slvideo->retained_frame_allocbytes)
+ {
+ delete[] slvideo->retained_frame_data;
+ slvideo->retained_frame_data = new U8[needbytes];
+ slvideo->retained_frame_allocbytes = needbytes;
+
+ }
+ // copy the actual frame data to neutral territory -
+ // flipped, for GL reasons
+ for (int ypos=0; yposheight; ++ypos)
+ {
+ memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes],
+ &(((U8*)GST_BUFFER_DATA(buf))[ypos*rowbytes]),
+ rowbytes);
+ }
+ // done with the shared data
+ GST_OBJECT_UNLOCK(slvideo);
+ }
+
+ return GST_FLOW_OK;
+}
+
+
+static GstStateChangeReturn
+gst_slvideo_change_state(GstElement * element, GstStateChange transition)
+{
+ GstSLVideo *slvideo;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ slvideo = GST_SLVIDEO (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ slvideo->fps_n = 0;
+ slvideo->fps_d = 1;
+ GST_VIDEO_SINK_WIDTH(slvideo) = 0;
+ GST_VIDEO_SINK_HEIGHT(slvideo) = 0;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+static GstCaps *
+gst_slvideo_get_caps (GstBaseSink * bsink)
+{
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO(bsink);
+
+ return llgst_caps_ref (slvideo->caps);
+}
+
+
+/* this function handles the link with other elements */
+static gboolean
+gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
+{
+ GstSLVideo *filter;
+ GstStructure *structure;
+ GstCaps *intersection;
+
+ GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
+
+ filter = GST_SLVIDEO(bsink);
+
+ intersection = llgst_caps_intersect (filter->caps, caps);
+ if (llgst_caps_is_empty (intersection))
+ {
+ // no overlap between our caps and requested caps
+ return FALSE;
+ }
+ llgst_caps_unref(intersection);
+
+ int width, height;
+ gboolean ret;
+ const GValue *fps;
+ const GValue *par;
+ structure = llgst_caps_get_structure (caps, 0);
+ ret = llgst_structure_get_int (structure, "width", &width);
+ ret = ret && llgst_structure_get_int (structure, "height", &height);
+ fps = llgst_structure_get_value (structure, "framerate");
+ ret = ret && (fps != NULL);
+ par = llgst_structure_get_value (structure, "pixel-aspect-ratio");
+ if (!ret)
+ return FALSE;
+
+ filter->width = width;
+ filter->height = height;
+ filter->fps_n = llgst_value_get_fraction_numerator(fps);
+ filter->fps_d = llgst_value_get_fraction_denominator(fps);
+ if (par)
+ {
+ filter->par_n = llgst_value_get_fraction_numerator(par);
+ filter->par_d = llgst_value_get_fraction_denominator(par);
+ }
+ else
+ {
+ filter->par_n = 1;
+ filter->par_d = 1;
+ }
+ GST_VIDEO_SINK_WIDTH(filter) = width;
+ GST_VIDEO_SINK_HEIGHT(filter) = height;
+
+ filter->format = SLV_PF_UNKNOWN;
+ if (0 == strcmp(llgst_structure_get_name(structure),
+ "video/x-raw-rgb"))
+ {
+ int red_mask;
+ int green_mask;
+ int blue_mask;
+ llgst_structure_get_int(structure, "red_mask", &red_mask);
+ llgst_structure_get_int(structure, "green_mask", &green_mask);
+ llgst_structure_get_int(structure, "blue_mask", &blue_mask);
+ if ((unsigned int)red_mask == 0xFF000000 &&
+ (unsigned int)green_mask == 0x00FF0000 &&
+ (unsigned int)blue_mask == 0x0000FF00)
+ {
+ filter->format = SLV_PF_RGBX;
+ //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n");
+ } else if ((unsigned int)red_mask == 0x0000FF00 &&
+ (unsigned int)green_mask == 0x00FF0000 &&
+ (unsigned int)blue_mask == 0xFF000000)
+ {
+ filter->format = SLV_PF_BGRX;
+ //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
+ }
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_slvideo_start (GstBaseSink * bsink)
+{
+ GstSLVideo *slvideo;
+ gboolean ret = TRUE;
+
+ slvideo = GST_SLVIDEO(bsink);
+
+ return ret;
+}
+
+static gboolean
+gst_slvideo_stop (GstBaseSink * bsink)
+{
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO(bsink);
+
+ // free-up retained frame buffer
+ GST_OBJECT_LOCK(slvideo);
+ slvideo->retained_frame_ready = FALSE;
+ delete[] slvideo->retained_frame_data;
+ slvideo->retained_frame_data = NULL;
+ slvideo->retained_frame_allocbytes = 0;
+ GST_OBJECT_UNLOCK(slvideo);
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_slvideo_unlock (GstBaseSink * bsink)
+{
+ // nothing really to do here.
+ return TRUE;
+}
+
+
+/* initialize the plugin's class */
+static void
+gst_slvideo_class_init (GstSLVideoClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+
+ gobject_class->finalize = gst_slvideo_finalize;
+ gobject_class->set_property = gst_slvideo_set_property;
+ gobject_class->get_property = gst_slvideo_get_property;
+
+ gstelement_class->change_state = gst_slvideo_change_state;
+
+ gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_slvideo_get_caps);
+ gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR( gst_slvideo_set_caps);
+ //gstbasesink_class->buffer_alloc=GST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc);
+ //gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_slvideo_get_times);
+ gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
+ gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
+
+ gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_slvideo_start);
+ gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_slvideo_stop);
+
+ gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_slvideo_unlock);
+}
+
+
+static void
+gst_slvideo_update_caps (GstSLVideo * slvideo)
+{
+ GstCaps *caps;
+
+ // GStreamer will automatically convert colourspace if necessary.
+ // GStreamer will automatically resize media to one of these enumerated
+ // powers-of-two that we ask for (yay GStreamer!)
+ caps = llgst_caps_from_string (SLV_ALLCAPS);
+
+ llgst_caps_replace (&slvideo->caps, caps);
+}
+
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set functions
+ * initialize structure
+ */
+static void
+gst_slvideo_init (GstSLVideo * filter,
+ GstSLVideoClass * gclass)
+{
+ filter->width = -1;
+ filter->height = -1;
+
+ // this is the info we share with the client app
+ GST_OBJECT_LOCK(filter);
+ filter->retained_frame_ready = FALSE;
+ filter->retained_frame_data = NULL;
+ filter->retained_frame_allocbytes = 0;
+ filter->retained_frame_width = filter->width;
+ filter->retained_frame_height = filter->height;
+ filter->retained_frame_format = SLV_PF_UNKNOWN;
+ GST_OBJECT_UNLOCK(filter);
+
+ gst_slvideo_update_caps(filter);
+}
+
+static void
+gst_slvideo_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ llg_return_if_fail (GST_IS_SLVIDEO (object));
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_slvideo_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ llg_return_if_fail (GST_IS_SLVIDEO (object));
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+/* entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and pad templates
+ * register the features
+ */
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ //fprintf(stderr, "\n\n\nPLUGIN INIT\n\n\n");
+
+ GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, "private-slvideo-plugin",
+ 0, "Second Life Video Sink");
+
+ return llgst_element_register (plugin, "private-slvideo",
+ GST_RANK_NONE, GST_TYPE_SLVIDEO);
+}
+
+/* this is the structure that gstreamer looks for to register plugins
+ */
+/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since
+ some g++ versions buggily avoid __attribute__((constructor)) functions -
+ so we provide an explicit plugin init function.
+ */
+void gst_slvideo_init_class (void)
+{
+#define PACKAGE "packagehack"
+ static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "private-slvideoplugin",
+ "SL Video sink plugin",
+ plugin_init, "0.1", GST_LICENSE_UNKNOWN,
+ "Second Life",
+ "http://www.secondlife.com/");
+#undef PACKAGE
+ ll_gst_plugin_register_static (&gst_plugin_desc);
+ //fprintf(stderr, "\n\n\nCLASS INIT\n\n\n");
+}
+
+#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.h b/linden/indra/llmedia/llmediaimplgstreamervidplug.h
new file mode 100644
index 0000000..2bfb853
--- /dev/null
+++ b/linden/indra/llmedia/llmediaimplgstreamervidplug.h
@@ -0,0 +1,101 @@
+/**
+ * @file llmediaimplgstreamervidplug.h
+ * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
+ *
+ * Copyright (c) 2007-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#ifndef __GST_SLVIDEO_H__
+#define __GST_SLVIDEO_H__
+
+#if LL_GSTREAMER_ENABLED
+
+extern "C" {
+#include
+#include
+#include
+}
+
+G_BEGIN_DECLS
+
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_SLVIDEO \
+ (gst_slvideo_get_type())
+#define GST_SLVIDEO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo))
+#define GST_SLVIDEO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass))
+#define GST_IS_SLVIDEO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO))
+#define GST_IS_SLVIDEO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO))
+
+typedef struct _GstSLVideo GstSLVideo;
+typedef struct _GstSLVideoClass GstSLVideoClass;
+
+typedef enum {
+ SLV_PF_UNKNOWN = 0,
+ SLV_PF_RGBX = 1,
+ SLV_PF_BGRX = 2,
+ SLV__END = 3
+} SLVPixelFormat;
+const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4};
+
+struct _GstSLVideo
+{
+ GstVideoSink video_sink;
+
+ GstCaps *caps;
+
+ int fps_n, fps_d;
+ int par_n, par_d;
+ int height, width;
+ SLVPixelFormat format;
+
+ // SHARED WITH APPLICATION:
+ // Access to the following should be protected by GST_OBJECT_LOCK() on
+ // the GstSLVideo object, and should be totally consistent upon UNLOCK
+ // (i.e. all written at once to reflect the current retained frame info
+ // when the retained frame is updated.)
+ bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.)
+ U8* retained_frame_data;
+ int retained_frame_allocbytes;
+ int retained_frame_width, retained_frame_height;
+ SLVPixelFormat retained_frame_format;
+};
+
+struct _GstSLVideoClass
+{
+ GstVideoSink parent_class;
+};
+
+GType gst_slvideo_get_type (void);
+
+void gst_slvideo_init_class (void);
+
+G_END_DECLS
+
+#endif // LL_GSTREAMER_ENABLED
+
+#endif /* __GST_SLVIDEO_H__ */
diff --git a/linden/indra/llmedia/llmediamoviebase.cpp b/linden/indra/llmedia/llmediamoviebase.cpp
index 46b76b0..de9933b 100644
--- a/linden/indra/llmedia/llmediamoviebase.cpp
+++ b/linden/indra/llmedia/llmediamoviebase.cpp
@@ -30,6 +30,7 @@
#include "llmediamoviebase.h"
#include "llmediaimplquicktime.h"
+#include "llmediaimplgstreamer.h"
LLMediaMovieBase::LLMediaMovieBase()
{
@@ -47,6 +48,13 @@ LLMediaMovieBase* LLMediaMovieBase::make( const MediaType mediaTypeIn, S32 width
}
else
#endif
+#if LL_GSTREAMER_ENABLED
+ if ( mediaTypeIn == QuickTime )
+ {
+ return new LLMediaImplGStreamer ();
+ }
+ else
+#endif
return 0;
}
diff --git a/linden/indra/llmessage/llcurl.cpp b/linden/indra/llmessage/llcurl.cpp
index 362204a..b94a41e 100644
--- a/linden/indra/llmessage/llcurl.cpp
+++ b/linden/indra/llmessage/llcurl.cpp
@@ -96,7 +96,7 @@ namespace boost
void intrusive_ptr_release(LLCurl::Responder* p)
{
- if(0 == --p->mReferenceCount)
+ if(p && 0 == --p->mReferenceCount)
{
delete p;
}
diff --git a/linden/indra/llmessage/lldatapacker.cpp b/linden/indra/llmessage/lldatapacker.cpp
index 3cdaa25..8725870 100644
--- a/linden/indra/llmessage/lldatapacker.cpp
+++ b/linden/indra/llmessage/lldatapacker.cpp
@@ -1895,7 +1895,10 @@ BOOL LLDataPackerAsciiFile::getValueStr(const char *name, char *out_value, S32 v
{
fpos_t last_pos;
fgetpos(mFP, &last_pos);
- fgets(buffer, DP_BUFSIZE, mFP);
+ if (fgets(buffer, DP_BUFSIZE, mFP) == NULL)
+ {
+ buffer[0] = '\0';
+ }
sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
diff --git a/linden/indra/llmessage/llhttpassetstorage.cpp b/linden/indra/llmessage/llhttpassetstorage.cpp
index d83349b..b6c20b9 100644
--- a/linden/indra/llmessage/llhttpassetstorage.cpp
+++ b/linden/indra/llmessage/llhttpassetstorage.cpp
@@ -38,7 +38,11 @@
#include "llvfile.h"
#include "llvfs.h"
-#include "zlib/zlib.h"
+#ifdef LL_STANDALONE
+# include
+#else
+# include "zlib/zlib.h"
+#endif
const U32 MAX_RUNNING_REQUESTS = 1;
const F32 MAX_PROCESSING_TIME = 0.005f;
diff --git a/linden/indra/llmessage/llhttpclient.cpp b/linden/indra/llmessage/llhttpclient.cpp
index 392dfd0..e36503a 100644
--- a/linden/indra/llmessage/llhttpclient.cpp
+++ b/linden/indra/llmessage/llhttpclient.cpp
@@ -252,6 +252,7 @@ static void request(
LLURLRequest::ERequestAction method,
Injector* body_injector,
LLHTTPClient::ResponderPtr responder,
+ const LLSD& headers,
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS)
{
if (!LLHTTPClient::hasPump())
@@ -263,6 +264,19 @@ static void request(
LLURLRequest *req = new LLURLRequest(method, url);
req->requestEncoding("");
+
+ if (headers.isMap())
+ {
+ LLSD::map_const_iterator iter = headers.beginMap();
+ LLSD::map_const_iterator end = headers.endMap();
+
+ for (; iter != end; ++iter)
+ {
+ std::ostringstream header;
+ header << iter->first << ": " << iter->second.asString() ;
+ req->addHeader(header.str().c_str());
+ }
+ }
if (!gCABundle.empty())
{
req->checkRootCertificate(true, gCABundle.c_str());
@@ -287,17 +301,37 @@ static void request(
theClientPump->addChain(chain, timeout);
}
+static void request(
+ const std::string& url,
+ LLURLRequest::ERequestAction method,
+ Injector* body_injector,
+ LLHTTPClient::ResponderPtr responder,
+ const F32 timeout=HTTP_REQUEST_EXPIRY_SECS)
+{
+ request(url, method, body_injector, responder, LLSD(), timeout);
+}
+
+void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout)
+{
+ request(url, LLURLRequest::HTTP_GET, NULL, responder, headers, timeout);
+}
+
void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const F32 timeout)
{
- request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout);
+ get(url, responder, LLSD(), timeout);
}
-void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const F32 timeout)
+void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers, const F32 timeout)
{
LLURI uri;
uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
- get(uri.asString(), responder, timeout);
+ get(uri.asString(), responder, headers, timeout);
+}
+
+void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const F32 timeout)
+{
+ get(url, query, responder, LLSD(), timeout);
}
// A simple class for managing data returned from a curl http request.
diff --git a/linden/indra/llmessage/llhttpclient.h b/linden/indra/llmessage/llhttpclient.h
index 88f8cbb..578b176 100644
--- a/linden/indra/llmessage/llhttpclient.h
+++ b/linden/indra/llmessage/llhttpclient.h
@@ -79,7 +79,9 @@ public:
typedef boost::intrusive_ptr ResponderPtr;
static void get(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+ static void get(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
static void get(const std::string& url, const LLSD& query, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+ static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
static void put(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
///< non-blocking
static void post(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
diff --git a/linden/indra/llmessage/lliohttpserver.cpp b/linden/indra/llmessage/lliohttpserver.cpp
index 5c96102..3c8010b 100644
--- a/linden/indra/llmessage/lliohttpserver.cpp
+++ b/linden/indra/llmessage/lliohttpserver.cpp
@@ -53,6 +53,7 @@
static const char HTTP_VERSION_STR[] = "HTTP/1.0";
static const std::string CONTEXT_REQUEST("request");
+static const std::string CONTEXT_RESPONSE("response");
static const std::string HTTP_VERB_GET("GET");
static const std::string HTTP_VERB_PUT("PUT");
static const std::string HTTP_VERB_POST("POST");
@@ -156,10 +157,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
LLBufferStream istr(channels, buffer.get());
static LLTimer timer;
- if (sTimingCallback)
- {
- timer.reset();
- }
+ timer.reset();
std::string verb = context[CONTEXT_REQUEST]["verb"];
if(verb == HTTP_VERB_GET)
@@ -189,6 +187,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
mResponse->methodNotAllowed();
}
+ F32 delta = timer.getElapsedTimeF32();
if (sTimingCallback)
{
LLHTTPNode::Description desc;
@@ -197,16 +196,20 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
std::string timing_name = info["description"];
timing_name += " ";
timing_name += verb;
- F32 delta = timer.getElapsedTimeF32();
sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
}
+ // Log all HTTP transactions.
+ llinfos << verb << " " << context[CONTEXT_REQUEST]["path"].asString()
+ << " " << mStatusCode << " " << mStatusMessage << " " << delta
+ << "s" << llendl;
+
// Log Internal Server Errors
- if(mStatusCode == 500)
- {
- llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error"
- << llendl;
- }
+ //if(mStatusCode == 500)
+ //{
+ // llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error"
+ // << llendl;
+ //}
}
PUMP_DEBUG;
@@ -223,7 +226,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
case STATE_GOOD_RESULT:
{
- context["response"]["contentType"] = "application/xml";
+ context[CONTEXT_RESPONSE]["contentType"] = "application/xml";
LLBufferStream ostr(channels, buffer.get());
LLSDSerialize::toXML(mGoodResult, ostr);
@@ -232,9 +235,9 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
case STATE_STATUS_RESULT:
{
- context["response"]["contentType"] = "text/plain";
- context["response"]["statusCode"] = mStatusCode;
- context["response"]["statusMessage"] = mStatusMessage;
+ context[CONTEXT_RESPONSE]["contentType"] = "text/plain";
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
LLBufferStream ostr(channels, buffer.get());
ostr << mStatusMessage << std::ends;
@@ -371,9 +374,9 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
PUMP_DEBUG;
//mGotEOS = true;
std::ostringstream ostr;
- std::string message = context["response"]["statusMessage"];
+ std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
- int code = context["response"]["statusCode"];
+ int code = context[CONTEXT_RESPONSE]["statusCode"];
if (code < 200)
{
code = 200;
@@ -382,7 +385,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n";
- std::string type = context["response"]["contentType"].asString();
+ std::string type = context[CONTEXT_RESPONSE]["contentType"].asString();
if (!type.empty())
{
ostr << "Content-Type: " << type << "\r\n";
diff --git a/linden/indra/llmessage/llmessageconfig.cpp b/linden/indra/llmessage/llmessageconfig.cpp
index 8d114a9..6ecb1ad 100644
--- a/linden/indra/llmessage/llmessageconfig.cpp
+++ b/linden/indra/llmessage/llmessageconfig.cpp
@@ -252,3 +252,19 @@ bool LLMessageConfig::isCapBanned(const std::string& cap_name)
{
return LLMessageConfigFile::instance().isCapBanned(cap_name);
}
+
+// return the web-service path to use for a given
+// message. This entry *should* match the entry
+// in simulator.xml!
+LLSD LLMessageConfig::getConfigForMessage(const std::string& msg_name)
+{
+ if (sServerName.empty())
+ {
+ llerrs << "LLMessageConfig::isMessageTrusted(name) before"
+ << " LLMessageConfig::initClass()" << llendl;
+ }
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ // LLSD for the CamelCase message name
+ LLSD config = file.mMessages[msg_name];
+ return config;
+}
diff --git a/linden/indra/llmessage/llmessageconfig.h b/linden/indra/llmessage/llmessageconfig.h
index ca09c27..86e7fb0 100644
--- a/linden/indra/llmessage/llmessageconfig.h
+++ b/linden/indra/llmessage/llmessageconfig.h
@@ -30,6 +30,7 @@
#define LL_MESSAGECONFIG_H
#include
+#include "llsd.h"
class LLSD;
@@ -50,5 +51,6 @@ public:
static SenderTrust getSenderTrustedness(const std::string& msg_name);
static bool isValidMessage(const std::string& msg_name);
static bool isCapBanned(const std::string& cap_name);
+ static LLSD getConfigForMessage(const std::string& msg_name);
};
#endif // LL_MESSAGECONFIG_H
diff --git a/linden/indra/llmessage/llmessagereader.cpp b/linden/indra/llmessage/llmessagereader.cpp
index db4cbdf..2679019 100644
--- a/linden/indra/llmessage/llmessagereader.cpp
+++ b/linden/indra/llmessage/llmessagereader.cpp
@@ -1,5 +1,5 @@
/**
- * @file llsdmessagereader.cpp
+ * @file llmessagereader.cpp
* @brief LLMessageReader class implementation
*
* Copyright (c) 2007-2007, Linden Research, Inc.
@@ -26,6 +26,7 @@
* COMPLETENESS OR PERFORMANCE.
*/
+#include "linden_common.h"
#include "llmessagereader.h"
static BOOL sTimeDecodes = FALSE;
diff --git a/linden/indra/llmessage/llmessagetemplateparser.cpp b/linden/indra/llmessage/llmessagetemplateparser.cpp
index eb5e87e..4c14ede 100644
--- a/linden/indra/llmessage/llmessagetemplateparser.cpp
+++ b/linden/indra/llmessage/llmessagetemplateparser.cpp
@@ -26,6 +26,7 @@
* COMPLETENESS OR PERFORMANCE.
*/
+#include "linden_common.h"
#include "llmessagetemplateparser.h"
#include
diff --git a/linden/indra/llmessage/llnamevalue.cpp b/linden/indra/llmessage/llnamevalue.cpp
index 6e449ed..a11bf97 100644
--- a/linden/indra/llmessage/llnamevalue.cpp
+++ b/linden/indra/llmessage/llnamevalue.cpp
@@ -122,6 +122,9 @@ void LLNameValue::baseInit()
mSendto = NVS_NULL;
mStringSendto = NameValueSendtoStrings[NVS_NULL];
+
+ mNameValueCB = NULL;
+ mUserData = NULL;
}
void LLNameValue::init(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto, TNameValueCallback nvcb, void **user_data)
diff --git a/linden/indra/llmessage/llnamevalue.h b/linden/indra/llmessage/llnamevalue.h
index fe733fa..580c99d 100644
--- a/linden/indra/llmessage/llnamevalue.h
+++ b/linden/indra/llmessage/llnamevalue.h
@@ -194,7 +194,6 @@ public:
ENameValueSendto mSendto;
UNameValueReference mNameValueReference;
- S32 mNumberEntries;
LLStringTable *mNVNameTable;
TNameValueCallback mNameValueCB;
void **mUserData;
diff --git a/linden/indra/llmessage/llservicebuilder.cpp b/linden/indra/llmessage/llservicebuilder.cpp
index 91040c0..0b35a69 100644
--- a/linden/indra/llmessage/llservicebuilder.cpp
+++ b/linden/indra/llmessage/llservicebuilder.cpp
@@ -109,7 +109,7 @@ std::string LLServiceBuilder::buildServiceURI(
const LLSD& option_map)
{
std::string service_url = buildServiceURI(service_name);
-
+
// Find the Service Name
if(!service_url.empty() && option_map.isMap())
{
@@ -128,6 +128,23 @@ std::string LLServiceBuilder::buildServiceURI(
find_pos,
variable_name.length(),
(*option_itr).second.asString());
+ continue;
+ }
+ variable_name.assign("{%");
+ variable_name.append((*option_itr).first);
+ variable_name.append("}");
+ find_pos = service_url.find(variable_name);
+ if(find_pos != std::string::npos)
+ {
+ std::string query_str = LLURI::mapToQueryString(
+ (*option_itr).second);
+ if(!query_str.empty())
+ {
+ service_url.replace(
+ find_pos,
+ variable_name.length(),
+ query_str);
+ }
}
}
}
diff --git a/linden/indra/llmessage/lltemplatemessagereader.cpp b/linden/indra/llmessage/lltemplatemessagereader.cpp
index a1f5213..329d2a8 100644
--- a/linden/indra/llmessage/lltemplatemessagereader.cpp
+++ b/linden/indra/llmessage/lltemplatemessagereader.cpp
@@ -26,6 +26,7 @@
* COMPLETENESS OR PERFORMANCE.
*/
+#include "linden_common.h"
#include "lltemplatemessagereader.h"
#include "llfasttimer.h"
@@ -351,7 +352,7 @@ void LLTemplateMessageReader::getF64(const char *block, const char *var,
void LLTemplateMessageReader::getVector3(const char *block, const char *var,
LLVector3 &v, S32 blocknum )
{
- getData(block, var, v.mV, sizeof(v.mV), blocknum);
+ getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
if( !v.isFinite() )
{
@@ -364,7 +365,7 @@ void LLTemplateMessageReader::getVector3(const char *block, const char *var,
void LLTemplateMessageReader::getVector4(const char *block, const char *var,
LLVector4 &v, S32 blocknum)
{
- getData(block, var, v.mV, sizeof(v.mV), blocknum);
+ getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
if( !v.isFinite() )
{
@@ -377,7 +378,7 @@ void LLTemplateMessageReader::getVector4(const char *block, const char *var,
void LLTemplateMessageReader::getVector3d(const char *block, const char *var,
LLVector3d &v, S32 blocknum )
{
- getData(block, var, v.mdV, sizeof(v.mdV), blocknum);
+ getData(block, var, &v.mdV[0], sizeof(v.mdV), blocknum);
if( !v.isFinite() )
{
@@ -392,7 +393,7 @@ void LLTemplateMessageReader::getQuat(const char *block, const char *var,
LLQuaternion &q, S32 blocknum)
{
LLVector3 vec;
- getData(block, var, vec.mV, sizeof(vec.mV), blocknum);
+ getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
if( vec.isFinite() )
{
q.unpackFromVector3( vec );
@@ -408,7 +409,7 @@ void LLTemplateMessageReader::getQuat(const char *block, const char *var,
void LLTemplateMessageReader::getUUID(const char *block, const char *var,
LLUUID &u, S32 blocknum)
{
- getData(block, var, u.mData, sizeof(u.mData), blocknum);
+ getData(block, var, &u.mData[0], sizeof(u.mData), blocknum);
}
inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
diff --git a/linden/indra/llmessage/lluseroperation.cpp b/linden/indra/llmessage/lluseroperation.cpp
index 29146ea..f43e02a 100644
--- a/linden/indra/llmessage/lluseroperation.cpp
+++ b/linden/indra/llmessage/lluseroperation.cpp
@@ -42,7 +42,8 @@ LLUserOperationMgr* gUserOperationMgr = NULL;
LLUserOperation::LLUserOperation(const LLUUID& agent_id)
: mAgentID(agent_id),
- mTimer()
+ mTimer(),
+ mNoExpire(FALSE)
{
mTransactionID.generate();
}
@@ -51,14 +52,16 @@ LLUserOperation::LLUserOperation(const LLUUID& agent_id,
const LLUUID& transaction_id) :
mAgentID(agent_id),
mTransactionID(transaction_id),
- mTimer()
+ mTimer(),
+ mNoExpire(FALSE)
{
}
// protected constructor which is used by base classes that determine
// transaction, agent, et. after construction.
LLUserOperation::LLUserOperation() :
- mTimer()
+ mTimer(),
+ mNoExpire(FALSE)
{
}
@@ -66,11 +69,19 @@ LLUserOperation::~LLUserOperation()
{
}
+void LLUserOperation::SetNoExpireFlag(const BOOL flag)
+{
+ mNoExpire = flag;
+}
BOOL LLUserOperation::isExpired()
{
- const F32 EXPIRE_TIME_SECS = 10.f;
- return mTimer.getElapsedTimeF32() > EXPIRE_TIME_SECS;
+ if (!mNoExpire)
+ {
+ const F32 EXPIRE_TIME_SECS = 10.f;
+ return mTimer.getElapsedTimeF32() > EXPIRE_TIME_SECS;
+ }
+ return FALSE;
}
void LLUserOperation::expire()
diff --git a/linden/indra/llmessage/lluseroperation.h b/linden/indra/llmessage/lluseroperation.h
index 2b351f9..6ac2862 100644
--- a/linden/indra/llmessage/lluseroperation.h
+++ b/linden/indra/llmessage/lluseroperation.h
@@ -48,6 +48,9 @@ public:
// Operation never got necessary data, so expired
virtual BOOL isExpired();
+ // ability to mark this operation as never expiring.
+ void SetNoExpireFlag(const BOOL flag);
+
// Send request to the dataserver
virtual void sendRequest() = 0;
@@ -67,6 +70,7 @@ protected:
LLUUID mAgentID;
LLUUID mTransactionID;
LLFrameTimer mTimer;
+ BOOL mNoExpire; // this is used for operations that expect an answer and will wait till it gets one.
};
diff --git a/linden/indra/llmessage/llxfer_file.cpp b/linden/indra/llmessage/llxfer_file.cpp
index 33db248..b36dd5a 100644
--- a/linden/indra/llmessage/llxfer_file.cpp
+++ b/linden/indra/llmessage/llxfer_file.cpp
@@ -289,7 +289,11 @@ S32 LLXfer_File::flush()
if (mFp)
{
- fwrite(mBuffer,1,mBufferLength,mFp);
+ if (fwrite(mBuffer,1,mBufferLength,mFp) != mBufferLength)
+ {
+ llwarns << "Short write" << llendl;
+ }
+
// llinfos << "******* wrote " << mBufferLength << " bytes of file xfer" << llendl;
fclose(mFp);
mFp = NULL;
diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp
index 01dce40..a9d5dd3 100644
--- a/linden/indra/llmessage/message.cpp
+++ b/linden/indra/llmessage/message.cpp
@@ -405,6 +405,7 @@ LLMessageSystem::~LLMessageSystem()
{
end_net(mSocket);
}
+ mSocket = 0;
delete mTemplateMessageReader;
mTemplateMessageReader = NULL;
diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h
index 6c834f7..d18bd09 100644
--- a/linden/indra/llmessage/message.h
+++ b/linden/indra/llmessage/message.h
@@ -39,6 +39,10 @@
#include
#endif
+#if LL_SOLARIS
+#include
+#endif
+
#if LL_WINDOWS
#include "winsock2.h" // htons etc.
#endif
@@ -204,14 +208,14 @@ public:
class LLMessageSystem
{
private:
- U8 mSendBuffer[MAX_BUFFER_SIZE];
- S32 mSendSize;
+ U8 mSendBuffer[MAX_BUFFER_SIZE];
+ S32 mSendSize;
public:
- LLPacketRing mPacketRing;
- LLReliablePacketParams mReliablePacketParams;
+ LLPacketRing mPacketRing;
+ LLReliablePacketParams mReliablePacketParams;
- //LLLinkedList mAckList;
+ //LLLinkedList mAckList;
// Set this flag to TRUE when you want *very* verbose logs.
BOOL mVerboseLog;
@@ -222,36 +226,35 @@ class LLMessageSystem
typedef std::map message_template_number_map_t;
private:
- message_template_name_map_t mMessageTemplates;
- message_template_number_map_t mMessageNumbers;
+ message_template_name_map_t mMessageTemplates;
+ message_template_number_map_t mMessageNumbers;
public:
- S32 mSystemVersionMajor;
- S32 mSystemVersionMinor;
- S32 mSystemVersionPatch;
- S32 mSystemVersionServer;
- U32 mVersionFlags;
+ S32 mSystemVersionMajor;
+ S32 mSystemVersionMinor;
+ S32 mSystemVersionPatch;
+ S32 mSystemVersionServer;
+ U32 mVersionFlags;
+ BOOL mbProtected;
- BOOL mbProtected;
+ U32 mNumberHighFreqMessages;
+ U32 mNumberMediumFreqMessages;
+ U32 mNumberLowFreqMessages;
+ S32 mPort;
+ S32 mSocket;
- U32 mNumberHighFreqMessages;
- U32 mNumberMediumFreqMessages;
- U32 mNumberLowFreqMessages;
- S32 mPort;
- S32 mSocket;
+ U32 mPacketsIn; // total packets in, including compressed and uncompressed
+ U32 mPacketsOut; // total packets out, including compressed and uncompressed
- U32 mPacketsIn; // total packets in, including compressed and uncompressed
- U32 mPacketsOut; // total packets out, including compressed and uncompressed
-
- U64 mBytesIn; // total bytes in, including compressed and uncompressed
- U64 mBytesOut; // total bytes out, including compressed and uncompressed
+ U64 mBytesIn; // total bytes in, including compressed and uncompressed
+ U64 mBytesOut; // total bytes out, including compressed and uncompressed
- U32 mCompressedPacketsIn; // total compressed packets in
- U32 mCompressedPacketsOut; // total compressed packets out
+ U32 mCompressedPacketsIn; // total compressed packets in
+ U32 mCompressedPacketsOut; // total compressed packets out
- U32 mReliablePacketsIn; // total reliable packets in
- U32 mReliablePacketsOut; // total reliable packets out
+ U32 mReliablePacketsIn; // total reliable packets in
+ U32 mReliablePacketsOut; // total reliable packets out
U32 mDroppedPackets; // total dropped packets in
U32 mResentPackets; // total resent packets out
@@ -259,26 +262,26 @@ public:
U32 mOffCircuitPackets; // total # of off-circuit packets rejected
U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected
- S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in
- S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out
- S64 mCompressedBytesIn; // total compressed size of compressed packets in
- S64 mCompressedBytesOut; // total compressed size of compressed packets out
- S64 mTotalBytesIn; // total size of all uncompressed packets in
- S64 mTotalBytesOut; // total size of all uncompressed packets out
+ S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in
+ S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out
+ S64 mCompressedBytesIn; // total compressed size of compressed packets in
+ S64 mCompressedBytesOut; // total compressed size of compressed packets out
+ S64 mTotalBytesIn; // total size of all uncompressed packets in
+ S64 mTotalBytesOut; // total size of all uncompressed packets out
BOOL mSendReliable; // does the outgoing message require a pos ack?
- LLCircuit mCircuitInfo;
- F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes
- F32 mCircuitPrintFreq; // seconds
+ LLCircuit mCircuitInfo;
+ F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes
+ F32 mCircuitPrintFreq; // seconds
- std::map mIPPortToCircuitCode;
- std::map mCircuitCodeToIPPort;
- U32 mOurCircuitCode;
- S32 mSendPacketFailureCount;
- S32 mUnackedListDepth;
- S32 mUnackedListSize;
- S32 mDSMaxListDepth;
+ std::map mIPPortToCircuitCode;
+ std::map mCircuitCodeToIPPort;
+ U32 mOurCircuitCode;
+ S32 mSendPacketFailureCount;
+ S32 mUnackedListDepth;
+ S32 mUnackedListSize;
+ S32 mDSMaxListDepth;
public:
// Read file and build message templates
@@ -693,14 +696,14 @@ private:
LLMessagePollInfo *mPollInfop;
- U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE];
- U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE];
- S32 mTrueReceiveSize;
+ U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE];
+ U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE];
+ S32 mTrueReceiveSize;
// Must be valid during decode
- BOOL mbError;
- S32 mErrorCode;
+ BOOL mbError;
+ S32 mErrorCode;
F64 mResendDumpTime; // The last time we dumped resends
@@ -775,6 +778,10 @@ void null_message_callback(LLMessageSystem *msg, void **data);
// Inlines
//
+#if !defined( LL_BIG_ENDIAN ) && !defined( LL_LITTLE_ENDIAN )
+#error Unknown endianness for htonmemcpy. Did you miss a common include?
+#endif
+
static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
{
char *s = (char *)vs;
diff --git a/linden/indra/llrender/llfont.cpp b/linden/indra/llrender/llfont.cpp
index ed787e0..b07d0d6 100644
--- a/linden/indra/llrender/llfont.cpp
+++ b/linden/indra/llrender/llfont.cpp
@@ -31,10 +31,11 @@
#include "llfont.h"
// Freetype stuff
-#if LL_LINUX // I had to do some work to avoid the system-installed FreeType headers... --ryan.
-#include "llfreetype2/freetype/ft2build.h"
+#if !defined(LL_LINUX) || defined(LL_STANDALONE)
+# include
#else
-#include
+// I had to do some work to avoid the system-installed FreeType headers... --ryan.
+# include "llfreetype2/freetype/ft2build.h"
#endif
// For some reason, this won't work if it's not wrapped in the ifdef
@@ -178,11 +179,20 @@ F32 LLFont::getDescenderHeight() const
BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback)
{
+ // Don't leak face objects. This is also needed to deal with
+ // changed font file names.
+ if (mFTFace)
+ {
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+ }
+
int error;
+
error = FT_New_Face( gFTLibrary,
- filename.c_str(),
- 0,
- &mFTFace );
+ filename.c_str(),
+ 0,
+ &mFTFace );
if (error)
{
@@ -326,6 +336,9 @@ BOOL LLFont::hasGlyph(const llwchar wch) const
BOOL LLFont::addChar(const llwchar wch)
{
+ if (mFTFace == NULL)
+ return FALSE;
+
llassert(!mIsFallback);
//lldebugs << "Adding new glyph for " << wch << " to font" << llendl;
@@ -378,6 +391,9 @@ void LLFont::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
BOOL LLFont::addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_index)
{
+ if (mFTFace == NULL)
+ return FALSE;
+
llassert(!mIsFallback);
fontp->renderGlyph(glyph_index);
S32 width = fontp->mFTFace->glyph->bitmap.width;
@@ -501,6 +517,9 @@ BOOL LLFont::addGlyph(const llwchar wch, const U32 glyph_index)
F32 LLFont::getXAdvance(const llwchar wch) const
{
+ if (mFTFace == NULL)
+ return 0.0;
+
llassert(!mIsFallback);
U32 glyph_index;
@@ -569,6 +588,9 @@ F32 LLFont::getXAdvance(const llwchar wch) const
void LLFont::renderGlyph(const U32 glyph_index)
{
+ if (mFTFace == NULL)
+ return;
+
int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT );
llassert(!error);
@@ -579,6 +601,9 @@ void LLFont::renderGlyph(const U32 glyph_index)
F32 LLFont::getXKerning(const llwchar char_left, const llwchar char_right) const
{
+ if (mFTFace == NULL)
+ return 0.0;
+
llassert(!mIsFallback);
LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL);
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp
index e2c4a59..a2e5abc 100644
--- a/linden/indra/llrender/llimagegl.cpp
+++ b/linden/indra/llrender/llimagegl.cpp
@@ -963,7 +963,8 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level)
}
else
{
-#ifndef LL_LINUX // *FIX: This should not be skipped for the linux client.
+#if !LL_LINUX && !LL_SOLARIS
+ // *FIX: This should not be skipped for the linux client.
llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl;
#endif
return FALSE;
diff --git a/linden/indra/llrender/llimagegl.h b/linden/indra/llrender/llimagegl.h
index 16315ee..3bdd1c9 100644
--- a/linden/indra/llrender/llimagegl.h
+++ b/linden/indra/llrender/llimagegl.h
@@ -136,7 +136,6 @@ public:
// Various GL/Rendering options
S32 mTextureMemory;
mutable F32 mLastBindTime; // last time this was bound, by discard level
- mutable F32 mLastBindAttempt; // last time bindTexture was called on this texture
private:
LLPointer mSaveData; // used for destroyGL/restoreGL
diff --git a/linden/indra/llui/files.lst b/linden/indra/llui/files.lst
index 5a62573..96bb170 100644
--- a/linden/indra/llui/files.lst
+++ b/linden/indra/llui/files.lst
@@ -8,7 +8,6 @@ llui/lldraghandle.cpp
llui/lleditmenuhandler.cpp
llui/llfloater.cpp
llui/llfocusmgr.cpp
-llui/llhtmlhelp.h
llui/lliconctrl.cpp
llui/llkeywords.cpp
llui/lllineeditor.cpp
diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp
index de8b82e..aa50a6e 100644
--- a/linden/indra/llui/llbutton.cpp
+++ b/linden/indra/llui/llbutton.cpp
@@ -89,7 +89,8 @@ LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& co
mCurGlowStrength(0.f),
mNeedsHighlight(FALSE),
mCommitOnReturn(TRUE),
- mImagep( NULL )
+ mImagep( NULL ),
+ mIsDirty( FALSE )
{
mUnselectedLabel = name;
mSelectedLabel = name;
@@ -216,6 +217,9 @@ void LLButton::init(void (*click_callback)(void*), void *callback_data, const LL
mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) );
mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) );
mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) );
+
+ mImageOverlayAlignment = LLFontGL::HCENTER;
+ mImageOverlayColor = LLColor4::white;
}
LLButton::~LLButton()
@@ -271,8 +275,12 @@ void LLButton::onCommit()
{
(*mClickedCallback)( mCallbackUserData );
}
+
+ mIsDirty = TRUE;
}
+
+
BOOL LLButton::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
{
BOOL handled = FALSE;
@@ -282,7 +290,8 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
{
(*mClickedCallback)( mCallbackUserData );
}
- handled = TRUE;
+ handled = TRUE;
+ mIsDirty = TRUE;
}
return handled;
}
@@ -299,6 +308,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
(*mClickedCallback)( mCallbackUserData );
}
handled = TRUE;
+ mIsDirty = TRUE;
}
}
return handled;
@@ -359,6 +369,8 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
{
(*mClickedCallback)( mCallbackUserData );
}
+
+ mIsDirty = TRUE;
}
mMouseDownTimer.stop();
@@ -618,7 +630,7 @@ void LLButton::draw()
// draw overlay image
if (mImageOverlay.notNull())
{
- const S32 IMG_PAD = 4;
+ const S32 IMG_PAD = 5;
// get max width and height (discard level 0)
S32 overlay_width = mImageOverlay->getWidth(0);
S32 overlay_height = mImageOverlay->getHeight(0);
@@ -639,7 +651,7 @@ void LLButton::draw()
overlay_width,
overlay_height,
mImageOverlay,
- LLColor4::white);
+ mImageOverlayColor);
break;
case LLFontGL::HCENTER:
gl_draw_scaled_image(
@@ -648,7 +660,7 @@ void LLButton::draw()
overlay_width,
overlay_height,
mImageOverlay,
- LLColor4::white);
+ mImageOverlayColor);
break;
case LLFontGL::RIGHT:
gl_draw_scaled_image(
@@ -657,7 +669,7 @@ void LLButton::draw()
overlay_width,
overlay_height,
mImageOverlay,
- LLColor4::white);
+ mImageOverlayColor);
break;
default:
// draw nothing
@@ -761,6 +773,7 @@ void LLButton::setToggleState(BOOL b)
void LLButton::setValue(const LLSD& value )
{
mToggleState = value.asBoolean();
+ mIsDirty = FALSE;
}
LLSD LLButton::getValue() const
@@ -876,7 +889,7 @@ void LLButton::setHoverImages( const LLString& image_name, const LLString& selec
setImageHoverSelected(selected_name);
}
-void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment)
+void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment, const LLColor4& color)
{
if (image_name.empty())
{
@@ -887,6 +900,7 @@ void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alig
LLUUID overlay_image_id = LLUI::findAssetUUIDByName(image_name);
mImageOverlay = LLUI::sImageProvider->getUIImageByID(overlay_image_id);
mImageOverlayAlignment = alignment;
+ mImageOverlayColor = color;
}
}
diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h
index 6e11779..aedc411 100644
--- a/linden/indra/llui/llbutton.h
+++ b/linden/indra/llui/llbutton.h
@@ -100,6 +100,8 @@ public:
// HACK: "committing" a button is the same as clicking on it.
virtual void onCommit();
+ virtual BOOL isDirty() { return mIsDirty; }; // Returns TRUE if the user has clicked on the button at all
+
void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; }
void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; }
@@ -142,7 +144,7 @@ public:
void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; }
- void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER);
+ void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
LLPointer getImageOverlay() { return mImageOverlay; }
@@ -208,6 +210,7 @@ protected:
LLPointer mImageOverlay;
LLFontGL::HAlign mImageOverlayAlignment;
+ LLColor4 mImageOverlayColor;
LLPointer mImageUnselected;
LLUIString mUnselectedLabel;
@@ -276,6 +279,8 @@ protected:
LLPointer mImagep;
+ BOOL mIsDirty;
+
static LLFrameTimer sFlashingTimer;
};
diff --git a/linden/indra/llui/llcheckboxctrl.cpp b/linden/indra/llui/llcheckboxctrl.cpp
index 5f3350e..24cf680 100644
--- a/linden/indra/llui/llcheckboxctrl.cpp
+++ b/linden/indra/llui/llcheckboxctrl.cpp
@@ -267,6 +267,18 @@ void LLCheckBoxCtrl::setControlName(const LLString& control_name, LLView* contex
mButton->setControlName(control_name, context);
}
+
+// virtual Returns TRUE if the user has modified this control.
+BOOL LLCheckBoxCtrl::isDirty()
+{
+ if ( mButton )
+ {
+ return mButton->isDirty();
+ }
+ return FALSE; // Shouldn't get here
+}
+
+
// virtual
LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const
{
diff --git a/linden/indra/llui/llcheckboxctrl.h b/linden/indra/llui/llcheckboxctrl.h
index 1b895cb..37b1330 100644
--- a/linden/indra/llui/llcheckboxctrl.h
+++ b/linden/indra/llui/llcheckboxctrl.h
@@ -110,6 +110,8 @@ public:
static void onButtonPress(void *userdata);
+ virtual BOOL isDirty(); // Returns TRUE if the user has modified this control.
+
protected:
// note: value is stored in toggle state of button
LLButton* mButton;
diff --git a/linden/indra/llui/llctrlselectioninterface.h b/linden/indra/llui/llctrlselectioninterface.h
index 878648d..e21f039 100644
--- a/linden/indra/llui/llctrlselectioninterface.h
+++ b/linden/indra/llui/llctrlselectioninterface.h
@@ -51,6 +51,8 @@ public:
virtual BOOL getCanSelect() const = 0;
+ virtual S32 getItemCount() const = 0;
+
virtual BOOL selectFirstItem() = 0;
virtual BOOL selectNthItem( S32 index ) = 0;
@@ -76,7 +78,6 @@ class LLCtrlListInterface : public LLCtrlSelectionInterface
public:
virtual ~LLCtrlListInterface();
- virtual S32 getItemCount() const = 0;
virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM) = 0;
virtual void clearColumns() = 0;
virtual void setColumnLabel(const LLString& column, const LLString& label) = 0;
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp
index 6ab182f..b45661f 100644
--- a/linden/indra/llui/llfloater.cpp
+++ b/linden/indra/llui/llfloater.cpp
@@ -312,28 +312,32 @@ void LLFloater::init(const LLString& title,
{
// Resize bars (sides)
const S32 RESIZE_BAR_THICKNESS = 3;
- mResizeBar[0] = new LLResizeBar(
+ mResizeBar[LLResizeBar::LEFT] = new LLResizeBar(
"resizebar_left",
+ this,
LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0),
- min_width, min_height, LLResizeBar::LEFT );
+ min_width, S32_MAX, LLResizeBar::LEFT );
addChild( mResizeBar[0] );
- mResizeBar[1] = new LLResizeBar(
+ mResizeBar[LLResizeBar::TOP] = new LLResizeBar(
"resizebar_top",
+ this,
LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS),
- min_width, min_height, LLResizeBar::TOP );
+ min_height, S32_MAX, LLResizeBar::TOP );
addChild( mResizeBar[1] );
- mResizeBar[2] = new LLResizeBar(
+ mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar(
"resizebar_right",
+ this,
LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
- min_width, min_height, LLResizeBar::RIGHT );
+ min_width, S32_MAX, LLResizeBar::RIGHT );
addChild( mResizeBar[2] );
- mResizeBar[3] = new LLResizeBar(
+ mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar(
"resizebar_bottom",
+ this,
LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0),
- min_width, min_height, LLResizeBar::BOTTOM );
+ min_height, S32_MAX, LLResizeBar::BOTTOM );
addChild( mResizeBar[3] );
@@ -367,18 +371,6 @@ void LLFloater::init(const LLString& title,
LLResizeHandle::LEFT_TOP );
addChild(mResizeHandle[3]);
}
- else
- {
- mResizeBar[0] = NULL;
- mResizeBar[1] = NULL;
- mResizeBar[2] = NULL;
- mResizeBar[3] = NULL;
-
- mResizeHandle[0] = NULL;
- mResizeHandle[1] = NULL;
- mResizeHandle[2] = NULL;
- mResizeHandle[3] = NULL;
- }
// Close button.
if (close_btn)
@@ -392,6 +384,13 @@ void LLFloater::init(const LLString& title,
mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
}
+ // Keep track of whether this window has ever been dragged while it
+ // was minimized. If it has, we'll remember its position for the
+ // next time it's minimized.
+ mHasBeenDraggedWhileMinimized = FALSE;
+ mPreviousMinimizedLeft = 0;
+ mPreviousMinimizedBottom = 0;
+
buildButtons();
// JC - Don't do this here, because many floaters first construct themselves,
@@ -626,7 +625,14 @@ void LLFloater::setResizeLimits( S32 min_width, S32 min_height )
{
if( mResizeBar[i] )
{
- mResizeBar[i]->setResizeLimits( min_width, min_height );
+ if (i == LLResizeBar::LEFT || i == LLResizeBar::RIGHT)
+ {
+ mResizeBar[i]->setResizeLimits( min_width, S32_MAX );
+ }
+ else
+ {
+ mResizeBar[i]->setResizeLimits( min_height, S32_MAX );
+ }
}
if( mResizeHandle[i] )
{
@@ -678,6 +684,25 @@ const LLString& LLFloater::getTitle() const
return mDragHandle ? mDragHandle->getTitle() : LLString::null;
}
+void LLFloater::setShortTitle( const LLString& short_title )
+{
+ mShortTitle = short_title;
+}
+
+LLString LLFloater::getShortTitle()
+{
+ if (mShortTitle.empty())
+ {
+ return mDragHandle ? mDragHandle->getTitle() : LLString::null;
+ }
+ else
+ {
+ return mShortTitle;
+ }
+}
+
+
+
BOOL LLFloater::canSnapTo(LLView* other_view)
{
if (NULL == other_view)
@@ -757,6 +782,16 @@ void LLFloater::userSetShape(const LLRect& new_rect)
}
}
}
+ else
+ {
+ // If minimized, and origin has changed, set
+ // mHasBeenDraggedWhileMinimized to TRUE
+ if ((new_rect.mLeft != old_rect.mLeft) ||
+ (new_rect.mBottom != old_rect.mBottom))
+ {
+ mHasBeenDraggedWhileMinimized = TRUE;
+ }
+ }
}
void LLFloater::setMinimized(BOOL minimize)
@@ -769,9 +804,19 @@ void LLFloater::setMinimized(BOOL minimize)
reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE);
- S32 left, bottom;
- gFloaterView->getMinimizePosition(&left, &bottom);
- setOrigin( left, bottom );
+ // If the floater has been dragged while minimized in the
+ // past, then locate it at its previous minimized location.
+ // Otherwise, ask the view for a minimize position.
+ if (mHasBeenDraggedWhileMinimized)
+ {
+ setOrigin(mPreviousMinimizedLeft, mPreviousMinimizedBottom);
+ }
+ else
+ {
+ S32 left, bottom;
+ gFloaterView->getMinimizePosition(&left, &bottom);
+ setOrigin( left, bottom );
+ }
if (mButtonsEnabled[BUTTON_MINIMIZE])
{
@@ -824,6 +869,15 @@ void LLFloater::setMinimized(BOOL minimize)
}
else
{
+ // If this window has been dragged while minimized (at any time),
+ // remember its position for the next time it's minimized.
+ if (mHasBeenDraggedWhileMinimized)
+ {
+ const LLRect& currentRect = getRect();
+ mPreviousMinimizedLeft = currentRect.mLeft;
+ mPreviousMinimizedBottom = currentRect.mBottom;
+ }
+
reshape( mPreviousRect.getWidth(), mPreviousRect.getHeight(), TRUE );
setOrigin( mPreviousRect.mLeft, mPreviousRect.mBottom );
@@ -987,12 +1041,22 @@ void LLFloater::setHost(LLMultiFloater* host)
}
}
-void LLFloater::moveResizeHandleToFront()
+void LLFloater::moveResizeHandlesToFront()
{
- // 0 is the bottom right
- if( mResizeHandle[0] )
+ for( S32 i = 0; i < 4; i++ )
{
- sendChildToFront(mResizeHandle[0]);
+ if( mResizeBar[i] )
+ {
+ sendChildToFront(mResizeBar[i]);
+ }
+ }
+
+ for( S32 i = 0; i < 4; i++ )
+ {
+ if( mResizeHandle[i] )
+ {
+ sendChildToFront(mResizeHandle[i]);
+ }
}
}
@@ -1040,7 +1104,6 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
if( mMinimized )
{
// Offer the click to the close button.
- // Any other click = restore
if( mButtonsEnabled[BUTTON_CLOSE] )
{
S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
@@ -1054,9 +1117,22 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
}
}
- // restore
- bringToFront( x, y );
- return TRUE;
+ // Offer the click to the restore button.
+ if( mButtonsEnabled[BUTTON_RESTORE] )
+ {
+ S32 local_x = x - mButtons[BUTTON_RESTORE]->getRect().mLeft;
+ S32 local_y = y - mButtons[BUTTON_RESTORE]->getRect().mBottom;
+
+ if (mButtons[BUTTON_RESTORE]->pointInView(local_x, local_y)
+ && mButtons[BUTTON_RESTORE]->handleMouseDown(local_x, local_y, mask))
+ {
+ // restore button handled it, return
+ return TRUE;
+ }
+ }
+
+ // Otherwise pass to drag handle for movement
+ return mDragHandle->handleMouseDown(x, y, mask);
}
else
{
@@ -1177,6 +1253,10 @@ BOOL LLFloater::getEditModeEnabled()
void LLFloater::show(LLFloater* floaterp)
{
if (floaterp) floaterp->open();
+ if (floaterp->getHost())
+ {
+ floaterp->getHost()->open();
+ }
}
//static
@@ -1190,7 +1270,7 @@ BOOL LLFloater::visible(LLFloater* floaterp)
{
if (floaterp)
{
- return floaterp->isInVisibleChain();
+ return !floaterp->isMinimized() && floaterp->isInVisibleChain();
}
return FALSE;
}
@@ -1217,12 +1297,15 @@ void LLFloater::onClickTearOff(void *userdata)
// reparent to floater view
gFloaterView->addChild(self);
- new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight());
-
self->open(); /* Flawfinder: ignore */
- self->setRect(new_rect);
+
+ // only force position for floaters that don't have that data saved
+ if (self->mRectControl.empty())
+ {
+ new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight());
+ self->setRect(new_rect);
+ }
gFloaterView->adjustToFitScreen(self, FALSE);
- self->setCanDrag(TRUE);
// give focus to new window to keep continuity for the user
self->setFocus(TRUE);
}
@@ -1232,6 +1315,8 @@ void LLFloater::onClickTearOff(void *userdata)
if (new_host)
{
new_host->showFloater(self);
+ // make sure host is visible
+ new_host->open();
}
}
}
@@ -1468,30 +1553,14 @@ void LLFloater::setCanResize(BOOL can_resize)
{
if (mResizable && !can_resize)
{
- removeChild(mResizeBar[0]);
- removeChild(mResizeBar[1]);
- removeChild(mResizeBar[2]);
- removeChild(mResizeBar[3]);
- removeChild(mResizeHandle[0]);
- removeChild(mResizeHandle[1]);
- removeChild(mResizeHandle[2]);
- removeChild(mResizeHandle[3]);
- delete mResizeBar[0];
- delete mResizeBar[1];
- delete mResizeBar[2];
- delete mResizeBar[3];
- delete mResizeHandle[0];
- delete mResizeHandle[1];
- delete mResizeHandle[2];
- mResizeHandle[3] = NULL;
- mResizeBar[0] = NULL;
- mResizeBar[1] = NULL;
- mResizeBar[2] = NULL;
- mResizeBar[3] = NULL;
- mResizeHandle[0] = NULL;
- mResizeHandle[1] = NULL;
- mResizeHandle[2] = NULL;
- mResizeHandle[3] = NULL;
+ for (S32 i = 0; i < 4; i++)
+ {
+ removeChild(mResizeBar[i], TRUE);
+ mResizeBar[i] = NULL;
+
+ removeChild(mResizeHandle[i], TRUE);
+ mResizeHandle[i] = NULL;
+ }
}
else if (!mResizable && can_resize)
{
@@ -1499,26 +1568,30 @@ void LLFloater::setCanResize(BOOL can_resize)
const S32 RESIZE_BAR_THICKNESS = 3;
mResizeBar[0] = new LLResizeBar(
"resizebar_left",
+ this,
LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0),
- mMinWidth, mMinHeight, LLResizeBar::LEFT );
+ mMinWidth, S32_MAX, LLResizeBar::LEFT );
addChild( mResizeBar[0] );
mResizeBar[1] = new LLResizeBar(
"resizebar_top",
+ this,
LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS),
- mMinWidth, mMinHeight, LLResizeBar::TOP );
+ mMinHeight, S32_MAX, LLResizeBar::TOP );
addChild( mResizeBar[1] );
mResizeBar[2] = new LLResizeBar(
"resizebar_right",
+ this,
LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
- mMinWidth, mMinHeight, LLResizeBar::RIGHT );
+ mMinWidth, S32_MAX, LLResizeBar::RIGHT );
addChild( mResizeBar[2] );
mResizeBar[3] = new LLResizeBar(
"resizebar_bottom",
+ this,
LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0),
- mMinWidth, mMinHeight, LLResizeBar::BOTTOM );
+ mMinHeight, S32_MAX, LLResizeBar::BOTTOM );
addChild( mResizeBar[3] );
@@ -1855,7 +1928,7 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
sibling->getVisible() &&
expanded_base_rect.rectInRect(&sibling->getRect()))
{
- base_rect |= sibling->getRect();
+ base_rect.unionWith(sibling->getRect());
}
}
@@ -2550,18 +2623,22 @@ BOOL LLMultiFloater::closeAllFloaters()
return TRUE; //else all tabs were successfully closed...
}
-void LLMultiFloater::growToFit(LLFloater* floaterp, S32 width, S32 height)
+void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
{
- floater_data_map_t::iterator found_data_it;
- found_data_it = mFloaterDataMap.find(floaterp->getHandle());
- if (found_data_it != mFloaterDataMap.end())
+ S32 new_width = llmax(mRect.getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
+ S32 new_height = llmax(mRect.getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
+
+ if (isMinimized())
{
- // store new width and height with this floater so that it will keep its size when detached
- found_data_it->second.mWidth = width;
- found_data_it->second.mHeight = height;
+ mPreviousRect.setLeftTopAndSize(mPreviousRect.mLeft, mPreviousRect.mTop, new_width, new_height);
+ }
+ else
+ {
+ S32 old_height = mRect.getHeight();
+ reshape(new_width, new_height);
+ // keep top left corner in same position
+ translate(0, old_height - new_height);
}
-
- resizeToContents();
}
/**
@@ -2618,12 +2695,18 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
floaterp->setCanMinimize(FALSE);
floaterp->setCanResize(FALSE);
floaterp->setCanDrag(FALSE);
+ floaterp->storeRectControl();
+
+ if (mAutoResize)
+ {
+ growToFit(floater_data.mWidth, floater_data.mHeight);
+ }
//add the panel, add it to proper maps
- mTabContainer->addTabPanel(floaterp, floaterp->getTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
+ mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
mFloaterDataMap[floaterp->getHandle()] = floater_data;
- resizeToContents();
+ updateResizeLimits();
if ( select_added_floater )
{
@@ -2673,7 +2756,6 @@ void LLMultiFloater::showFloater(LLFloater* floaterp)
{
addFloater(floaterp, TRUE);
}
- setVisibleAndFrontmost();
}
void LLMultiFloater::removeFloater(LLFloater* floaterp)
@@ -2696,9 +2778,11 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp)
}
mTabContainer->removeTabPanel(floaterp);
floaterp->setBackgroundVisible(TRUE);
+ floaterp->setCanDrag(TRUE);
floaterp->setHost(NULL);
+ floaterp->applyRectControl();
- resizeToContents();
+ updateResizeLimits();
tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
}
@@ -2840,18 +2924,8 @@ BOOL LLMultiFloater::postBuild()
return FALSE;
}
-void LLMultiFloater::resizeToContents()
+void LLMultiFloater::updateResizeLimits()
{
- // we're already in the middle of a reshape, don't interrupt it
- floater_data_map_t::iterator floater_it;
- S32 new_width = 0;
- S32 new_height = 0;
- for (floater_it = mFloaterDataMap.begin(); floater_it != mFloaterDataMap.end(); ++floater_it)
- {
- new_width = llmax(new_width, floater_it->second.mWidth + LLPANEL_BORDER_WIDTH * 2);
- new_height = llmax(new_height, floater_it->second.mHeight + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
- }
-
S32 new_min_width = 0;
S32 new_min_height = 0;
S32 tab_idx;
@@ -2867,21 +2941,23 @@ void LLMultiFloater::resizeToContents()
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = mRect.getHeight();
+ S32 new_width = llmax(mRect.getWidth(), new_min_width);
+ S32 new_height = llmax(mRect.getHeight(), new_min_height);
- if (mAutoResize)
+ if (isMinimized())
{
- reshape(new_width, new_height);
+ mPreviousRect.setLeftTopAndSize(mPreviousRect.mLeft, mPreviousRect.mTop, llmax(mPreviousRect.getWidth(), new_width), llmax(mPreviousRect.getHeight(), new_height));
}
else
{
- reshape(llmax(new_min_width, mRect.getWidth()), llmax(new_min_height, mRect.getHeight()));
- }
+ reshape(new_width, new_height);
- // make sure upper left corner doesn't move
- translate(0, cur_height - mRect.getHeight());
+ // make sure upper left corner doesn't move
+ translate(0, cur_height - mRect.getHeight());
- // Try to keep whole view onscreen, don't allow partial offscreen.
- gFloaterView->adjustToFitScreen(this, FALSE);
+ // Try to keep whole view onscreen, don't allow partial offscreen.
+ gFloaterView->adjustToFitScreen(this, FALSE);
+ }
}
// virtual
@@ -2937,6 +3013,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
{
LLString name(getName());
LLString title(getTitle());
+ LLString short_title(getShortTitle());
LLString rect_control("");
BOOL resizable = isResizable();
S32 min_width = getMinWidth();
@@ -2948,6 +3025,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
node->getAttributeString("name", name);
node->getAttributeString("title", title);
+ node->getAttributeString("short_title", short_title);
node->getAttributeString("rect_control", rect_control);
node->getAttributeBOOL("can_resize", resizable);
node->getAttributeBOOL("can_minimize", minimizable);
@@ -2974,6 +3052,8 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
minimizable,
close_btn);
+ setShortTitle(short_title);
+
BOOL can_tear_off;
if (node->getAttributeBOOL("can_tear_off", can_tear_off))
{
@@ -2988,17 +3068,13 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
LLFloater::setFloaterHost((LLMultiFloater*) this);
}
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- factory->createWidget(this, child);
- }
+ initChildrenXML(node, factory);
+
if (node->hasName("multi_floater"))
{
LLFloater::setFloaterHost(last_host);
}
-
BOOL result = postBuild();
if (!result)
@@ -3011,4 +3087,6 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
{
this->open(); /* Flawfinder: ignore */
}
+
+ moveResizeHandlesToFront();
}
diff --git a/linden/indra/llui/llfloater.h b/linden/indra/llui/llfloater.h
index 8b610e3..baa192a 100644
--- a/linden/indra/llui/llfloater.h
+++ b/linden/indra/llui/llfloater.h
@@ -143,8 +143,10 @@ public:
void setTitle( const LLString& title );
const LLString& getTitle() const;
+ void setShortTitle( const LLString& short_title );
+ LLString getShortTitle();
virtual void setMinimized(BOOL b);
- void moveResizeHandleToFront();
+ void moveResizeHandlesToFront();
void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE);
void addDependentFloater(LLViewHandle dependent_handle, BOOL reposition = TRUE);
LLFloater* getDependee() { return (LLFloater*)LLFloater::getFloaterByHandle(mDependeeHandle); }
@@ -242,6 +244,7 @@ protected:
LLRect mPreviousRect;
BOOL mForeground;
LLViewHandle mDependeeHandle;
+ LLString mShortTitle;
BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible.
@@ -281,6 +284,10 @@ protected:
static handle_map_t sFloaterMap;
std::vector mMinimizedHiddenChildren;
+
+ BOOL mHasBeenDraggedWhileMinimized;
+ S32 mPreviousMinimizedBottom;
+ S32 mPreviousMinimizedLeft;
};
/////////////////////////////////////////////////////////////
@@ -367,12 +374,11 @@ public:
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
-
/*virtual*/ EWidgetType getWidgetType() const;
/*virtual*/ LLString getWidgetTag() const;
virtual void setCanResize(BOOL can_resize);
- virtual void growToFit(LLFloater* floaterp, S32 width, S32 height);
+ virtual void growToFit(S32 content_width, S32 content_height);
virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainerCommon::eInsertionPoint insertion_point = LLTabContainerCommon::END);
virtual void showFloater(LLFloater* floaterp);
@@ -394,7 +400,7 @@ public:
void setTabContainer(LLTabContainerCommon* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
static void onTabSelected(void* userdata, bool);
- virtual void resizeToContents();
+ virtual void updateResizeLimits();
protected:
struct LLFloaterData
diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp
index f79164e..f9f3350 100644
--- a/linden/indra/llui/llfocusmgr.cpp
+++ b/linden/indra/llui/llfocusmgr.cpp
@@ -152,8 +152,7 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu
if (lock)
{
- mLockedView = mKeyboardFocus;
- mKeyboardLockedFocusLostCallback = on_focus_lost;
+ lockFocus();
}
}
@@ -312,6 +311,12 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( LLUICtrl* top_view )
}
}
+void LLFocusMgr::lockFocus()
+{
+ mLockedView = mKeyboardFocus;
+ mKeyboardLockedFocusLostCallback = mKeyboardFocusLostCallback;
+}
+
void LLFocusMgr::unlockFocus()
{
mLockedView = NULL;
diff --git a/linden/indra/llui/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h
index e189945..9b7a84e 100644
--- a/linden/indra/llui/llfocusmgr.h
+++ b/linden/indra/llui/llfocusmgr.h
@@ -81,6 +81,7 @@ public:
// All Three
void releaseFocusIfNeeded( LLView* top_view );
+ void lockFocus();
void unlockFocus();
BOOL focusLocked() { return mLockedView != NULL; }
diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h
index e715737..5ff2de7 100644
--- a/linden/indra/llui/lllineeditor.h
+++ b/linden/indra/llui/lllineeditor.h
@@ -127,6 +127,7 @@ public:
virtual void setRect(const LLRect& rect);
virtual BOOL acceptsTextInput() const;
virtual void onCommit();
+ virtual BOOL isDirty() { return ( mText.getString() != mPrevText ); }; // Returns TRUE if the user has changed value at all
// assumes UTF8 text
virtual void setValue(const LLSD& value );
diff --git a/linden/indra/llui/llmenugl.cpp b/linden/indra/llui/llmenugl.cpp
index 9530f26..b0d2d9f 100644
--- a/linden/indra/llui/llmenugl.cpp
+++ b/linden/indra/llui/llmenugl.cpp
@@ -172,6 +172,14 @@ LLXMLNodePtr LLMenuItemGL::getXML(bool save_children) const
out << LLKeyboard::stringFromKey(mAcceleratorKey);
node->createChild("shortcut", TRUE)->setStringValue(out.str());
+
+#ifdef LL_DARWIN
+ // Write in special tag if this key is really a ctrl combination on the Mac
+ if (mAcceleratorMask & MASK_MAC_CONTROL)
+ {
+ node->createChild("useMacCtrl", TRUE)->setBoolValue( TRUE );
+ }
+#endif // LL_DARWIN
}
return node;
@@ -204,7 +212,7 @@ BOOL LLMenuItemGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
- if( mEnabled && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == mAcceleratorMask) )
+ if( mEnabled && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
{
doIt();
return TRUE;
@@ -236,7 +244,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp)
for (list_it = listp->begin(); list_it != listp->end(); ++list_it)
{
accelerator = *list_it;
- if ((accelerator->mKey == mAcceleratorKey) && (accelerator->mMask == mAcceleratorMask))
+ if ((accelerator->mKey == mAcceleratorKey) && (accelerator->mMask == (mAcceleratorMask & MASK_NORMALKEYS)))
{
// *NOTE: get calling code to throw up warning or route
@@ -260,7 +268,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list *listp)
if (accelerator)
{
accelerator->mKey = mAcceleratorKey;
- accelerator->mMask = mAcceleratorMask;
+ accelerator->mMask = (mAcceleratorMask & MASK_NORMALKEYS);
// accelerator->mName = mLabel;
}
listp->push_back(accelerator);//addData(accelerator);
@@ -284,7 +292,16 @@ void LLMenuItemGL::appendAcceleratorString( LLString& st )
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if( mAcceleratorMask & MASK_CONTROL )
- st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98"
+ {
+ if ( mAcceleratorMask & MASK_MAC_CONTROL )
+ {
+ st.append( "Ctrl-" );
+ }
+ else
+ {
+ st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98"
+ }
+ }
if( mAcceleratorMask & MASK_ALT )
st.append( "Opt-" ); // Symbol would be "\xE2\x8C\xA5"
if( mAcceleratorMask & MASK_SHIFT )
@@ -299,7 +316,7 @@ void LLMenuItemGL::appendAcceleratorString( LLString& st )
#endif
LLString keystr = LLKeyboard::stringFromKey( mAcceleratorKey );
- if ((mAcceleratorMask & (MASK_CONTROL|MASK_ALT|MASK_SHIFT)) &&
+ if ((mAcceleratorMask & MASK_NORMALKEYS) &&
(keystr[0] == '-' || keystr[0] == '='))
{
st.append( " " );
@@ -998,7 +1015,7 @@ void LLMenuItemCallGL::buildDrawLabel( void )
BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask )
{
- if( (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == mAcceleratorMask) )
+ if( (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
{
LLPointer fired_event = new LLEvent(this);
fireEvent(fired_event, "on_build");
@@ -1394,9 +1411,9 @@ void LLMenuItemBranchGL::updateBranchParent(LLView* parentp)
}
}
-void LLMenuItemBranchGL::onVisibilityChange( BOOL curVisibilityIn )
+void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility )
{
- if (curVisibilityIn == FALSE && mBranch->getVisible() && !mBranch->getTornOff())
+ if (new_visibility == FALSE && !mBranch->getTornOff())
{
mBranch->setVisible(FALSE);
}
@@ -1965,10 +1982,23 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
child->hasName(LL_MENU_ITEM_CHECK_GL_TAG))
{
MASK mask = 0;
+
+#ifdef LL_DARWIN
+ // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd
+ BOOL useMacCtrl = FALSE;
+ child->getAttributeBOOL("useMacCtrl", useMacCtrl);
+#endif // LL_DARWIN
+
LLString shortcut;
child->getAttributeString("shortcut", shortcut);
if (shortcut.find("control") != shortcut.npos)
{
+#ifdef LL_DARWIN
+ if ( useMacCtrl )
+ {
+ mask |= MASK_MAC_CONTROL;
+ }
+#endif // LL_DARWIN
mask |= MASK_CONTROL;
}
if (shortcut.find("alt") != shortcut.npos)
@@ -2935,6 +2965,12 @@ BOOL LLMenuGL::handleKey( KEY key, MASK mask, BOOL called_from_parent )
BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)
{
+ // don't handle if not enabled
+ if(!mEnabled)
+ {
+ return FALSE;
+ }
+
// Pass down even if not visible
item_list_t::iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp
index dfa3f8a..91a327b 100644
--- a/linden/indra/llui/llpanel.cpp
+++ b/linden/indra/llui/llpanel.cpp
@@ -51,9 +51,18 @@
#include "llviewborder.h"
#include "llbutton.h"
+// LLLayoutStack
+#include "llgl.h"
+#include "llglheaders.h"
+#include "llresizebar.h"
+#include "llcriticaldamp.h"
+
LLPanel::panel_map_t LLPanel::sPanelMap;
LLPanel::alert_queue_t LLPanel::sAlertQueue;
+const S32 RESIZE_BAR_OVERLAP = 1;
+const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT;
+
void LLPanel::init()
{
// mRectControl
@@ -119,13 +128,16 @@ void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
addChild( mBorder );
}
+void LLPanel::removeBorder()
+{
+ delete mBorder;
+ mBorder = NULL;
+}
+
LLPanel::~LLPanel()
{
- if( !mRectControl.empty() )
- {
- LLUI::sConfigGroup->setRect( mRectControl, mRect );
- }
+ storeRectControl();
sPanelMap.erase(mViewHandle);
}
@@ -179,44 +191,41 @@ void LLPanel::setCtrlsEnabled( BOOL b )
void LLPanel::draw()
{
- if( getVisible() )
+ // draw background
+ if( mBgVisible )
{
- // draw background
- if( mBgVisible )
- {
- //RN: I don't see the point of this
- S32 left = 0;//LLPANEL_BORDER_WIDTH;
- S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
- S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
- S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
+ //RN: I don't see the point of this
+ S32 left = 0;//LLPANEL_BORDER_WIDTH;
+ S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
+ S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
+ S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
- if (mBgOpaque )
- {
- gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
- }
- else
- {
- gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
- }
+ if (mBgOpaque )
+ {
+ gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
}
-
- if( mDefaultBtn)
+ else
{
- if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
- {
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast(focus_ctrl)->getCommitOnReturn();
- // only enable default button when current focus is not a return-capturing button
- mDefaultBtn->setBorderEnabled(!focus_is_child_button);
- }
- else
- {
- mDefaultBtn->setBorderEnabled(FALSE);
- }
+ gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
}
+ }
- LLView::draw();
+ if( mDefaultBtn)
+ {
+ if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
+ {
+ LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
+ BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast(focus_ctrl)->getCommitOnReturn();
+ // only enable default button when current focus is not a return-capturing button
+ mDefaultBtn->setBorderEnabled(!focus_is_child_button);
+ }
+ else
+ {
+ mDefaultBtn->setBorderEnabled(FALSE);
+ }
}
+
+ LLView::draw();
}
void LLPanel::refresh()
@@ -572,7 +581,7 @@ LLXMLNodePtr LLPanel::getXML(bool save_children) const
return node;
}
-LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *factory)
+LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory)
{
LLString name("panel");
node->getAttributeString("name", name);
@@ -581,11 +590,21 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *fa
// Fall back on a default panel, if there was no special factory.
if (!panelp)
{
- panelp = new LLPanel("tab panel");
+ LLRect rect;
+ createRect(node, rect, parent, LLRect());
+ panelp = new LLPanel(name, rect);
+ panelp->initPanelXML(node, parent, factory);
+ // preserve panel's width and height, but override the location
+ const LLRect& panelrect = panelp->getRect();
+ S32 w = panelrect.getWidth();
+ S32 h = panelrect.getHeight();
+ rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
+ panelp->setRect(rect);
+ }
+ else
+ {
+ panelp->initPanelXML(node, parent, factory);
}
-
- panelp->initPanelXML(node, parentp, factory);
-
return panelp;
}
@@ -597,11 +616,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
setPanelParameters(node, parent);
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- factory->createWidget(this, child);
- }
+ initChildrenXML(node, factory);
LLString xml_filename;
node->getAttributeString("filename", xml_filename);
@@ -610,8 +625,16 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
if (!xml_filename.empty())
{
+ // Preserve postion of embedded panel but allow panel to dictate width/height
+ LLRect rect(getRect());
didPost = factory->buildPanel(this, xml_filename, NULL);
- } else {
+ S32 w = getRect().getWidth();
+ S32 h = getRect().getHeight();
+ rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
+ setRect(rect);
+ }
+ else
+ {
didPost = FALSE;
}
@@ -624,10 +647,32 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
return didPost;
}
-void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
+void LLPanel::initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory)
+{
+ LLXMLNodePtr child;
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ // look for string declarations for programmatic text
+ if (child->hasName("string"))
+ {
+ LLString string_name;
+ child->getAttributeString("name", string_name);
+ if (!string_name.empty())
+ {
+ mUIStrings[string_name] = LLUIString(child->getTextContents());
+ }
+ }
+ else
+ {
+ factory->createWidget(this, child);
+ }
+ }
+}
+
+void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
{
/////// Rect, follows, tool_tip, enabled, visible attributes ///////
- initFromXML(node, parentp);
+ initFromXML(node, parent);
/////// Border attributes ///////
BOOL border = FALSE;
@@ -652,6 +697,10 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
addBorder(bevel_style, border_style, border_thickness);
}
+ else
+ {
+ removeBorder();
+ }
/////// Background attributes ///////
BOOL background_visible = FALSE;
@@ -676,6 +725,30 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
setLabel(label);
}
+LLString LLPanel::getFormattedUIString(const LLString& name, const LLString::format_map_t& args) const
+{
+ ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
+ if (found_it != mUIStrings.end())
+ {
+ // make a copy as format works in place
+ LLUIString formatted_string = found_it->second;
+ formatted_string.setArgList(args);
+ return formatted_string.getString();
+ }
+ return LLString::null;
+}
+
+LLUIString LLPanel::getUIString(const LLString& name) const
+{
+ ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
+ if (found_it != mUIStrings.end())
+ {
+ return found_it->second;
+ }
+ return LLUIString(LLString::null);
+}
+
+
void LLPanel::childSetVisible(const LLString& id, bool visible)
{
LLView* child = getChildByName(id, true);
@@ -1065,3 +1138,493 @@ void LLPanel::childDisplayNotFound()
LLAlertDialog::showXml("FloaterNotFound", args);
}
+void LLPanel::storeRectControl()
+{
+ if( !mRectControl.empty() )
+ {
+ LLUI::sConfigGroup->setRect( mRectControl, mRect );
+ }
+}
+
+
+//
+// LLLayoutStack
+//
+struct LLLayoutStack::LLEmbeddedPanel
+{
+ LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize) :
+ mPanel(panelp),
+ mMinWidth(min_width),
+ mMinHeight(min_height),
+ mAutoResize(auto_resize),
+ mOrientation(orientation),
+ mVisibleAmt(1.f) // default to fully visible
+ {
+ LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
+ LLRect resize_bar_rect = panelp->getRect();
+
+ S32 min_dim;
+ if (orientation == HORIZONTAL)
+ {
+ min_dim = mMinHeight;
+ }
+ else
+ {
+ min_dim = mMinWidth;
+ }
+ mResizeBar = new LLResizeBar("resizer", mPanel, LLRect(), min_dim, S32_MAX, side);
+ mResizeBar->setEnableSnapping(FALSE);
+ // panels initialized as hidden should not start out partially visible
+ if (!mPanel->getVisible())
+ {
+ mVisibleAmt = 0.f;
+ }
+ }
+
+ LLPanel* mPanel;
+ S32 mMinWidth;
+ S32 mMinHeight;
+ BOOL mAutoResize;
+ LLResizeBar* mResizeBar;
+ eLayoutOrientation mOrientation;
+ F32 mVisibleAmt;
+};
+
+LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
+ mOrientation(orientation),
+ mMinWidth(0),
+ mMinHeight(0)
+{
+}
+
+LLLayoutStack::~LLLayoutStack()
+{
+}
+
+void LLLayoutStack::draw()
+{
+ updateLayout();
+ {
+ // clip if outside nominal bounds
+ LLLocalClipRect clip(getLocalRect(), mRect.getWidth() > mMinWidth || mRect.getHeight() > mMinHeight);
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLRect clip_rect = (*panel_it)->mPanel->getRect();
+ // scale clipping rectangle by visible amount
+ if (mOrientation == HORIZONTAL)
+ {
+ clip_rect.mRight = clip_rect.mLeft + llround(clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
+ }
+ else
+ {
+ clip_rect.mBottom = clip_rect.mTop - llround(clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
+ }
+ LLLocalClipRect clip(clip_rect, (*panel_it)->mVisibleAmt < 1.f);
+ // only force drawing invisible children if visible amount is non-zero
+ drawChild((*panel_it)->mPanel, 0, 0, (*panel_it)->mVisibleAmt > 0.f);
+ }
+ }
+}
+
+void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
+{
+ LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel((LLPanel*)ctrl);
+
+ if (embedded_panelp)
+ {
+ mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
+ delete embedded_panelp;
+ }
+
+ calcMinExtents();
+
+ LLView::removeCtrl(ctrl);
+}
+
+void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLView::reshape(width, height, called_from_parent);
+ //updateLayout();
+}
+
+LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
+{
+ LLXMLNodePtr node = LLView::getXML();
+ return node;
+}
+
+//static
+LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+{
+ LLString orientation_string("vertical");
+ node->getAttributeString("orientation", orientation_string);
+
+ eLayoutOrientation orientation = VERTICAL;
+
+ if (orientation_string == "horizontal")
+ {
+ orientation = HORIZONTAL;
+ }
+ else if (orientation_string == "vertical")
+ {
+ orientation = VERTICAL;
+ }
+ else
+ {
+ llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
+ }
+
+ LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
+
+ layout_stackp->initFromXML(node, parent);
+
+ LLXMLNodePtr child;
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ if (child->hasName("layout_panel"))
+ {
+ S32 min_width = 0;
+ S32 min_height = 0;
+ BOOL auto_resize = TRUE;
+
+ child->getAttributeS32("min_width", min_width);
+ child->getAttributeS32("min_height", min_height);
+ child->getAttributeBOOL("auto_resize", auto_resize);
+
+ LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
+ panelp->setFollowsNone();
+ if (panelp)
+ {
+ layout_stackp->addPanel(panelp, min_width, min_height, auto_resize);
+ }
+ }
+ }
+
+ return layout_stackp;
+}
+
+S32 LLLayoutStack::getMinWidth()
+{
+ return mMinWidth;
+}
+
+S32 LLLayoutStack::getMinHeight()
+{
+ return mMinHeight;
+}
+
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index)
+{
+ LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize);
+
+ mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
+ addChild(panel);
+ addChild(embedded_panel->mResizeBar);
+
+ // bring all resize bars to the front so that they are clickable even over the panels
+ // with a bit of overlap
+ for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ e_panel_list_t::iterator next_it = panel_it;
+ ++next_it;
+
+ LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
+ sendChildToFront(resize_barp);
+ // last resize bar is disabled, since its not between any two panels
+ if ( next_it == mPanels.end() )
+ {
+ resize_barp->setEnabled(FALSE);
+ }
+ else
+ {
+ resize_barp->setEnabled(TRUE);
+ }
+ }
+
+ //updateLayout();
+}
+
+void LLLayoutStack::removePanel(LLPanel* panel)
+{
+ removeChild(panel);
+ //updateLayout();
+}
+
+void LLLayoutStack::updateLayout(BOOL force_resize)
+{
+ calcMinExtents();
+
+ // calculate current extents
+ S32 cur_width = 0;
+ S32 cur_height = 0;
+
+ const F32 ANIM_OPEN_TIME = 0.02f;
+ const F32 ANIM_CLOSE_TIME = 0.02f;
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+ if (panelp->getVisible())
+ {
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
+ if ((*panel_it)->mVisibleAmt > 0.99f)
+ {
+ (*panel_it)->mVisibleAmt = 1.f;
+ }
+ }
+ else // not visible
+ {
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ if ((*panel_it)->mVisibleAmt < 0.001f)
+ {
+ (*panel_it)->mVisibleAmt = 0.f;
+ }
+ }
+ if (mOrientation == HORIZONTAL)
+ {
+ // all panels get expanded to max of all the minimum dimensions
+ cur_height = llmax(mMinHeight, panelp->getRect().getHeight());
+ cur_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
+ if (panel_it != mPanels.end())
+ {
+ cur_width += PANEL_STACK_GAP;
+ }
+ }
+ else //VERTICAL
+ {
+ cur_width = llmax(mMinWidth, panelp->getRect().getWidth());
+ cur_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
+ if (panel_it != mPanels.end())
+ {
+ cur_height += PANEL_STACK_GAP;
+ }
+ }
+ }
+
+ S32 num_resizable_panels = 0;
+ S32 shrink_headroom_available = 0;
+ S32 shrink_headroom_total = 0;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ // panels that are not fully visible do not count towards shrink headroom
+ if ((*panel_it)->mVisibleAmt < 1.f)
+ continue;
+ // if currently resizing a panel or the panel is flagged as not automatically resizing
+ // only track total available headroom, but don't use it for automatic resize logic
+ if ((*panel_it)->mResizeBar->hasMouseCapture() || (!(*panel_it)->mAutoResize && !force_resize))
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ }
+ else //VERTICAL
+ {
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ }
+ }
+ else
+ {
+ num_resizable_panels++;
+ if (mOrientation == HORIZONTAL)
+ {
+ shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ }
+ else //VERTICAL
+ {
+ shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ }
+ }
+ }
+
+ // positive means panels need to grow, negative means shrink
+ S32 pixels_to_distribute;
+ if (mOrientation == HORIZONTAL)
+ {
+ pixels_to_distribute = mRect.getWidth() - cur_width;
+ }
+ else //VERTICAL
+ {
+ pixels_to_distribute = mRect.getHeight() - cur_height;
+ }
+
+ S32 cur_x = 0;
+ S32 cur_y = mRect.getHeight();
+
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ S32 cur_width = panelp->getRect().getWidth();
+ S32 cur_height = panelp->getRect().getHeight();
+ S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
+ S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
+
+ S32 delta_size = 0;
+
+ // if panel can automatically resize (not animating, and resize flag set)...
+ if ((*panel_it)->mVisibleAmt == 1.f && (force_resize || (*panel_it)->mAutoResize) && !(*panel_it)->mResizeBar->hasMouseCapture())
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ // if we're shrinking
+ if (pixels_to_distribute < 0)
+ {
+ // shrink proportionally to amount over minimum
+ delta_size = llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available);
+ }
+ else
+ {
+ // grow all elements equally
+ delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
+ }
+ new_width = llmax((*panel_it)->mMinWidth, panelp->getRect().getWidth() + delta_size);
+ }
+ else
+ {
+ new_width = llmax(mMinWidth, mRect.getWidth());
+ }
+
+ if (mOrientation == VERTICAL)
+ {
+ if (pixels_to_distribute < 0)
+ {
+ // shrink proportionally to amount over minimum
+ delta_size = llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available);
+ }
+ else
+ {
+ delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
+ }
+ new_height = llmax((*panel_it)->mMinHeight, panelp->getRect().getHeight() + delta_size);
+ }
+ else
+ {
+ new_height = llmax(mMinHeight, mRect.getHeight());
+ }
+ }
+ else // don't resize
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ new_height = llmax(mMinHeight, mRect.getHeight());
+ }
+ else // VERTICAL
+ {
+ new_width = llmax(mMinWidth, mRect.getWidth());
+ }
+ }
+
+ // adjust running headroom count based on new sizes
+ shrink_headroom_total += delta_size;
+
+ panelp->reshape(new_width, new_height);
+ panelp->setOrigin(cur_x, cur_y - new_height);
+
+ LLRect panel_rect = panelp->getRect();
+ LLRect resize_bar_rect = panel_rect;
+ if (mOrientation == HORIZONTAL)
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
+ resize_bar_rect.mRight = panel_rect.mRight + PANEL_STACK_GAP + RESIZE_BAR_OVERLAP;
+ }
+ else
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
+ resize_bar_rect.mBottom = panel_rect.mBottom - PANEL_STACK_GAP - RESIZE_BAR_OVERLAP;
+ }
+ (*panel_it)->mResizeBar->setRect(resize_bar_rect);
+
+ if (mOrientation == HORIZONTAL)
+ {
+ cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
+ }
+ else //VERTICAL
+ {
+ cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
+ }
+ }
+
+ // update resize bars with new limits
+ LLResizeBar* last_resize_bar = NULL;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ if (mOrientation == HORIZONTAL)
+ {
+ (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinWidth, (*panel_it)->mMinWidth + shrink_headroom_total);
+ }
+ else //VERTICAL
+ {
+ (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinHeight, (*panel_it)->mMinHeight + shrink_headroom_total);
+ }
+ // hide resize bars for invisible panels
+ (*panel_it)->mResizeBar->setVisible(panelp->getVisible());
+ if (panelp->getVisible())
+ {
+ last_resize_bar = (*panel_it)->mResizeBar;
+ }
+ }
+
+ // hide last resize bar as there is nothing past it
+ if (last_resize_bar)
+ {
+ last_resize_bar->setVisible(FALSE);
+ }
+
+ // not enough room to fit existing contents
+ if (!force_resize &&
+ ((cur_y != -PANEL_STACK_GAP) || (cur_x != mRect.getWidth() + PANEL_STACK_GAP)))
+ {
+ // do another layout pass with all stacked elements contributing
+ // even those that don't usually resize
+ llassert_always(force_resize == FALSE);
+ updateLayout(TRUE);
+ }
+}
+
+LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp)
+{
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ if ((*panel_it)->mPanel == panelp)
+ {
+ return *panel_it;
+ }
+ }
+ return NULL;
+}
+
+void LLLayoutStack::calcMinExtents()
+{
+ mMinWidth = 0;
+ mMinHeight = 0;
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ mMinHeight = llmax(mMinHeight, (*panel_it)->mMinHeight);
+ mMinWidth += (*panel_it)->mMinWidth;
+ if (panel_it != mPanels.begin())
+ {
+ mMinWidth += PANEL_STACK_GAP;
+ }
+ }
+ else //VERTICAL
+ {
+ mMinWidth = llmax(mMinWidth, (*panel_it)->mMinWidth);
+ mMinHeight += (*panel_it)->mMinHeight;
+ if (panel_it != mPanels.begin())
+ {
+ mMinHeight += PANEL_STACK_GAP;
+ }
+ }
+ }
+}
diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h
index fea3eee..28c56fa 100644
--- a/linden/indra/llui/llpanel.h
+++ b/linden/indra/llui/llpanel.h
@@ -35,6 +35,7 @@
#include "llcallbackmap.h"
#include "lluictrl.h"
#include "llviewborder.h"
+#include "lluistring.h"
#include "v4color.h"
#include
#include
@@ -91,6 +92,8 @@ public:
LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE,
S32 border_thickness = LLPANEL_BORDER_WIDTH );
+ void removeBorder();
+
virtual ~LLPanel();
virtual void draw();
virtual void refresh(); // called in setFocus()
@@ -117,6 +120,7 @@ public:
LLString getLabel() const { return mLabel; }
void setRectControl(const LLString& rect_control) { mRectControl.assign(rect_control); }
+ void storeRectControl();
void setBorderVisible( BOOL b );
@@ -136,8 +140,12 @@ public:
virtual LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory);
void setPanelParameters(LLXMLNodePtr node, LLView *parentp);
+ LLString getFormattedUIString(const LLString& name, const LLString::format_map_t& args = LLUIString::sNullArgs) const;
+ LLUIString getUIString(const LLString& name) const;
+
// ** Wrappers for setting child properties by name ** -TomY
// Override to set not found list
@@ -216,6 +224,8 @@ public:
typedef std::queue alert_queue_t;
static alert_queue_t sAlertQueue;
+ typedef std::map ui_string_map_t;
+
private:
// common constructor
void init();
@@ -241,6 +251,8 @@ protected:
LLString mLabel;
S32 mLastTabGroup;
+ ui_string_map_t mUIStrings;
+
typedef std::map requirements_map_t;
requirements_map_t mRequirements;
@@ -248,4 +260,50 @@ protected:
static panel_map_t sPanelMap;
};
+class LLLayoutStack : public LLView
+{
+public:
+ typedef enum e_layout_orientation
+ {
+ HORIZONTAL,
+ VERTICAL
+ } eLayoutOrientation;
+
+ LLLayoutStack(eLayoutOrientation orientation);
+ virtual ~LLLayoutStack();
+
+ /*virtual*/ void draw();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+ /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
+ /*virtual*/ void removeCtrl(LLUICtrl* ctrl);
+ virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LAYOUT_STACK; }
+ virtual LLString getWidgetTag() const { return LL_LAYOUT_STACK_TAG; }
+
+ static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+
+ S32 getMinWidth();
+ S32 getMinHeight();
+
+ void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index = S32_MAX);
+ void removePanel(LLPanel* panel);
+ void updateLayout(BOOL force_resize = FALSE);
+
+protected:
+ struct LLEmbeddedPanel;
+
+ LLEmbeddedPanel* findEmbeddedPanel(LLPanel* panelp);
+ void calcMinExtents();
+ S32 getMinStackSize();
+ S32 getCurStackSize();
+
+protected:
+ eLayoutOrientation mOrientation;
+
+ typedef std::vector e_panel_list_t;
+ e_panel_list_t mPanels;
+
+ S32 mMinWidth;
+ S32 mMinHeight;
+};
+
#endif
diff --git a/linden/indra/llui/llradiogroup.cpp b/linden/indra/llui/llradiogroup.cpp
index eda54b1..0104998 100644
--- a/linden/indra/llui/llradiogroup.cpp
+++ b/linden/indra/llui/llradiogroup.cpp
@@ -169,7 +169,7 @@ BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
// do any of the tab buttons have keyboard focus?
- if (getEnabled() && !called_from_parent)
+ if (getEnabled() && !called_from_parent && mask == MASK_NONE)
{
switch(key)
{
@@ -441,6 +441,69 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
return radio_group;
}
+// LLCtrlSelectionInterface functions
+BOOL LLRadioGroup::setCurrentByID( const LLUUID& id )
+{
+ return FALSE;
+}
+
+LLUUID LLRadioGroup::getCurrentID()
+{
+ return LLUUID::null;
+}
+
+BOOL LLRadioGroup::setSelectedByValue(LLSD value, BOOL selected)
+{
+ S32 idx = 0;
+ std::string value_string = value.asString();
+ for (button_list_t::const_iterator iter = mRadioButtons.begin();
+ iter != mRadioButtons.end(); ++iter)
+ {
+ if((*iter)->getName() == value_string)
+ {
+ setSelectedIndex(idx);
+ return TRUE;
+ }
+ idx++;
+ }
+
+ return FALSE;
+}
+
+LLSD LLRadioGroup::getSimpleSelectedValue()
+{
+ return getValue();
+}
+
+BOOL LLRadioGroup::isSelected(LLSD value)
+{
+ S32 idx = 0;
+ std::string value_string = value.asString();
+ for (button_list_t::const_iterator iter = mRadioButtons.begin();
+ iter != mRadioButtons.end(); ++iter)
+ {
+ if((*iter)->getName() == value_string)
+ {
+ if (idx == mSelectedIndex)
+ {
+ return TRUE;
+ }
+ }
+ idx++;
+ }
+ return FALSE;
+}
+
+BOOL LLRadioGroup::operateOnSelection(EOperation op)
+{
+ return FALSE;
+}
+
+BOOL LLRadioGroup::operateOnAll(EOperation op)
+{
+ return FALSE;
+}
+
LLRadioCtrl::LLRadioCtrl(const LLString& name, const LLRect& rect, const LLString& label,
const LLFontGL* font, void (*commit_callback)(LLUICtrl*, void*), void* callback_userdata) :
@@ -458,3 +521,4 @@ void LLRadioCtrl::setValue(const LLSD& value)
LLCheckBoxCtrl::setValue(value);
mButton->setTabStop(value.asBoolean());
}
+
diff --git a/linden/indra/llui/llradiogroup.h b/linden/indra/llui/llradiogroup.h
index 0cd5901..3dec41d 100644
--- a/linden/indra/llui/llradiogroup.h
+++ b/linden/indra/llui/llradiogroup.h
@@ -35,6 +35,7 @@
#include "lluictrl.h"
#include "llcheckboxctrl.h"
+#include "llctrlselectioninterface.h"
class LLFontGL;
@@ -52,7 +53,7 @@ public:
};
class LLRadioGroup
-: public LLUICtrl
+: public LLUICtrl, public LLCtrlSelectionInterface
{
public:
// Build a radio group. The number (0...n-1) of the currently selected
@@ -83,7 +84,6 @@ public:
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void setIndexEnabled(S32 index, BOOL enabled);
- S32 getItemCount() { return mRadioButtons.size(); }
// return the index value of the selected item
S32 getSelectedIndex() const;
@@ -107,6 +107,23 @@ public:
// button.
static void onClickButton(LLUICtrl* radio, void* userdata);
+ //========================================================================
+ LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; };
+
+ // LLCtrlSelectionInterface functions
+ /*virtual*/ S32 getItemCount() const { return mRadioButtons.size(); }
+ /*virtual*/ BOOL getCanSelect() const { return TRUE; }
+ /*virtual*/ BOOL selectFirstItem() { return setSelectedIndex(0); }
+ /*virtual*/ BOOL selectNthItem( S32 index ) { return setSelectedIndex(index); }
+ /*virtual*/ S32 getFirstSelectedIndex() { return getSelectedIndex(); }
+ /*virtual*/ BOOL setCurrentByID( const LLUUID& id );
+ /*virtual*/ LLUUID getCurrentID(); // LLUUID::null if no items in menu
+ /*virtual*/ BOOL setSelectedByValue(LLSD value, BOOL selected);
+ /*virtual*/ LLSD getSimpleSelectedValue();
+ /*virtual*/ BOOL isSelected(LLSD value);
+ /*virtual*/ BOOL operateOnSelection(EOperation op);
+ /*virtual*/ BOOL operateOnAll(EOperation op);
+
protected:
// protected function shared by the two constructors.
void init(BOOL border);
diff --git a/linden/indra/llui/llresizebar.cpp b/linden/indra/llui/llresizebar.cpp
index 79127a8..f716e8e 100644
--- a/linden/indra/llui/llresizebar.cpp
+++ b/linden/indra/llui/llresizebar.cpp
@@ -38,16 +38,18 @@
#include "llfocusmgr.h"
#include "llwindow.h"
-LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side )
+LLResizeBar::LLResizeBar( const LLString& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side )
:
LLView( name, rect, TRUE ),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
mLastMouseScreenY( 0 ),
- mMinWidth( min_width ),
- mMinHeight( min_height ),
- mSide( side )
+ mMinSize( min_size ),
+ mMaxSize( max_size ),
+ mSide( side ),
+ mSnappingEnabled(TRUE),
+ mResizingView(resizing_view)
{
// set up some generically good follow code.
switch( side )
@@ -149,12 +151,11 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
// Make sure the mouse in still over the application. We don't want to make the parent
// so big that we can't see the resize handle any more.
LLRect valid_rect = getRootView()->getRect();
- LLView* resizing_view = getParent();
- if( valid_rect.localPointInRect( screen_x, screen_y ) && resizing_view )
+ if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )
{
// Resize the parent
- LLRect orig_rect = resizing_view->getRect();
+ LLRect orig_rect = mResizingView->getRect();
LLRect scaled_rect = orig_rect;
S32 new_width = orig_rect.getWidth();
@@ -163,76 +164,63 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
switch( mSide )
{
case LEFT:
- new_width = orig_rect.getWidth() - delta_x;
- if( new_width < mMinWidth )
- {
- new_width = mMinWidth;
- delta_x = orig_rect.getWidth() - mMinWidth;
- }
+ new_width = llclamp(orig_rect.getWidth() - delta_x, mMinSize, mMaxSize);
+ delta_x = orig_rect.getWidth() - new_width;
scaled_rect.translate(delta_x, 0);
break;
case TOP:
- new_height = orig_rect.getHeight() + delta_y;
- if( new_height < mMinHeight )
- {
- new_height = mMinHeight;
- delta_y = mMinHeight - orig_rect.getHeight();
- }
+ new_height = llclamp(orig_rect.getHeight() + delta_y, mMinSize, mMaxSize);
+ delta_y = new_height - orig_rect.getHeight();
break;
case RIGHT:
- new_width = orig_rect.getWidth() + delta_x;
- if( new_width < mMinWidth )
- {
- new_width = mMinWidth;
- delta_x = mMinWidth - orig_rect.getWidth();
- }
+ new_width = llclamp(orig_rect.getWidth() + delta_x, mMinSize, mMaxSize);
+ delta_x = new_width - orig_rect.getWidth();
break;
case BOTTOM:
- new_height = orig_rect.getHeight() - delta_y;
- if( new_height < mMinHeight )
- {
- new_height = mMinHeight;
- delta_y = orig_rect.getHeight() - mMinHeight;
- }
+ new_height = llclamp(orig_rect.getHeight() - delta_y, mMinSize, mMaxSize);
+ delta_y = orig_rect.getHeight() - new_height;
scaled_rect.translate(0, delta_y);
break;
}
scaled_rect.mTop = scaled_rect.mBottom + new_height;
scaled_rect.mRight = scaled_rect.mLeft + new_width;
- resizing_view->setRect(scaled_rect);
+ mResizingView->setRect(scaled_rect);
LLView* snap_view = NULL;
- switch( mSide )
+ if (mSnappingEnabled)
{
- case LEFT:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
- case TOP:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
- case RIGHT:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
- case BOTTOM:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
+ switch( mSide )
+ {
+ case LEFT:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ case TOP:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ case RIGHT:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ case BOTTOM:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ }
}
// register "snap" behavior with snapped view
- resizing_view->snappedTo(snap_view);
+ mResizingView->snappedTo(snap_view);
// restore original rectangle so the appropriate changes are detected
- resizing_view->setRect(orig_rect);
+ mResizingView->setRect(orig_rect);
// change view shape as user operation
- resizing_view->userSetShape(scaled_rect);
+ mResizingView->userSetShape(scaled_rect);
// update last valid mouse cursor position based on resized view's actual size
- LLRect new_rect = resizing_view->getRect();
+ LLRect new_rect = mResizingView->getRect();
switch(mSide)
{
case LEFT:
diff --git a/linden/indra/llui/llresizebar.h b/linden/indra/llui/llresizebar.h
index e1fc0f9..d3596ec 100644
--- a/linden/indra/llui/llresizebar.h
+++ b/linden/indra/llui/llresizebar.h
@@ -37,7 +37,7 @@ class LLResizeBar : public LLView
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM };
- LLResizeBar(const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side );
+ LLResizeBar(const LLString& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side );
virtual EWidgetType getWidgetType() const;
virtual LLString getWidgetTag() const;
@@ -47,7 +47,8 @@ public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; }
+ void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; }
+ void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; }
protected:
S32 mDragLastScreenX;
@@ -55,9 +56,11 @@ protected:
S32 mLastMouseScreenX;
S32 mLastMouseScreenY;
LLCoordGL mLastMouseDir;
- S32 mMinWidth;
- S32 mMinHeight;
+ S32 mMinSize;
+ S32 mMaxSize;
Side mSide;
+ BOOL mSnappingEnabled;
+ LLView* mResizingView;
};
const S32 RESIZE_BAR_HEIGHT = 3;
diff --git a/linden/indra/llui/llresmgr.cpp b/linden/indra/llui/llresmgr.cpp
index 2350093..5ed2cb3 100644
--- a/linden/indra/llui/llresmgr.cpp
+++ b/linden/indra/llui/llresmgr.cpp
@@ -440,6 +440,9 @@ const LLString LLLocale::SYSTEM_LOCALE("English_United States.1252");
#elif LL_DARWIN
const LLString LLLocale::USER_LOCALE("en_US.iso8859-1");// = LLString::null;
const LLString LLLocale::SYSTEM_LOCALE("en_US.iso8859-1");
+#elif LL_SOLARIS
+const LLString LLLocale::USER_LOCALE("en_US.ISO8859-1");
+const LLString LLLocale::SYSTEM_LOCALE("C");
#else // LL_LINUX likes this
const LLString LLLocale::USER_LOCALE("en_US.utf8");
const LLString LLLocale::SYSTEM_LOCALE("C");
diff --git a/linden/indra/llui/llscrollcontainer.cpp b/linden/indra/llui/llscrollcontainer.cpp
index be41aa8..b910964 100644
--- a/linden/indra/llui/llscrollcontainer.cpp
+++ b/linden/indra/llui/llscrollcontainer.cpp
@@ -505,8 +505,7 @@ void LLScrollableContainerView::draw()
BOOL show_h_scrollbar = FALSE;
calcVisibleSize( mScrolledView->getRect(), &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
- LLGLEnable scissor_test(GL_SCISSOR_TEST);
- LLUI::setScissorRegionLocal(LLRect(mInnerRect.mLeft,
+ LLLocalClipRect clip(LLRect(mInnerRect.mLeft,
mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0) + visible_height,
visible_width,
mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0)
diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp
index 5571d39..56a6a22 100644
--- a/linden/indra/llui/llscrolllistctrl.cpp
+++ b/linden/indra/llui/llscrolllistctrl.cpp
@@ -51,7 +51,7 @@
#include "llkeyboard.h"
#include "llresizebar.h"
-const S32 LIST_BORDER_PAD = 2; // white space inside the border and to the left of the scrollbar
+const S32 LIST_BORDER_PAD = 0; // white space inside the border and to the left of the scrollbar
const S32 MIN_COLUMN_WIDTH = 20;
const S32 LIST_SNAP_PADDING = 5;
@@ -417,6 +417,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mCommitOnKeyboardMovement(TRUE),
mCommitOnSelectionChange(FALSE),
mSelectionChanged(FALSE),
+ mNeedsScroll(FALSE),
mCanSelect(TRUE),
mDisplayColumnHeaders(FALSE),
mCollapseEmptyColumns(FALSE),
@@ -1439,14 +1440,16 @@ void LLScrollListCtrl::drawItems()
S32 x = mItemListRect.mLeft;
S32 y = mItemListRect.mTop - mLineHeight;
- S32 num_page_lines = mPageLines;
+ // allow for partial line at bottom
+ S32 num_page_lines = mPageLines + 1;
LLRect item_rect;
LLGLSUIDefault gls_ui;
{
-
+ LLLocalClipRect clip(mItemListRect);
+
S32 cur_x = x;
S32 cur_y = y;
@@ -1558,6 +1561,11 @@ void LLScrollListCtrl::draw()
{
if( getVisible() )
{
+ if (mNeedsScroll)
+ {
+ scrollToShowSelected();
+ mNeedsScroll = FALSE;
+ }
LLRect background(0, mRect.getHeight(), mRect.getWidth(), 0);
// Draw background
if (mBackgroundVisible)
@@ -1710,6 +1718,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
gFocusMgr.setMouseCapture(this);
selectItemAt(x, y, mask);
+ mNeedsScroll = TRUE;
}
return TRUE;
@@ -1719,17 +1728,16 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
{
if (hasMouseCapture())
{
+ // release mouse capture immediately so
+ // scroll to show selected logic will work
+ gFocusMgr.setMouseCapture(NULL);
if(mask == MASK_NONE)
{
selectItemAt(x, y, mask);
+ mNeedsScroll = TRUE;
}
}
- if (hasMouseCapture())
- {
- gFocusMgr.setMouseCapture(NULL);
- }
-
// always commit when mouse operation is completed inside list
if (mItemListRect.pointInRect(x,y))
{
@@ -1770,7 +1778,8 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
mItemListRect.getWidth(),
mLineHeight );
- int num_page_lines = mPageLines;
+ // allow for partial line at bottom
+ S32 num_page_lines = mPageLines + 1;
S32 line = 0;
item_list::iterator iter;
@@ -1803,6 +1812,7 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
if(mask == MASK_NONE)
{
selectItemAt(x, y, mask);
+ mNeedsScroll = TRUE;
}
}
else if (mCanSelect)
@@ -1850,7 +1860,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
{
// commit implicit in call
selectPrevItem(FALSE);
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
handled = TRUE;
}
break;
@@ -1859,7 +1869,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
{
// commit implicit in call
selectNextItem(FALSE);
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
handled = TRUE;
}
break;
@@ -1867,7 +1877,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectNthItem(getFirstSelectedIndex() - (mScrollbar->getPageSize() - 1));
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1880,7 +1890,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectNthItem(getFirstSelectedIndex() + (mScrollbar->getPageSize() - 1));
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1893,7 +1903,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectFirstItem();
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1906,7 +1916,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectNthItem(getItemCount() - 1);
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1945,6 +1955,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
}
else if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString), FALSE))
{
+ mNeedsScroll = TRUE;
// update search string only on successful match
mSearchTimer.reset();
@@ -1984,6 +1995,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE))
{
// update search string only on successful match
+ mNeedsScroll = TRUE;
mSearchString += uni_char;
mSearchTimer.reset();
@@ -2029,6 +2041,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
{
selectItem(item);
+ mNeedsScroll = TRUE;
cellp->highlightText(0, 1);
mSearchTimer.reset();
@@ -2050,8 +2063,6 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
}
}
- // make sure selected item is on screen
- scrollToShowSelected();
return TRUE;
}
@@ -2203,6 +2214,13 @@ void LLScrollListCtrl::setScrollPos( S32 pos )
void LLScrollListCtrl::scrollToShowSelected()
{
+ // don't scroll automatically when capturing mouse input
+ // as that will change what is currently under the mouse cursor
+ if (hasMouseCapture())
+ {
+ return;
+ }
+
S32 index = getFirstSelectedIndex();
if (index < 0)
{
@@ -3033,8 +3051,9 @@ LLColumnHeader::LLColumnHeader(const LLString& label, const LLRect &rect, LLScro
const S32 RESIZE_BAR_THICKNESS = 3;
mResizeBar = new LLResizeBar(
"resizebar",
+ this,
LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
- MIN_COLUMN_WIDTH, mRect.getHeight(), LLResizeBar::RIGHT );
+ MIN_COLUMN_WIDTH, S32_MAX, LLResizeBar::RIGHT );
addChild(mResizeBar);
mResizeBar->setEnabled(FALSE);
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h
index f1bd9bb..809c528 100644
--- a/linden/indra/llui/llscrolllistctrl.h
+++ b/linden/indra/llui/llscrolllistctrl.h
@@ -605,6 +605,7 @@ protected:
BOOL mCommitOnKeyboardMovement;
BOOL mCommitOnSelectionChange;
BOOL mSelectionChanged;
+ BOOL mNeedsScroll;
BOOL mCanSelect;
BOOL mDisplayColumnHeaders;
BOOL mCollapseEmptyColumns;
diff --git a/linden/indra/llui/llslider.cpp b/linden/indra/llui/llslider.cpp
index 8c0d2a1..e3a3153 100644
--- a/linden/indra/llui/llslider.cpp
+++ b/linden/indra/llui/llslider.cpp
@@ -50,6 +50,7 @@ LLSlider::LLSlider(
F32 min_value,
F32 max_value,
F32 increment,
+ BOOL volume,
const LLString& control_name)
:
LLUICtrl( name, rect, TRUE, on_commit_callback, callback_userdata,
@@ -59,6 +60,7 @@ LLSlider::LLSlider(
mMinValue( min_value ),
mMaxValue( max_value ),
mIncrement( increment ),
+ mVolumeSlider( volume ),
mMouseOffset( 0 ),
mDragStartThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
mThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
@@ -69,7 +71,7 @@ LLSlider::LLSlider(
mMouseDownCallback( NULL ),
mMouseUpCallback( NULL )
{
- // prperly handle setting the starting thumb rect
+ // properly handle setting the starting thumb rect
// do it this way to handle both the operating-on-settings
// and standalone ways of using this
setControlName(control_name, NULL);
@@ -94,13 +96,15 @@ void LLSlider::setValue(F32 value, BOOL from_event)
value -= mMinValue;
value += mIncrement/2.0001f;
value -= fmod(value, mIncrement);
- mValue = mMinValue + value;
+ value += mMinValue;
- if (!from_event)
+ if (!from_event && mValue != value)
{
- setControlValue(mValue);
+ setControlValue(value);
}
-
+
+ mValue = value;
+
F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
S32 left_edge = THUMB_WIDTH/2;
@@ -111,6 +115,18 @@ void LLSlider::setValue(F32 value, BOOL from_event)
mThumbRect.mRight = x + (THUMB_WIDTH/2);
}
+void LLSlider::setValueAndCommit(F32 value)
+{
+ F32 old_value = mValue;
+ setValue(value);
+
+ if (mValue != old_value)
+ {
+ onCommit();
+ }
+}
+
+
F32 LLSlider::getValueF32() const
{
return mValue;
@@ -127,8 +143,7 @@ BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
x = llclamp( x, left_edge, right_edge );
F32 t = F32(x - left_edge) / (right_edge - left_edge);
- setValue(t * (mMaxValue - mMinValue) + mMinValue );
- onCommit();
+ setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
getWindow()->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
@@ -178,8 +193,7 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
if (MASK_CONTROL & mask) // if CTRL is modifying
{
- setValue(mInitialValue);
- onCommit();
+ setValueAndCommit(mInitialValue);
}
else
{
@@ -216,13 +230,11 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
handled = TRUE;
break;
case KEY_LEFT:
- setValue(getValueF32() - getIncrement());
- onCommit();
+ setValueAndCommit(getValueF32() - getIncrement());
handled = TRUE;
break;
case KEY_RIGHT:
- setValue(getValueF32() + getIncrement());
- onCommit();
+ setValueAndCommit(getValueF32() + getIncrement());
handled = TRUE;
break;
default:
@@ -244,33 +256,93 @@ void LLSlider::draw()
LLRect rect(mDragStartThumbRect);
F32 opacity = mEnabled ? 1.f : 0.3f;
+ LLColor4 center_color = (mThumbCenterColor % opacity);
+ LLColor4 outline_color = (mThumbOutlineColor % opacity);
+ LLColor4 track_color = (mTrackColor % opacity);
+ LLImageGL* thumb_imagep = NULL;
+
// Track
+ if (mVolumeSlider)
+ {
+ LLRect track(0, mRect.getHeight(), mRect.getWidth(), 0);
+
+ track.mBottom += 3;
+ track.mTop -= 1;
+ track.mRight -= 1;
+
+ gl_triangle_2d(track.mLeft, track.mBottom,
+ track.mRight, track.mBottom,
+ track.mRight, track.mTop,
+ center_color,
+ TRUE);
+ gl_triangle_2d(track.mLeft, track.mBottom,
+ track.mRight, track.mBottom,
+ track.mRight, track.mTop,
+ outline_color,
+ FALSE);
+ }
+ else
+ {
+ LLUUID thumb_image_id;
+ thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
+ thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
- LLUUID thumb_image_id;
- thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
- LLImageGL* thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
-
- S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2;
- LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset );
+ S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2;
+ LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset );
- track_rect.stretch(-1);
- gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
- thumb_imagep, mTrackColor % opacity);
- //gl_rect_2d( track_rect, mThumbOutlineColor % opacity );
+ track_rect.stretch(-1);
+ gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
+ thumb_imagep, track_color);
+ }
+ // Thumb
if (!thumb_imagep)
{
- gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
- if (hasMouseCapture())
+ if (mVolumeSlider)
+ {
+ if (hasMouseCapture())
+ {
+ LLRect rect(mDragStartThumbRect);
+ gl_rect_2d( rect, outline_color );
+ rect.stretch(-1);
+ gl_rect_2d( rect, mThumbCenterColor % 0.3f );
+
+ if (hasFocus())
+ {
+ LLRect thumb_rect = mThumbRect;
+ thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
+ gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
+ }
+ gl_rect_2d( mThumbRect, mThumbOutlineColor );
+ }
+ else
+ {
+ if (hasFocus())
+ {
+ LLRect thumb_rect = mThumbRect;
+ thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
+ gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
+ }
+ LLRect rect(mThumbRect);
+ gl_rect_2d(rect, outline_color);
+ rect.stretch(-1);
+ gl_rect_2d( rect, center_color);
+ }
+ }
+ else
{
- gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE);
+ gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
+ if (hasMouseCapture())
+ {
+ gl_rect_2d(mDragStartThumbRect, center_color, FALSE);
+ }
}
}
else if( hasMouseCapture() )
{
gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(),
- thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
+ thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
if (hasFocus())
{
@@ -278,20 +350,12 @@ void LLSlider::draw()
LLRect highlight_rect = mThumbRect;
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
- thumb_imagep, gFocusMgr.getFocusColor());
+ thumb_imagep, gFocusMgr.getFocusColor());
}
-
gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
- thumb_imagep, mThumbOutlineColor, TRUE);
-
- //// Start Thumb
- //gl_rect_2d( mDragStartThumbRect, mThumbOutlineColor % 0.3f );
- //rect.stretch(-1);
- //gl_rect_2d( rect, mThumbCenterColor % 0.3f );
+ thumb_imagep, mThumbOutlineColor, TRUE);
- //// Thumb
- //gl_rect_2d( mThumbRect, mThumbOutlineColor );
}
else
{
@@ -301,22 +365,12 @@ void LLSlider::draw()
LLRect highlight_rect = mThumbRect;
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
- thumb_imagep, gFocusMgr.getFocusColor());
+ thumb_imagep, gFocusMgr.getFocusColor());
}
gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
- thumb_imagep, mThumbCenterColor % opacity, TRUE);
- //rect = mThumbRect;
-
- //gl_rect_2d( mThumbRect, mThumbOutlineColor % opacity );
- //
- //rect.stretch(-1);
-
- //// Thumb
- //gl_rect_2d( rect, mThumbCenterColor % opacity );
-
+ thumb_imagep, center_color, TRUE);
}
-
LLUICtrl::draw();
}
}
@@ -330,6 +384,7 @@ LLXMLNodePtr LLSlider::getXML(bool save_children) const
node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
node->createChild("increment", TRUE)->setFloatValue(getIncrement());
+ node->createChild("volume", TRUE)->setBoolValue(getVolumeSlider());
return node;
}
@@ -356,6 +411,8 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
F32 increment = 0.1f;
node->getAttributeF32("increment", increment);
+ BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
+ node->getAttributeBOOL("volume", volume);
LLSlider* slider = new LLSlider(name,
rect,
@@ -364,7 +421,8 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
initial_value,
min_value,
max_value,
- increment);
+ increment,
+ volume);
slider->initFromXML(node, parent);
diff --git a/linden/indra/llui/llslider.h b/linden/indra/llui/llslider.h
index 4f42a56..8fcd672 100644
--- a/linden/indra/llui/llslider.h
+++ b/linden/indra/llui/llslider.h
@@ -46,6 +46,7 @@ public:
F32 min_value,
F32 max_value,
F32 increment,
+ BOOL volume,
const LLString& control_name = LLString::null );
virtual EWidgetType getWidgetType() const;
@@ -66,6 +67,7 @@ public:
F32 getMinValue() const { return mMinValue; }
F32 getMaxValue() const { return mMaxValue; }
F32 getIncrement() const { return mIncrement; }
+ BOOL getVolumeSlider() const { return mVolumeSlider; }
void setMinValue(F32 min_value) {mMinValue = min_value;}
void setMaxValue(F32 max_value) {mMaxValue = max_value;}
void setIncrement(F32 increment) {mIncrement = increment;}
@@ -79,12 +81,16 @@ public:
virtual void draw();
protected:
+ void setValueAndCommit(F32 value);
+
+protected:
F32 mValue;
F32 mInitialValue;
F32 mMinValue;
F32 mMaxValue;
F32 mIncrement;
+ BOOL mVolumeSlider;
S32 mMouseOffset;
LLRect mDragStartThumbRect;
diff --git a/linden/indra/llui/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp
index 9a67bca..dff27cc 100644
--- a/linden/indra/llui/llsliderctrl.cpp
+++ b/linden/indra/llui/llsliderctrl.cpp
@@ -57,6 +57,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
S32 text_left,
BOOL show_text,
BOOL can_edit_text,
+ BOOL volume,
void (*commit_callback)(LLUICtrl*, void*),
void* callback_user_data,
F32 initial_value, F32 min_value, F32 max_value, F32 increment,
@@ -65,6 +66,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
mFont(font),
mShowText( show_text ),
mCanEditText( can_edit_text ),
+ mVolumeSlider( volume ),
mPrecision( 3 ),
mLabelBox( NULL ),
mLabelWidth( label_width ),
@@ -104,7 +106,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
"slider",
slider_rect,
LLSliderCtrl::onSliderCommit, this,
- initial_value, min_value, max_value, increment,
+ initial_value, min_value, max_value, increment, volume,
control_which );
addChild( mSlider );
@@ -443,6 +445,8 @@ LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const
node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
+ node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider);
+
node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
if (mLabelBox)
@@ -494,6 +498,9 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
BOOL can_edit_text = FALSE;
node->getAttributeBOOL("can_edit_text", can_edit_text);
+ BOOL volume = FALSE;
+ node->getAttributeBOOL("volume", volume);
+
F32 initial_value = 0.f;
node->getAttributeF32("initial_val", initial_value);
@@ -541,6 +548,7 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
rect.getWidth() - text_left,
show_text,
can_edit_text,
+ volume,
callback,
NULL,
initial_value,
diff --git a/linden/indra/llui/llsliderctrl.h b/linden/indra/llui/llsliderctrl.h
index 26c9dee..6896360 100644
--- a/linden/indra/llui/llsliderctrl.h
+++ b/linden/indra/llui/llsliderctrl.h
@@ -60,6 +60,7 @@ public:
S32 text_left,
BOOL show_text,
BOOL can_edit_text,
+ BOOL volume,
void (*commit_callback)(LLUICtrl*, void*),
void* callback_userdata,
F32 initial_value, F32 min_value, F32 max_value, F32 increment,
@@ -124,7 +125,8 @@ private:
const LLFontGL* mFont;
BOOL mShowText;
BOOL mCanEditText;
-
+ BOOL mVolumeSlider;
+
S32 mPrecision;
LLTextBox* mLabelBox;
S32 mLabelWidth;
diff --git a/linden/indra/llui/lltabcontainer.cpp b/linden/indra/llui/lltabcontainer.cpp
index 01c06c3..135931d 100644
--- a/linden/indra/llui/lltabcontainer.cpp
+++ b/linden/indra/llui/lltabcontainer.cpp
@@ -70,6 +70,7 @@ LLTabContainerCommon::LLTabContainerCommon(
:
LLPanel(name, rect, bordered),
mCurrentTabIdx(-1),
+ mTabsHidden(FALSE),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
@@ -95,6 +96,7 @@ LLTabContainerCommon::LLTabContainerCommon(
:
LLPanel(name, rect_control, bordered),
mCurrentTabIdx(-1),
+ mTabsHidden(FALSE),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
@@ -147,11 +149,11 @@ void LLTabContainerCommon::addPlaceholder(LLPanel* child, const LLString& label)
addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
}
-void LLTabContainerCommon::lockTabs()
+void LLTabContainerCommon::lockTabs(S32 num_tabs)
{
- // count current tabs and ensure no new tabs get
+ // count current tabs or use supplied value and ensure no new tabs get
// inserted between them
- mLockedTabCount = getTabCount();
+ mLockedTabCount = num_tabs > 0 ? num_tabs : getTabCount();
}
void LLTabContainerCommon::removeTabPanel(LLPanel* child)
@@ -542,12 +544,12 @@ void LLTabContainerCommon::setTabPanelFlashing(LLPanel* child, BOOL state )
}
}
-void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name)
+void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name, const LLColor4& color)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(img_name, LLFontGL::RIGHT);
+ tuple->mButton->setImageOverlay(img_name, LLFontGL::RIGHT, color);
}
}
@@ -667,6 +669,8 @@ LLView* LLTabContainerCommon::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtr
}
}
+ node->getAttributeBOOL("hide_tabs", tab_container->mTabsHidden);
+
tab_container->setPanelParameters(node, parent);
if (LLFloater::getFloaterHost())
@@ -1036,10 +1040,11 @@ void LLTabContainer::setPanelTitle(S32 index, const LLString& title)
{
if (index >= 0 && index < (S32)mTabList.size())
{
- LLButton* tab_button = mTabList[index]->mButton;
+ LLTabTuple* tuple = mTabList[index];
+ LLButton* tab_button = tuple->mButton;
const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
mTotalTabWidth -= tab_button->getRect().getWidth();
- tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
+ tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
mTotalTabWidth += tab_button->getRect().getWidth();
tab_button->setLabelSelected(title);
tab_button->setLabelUnselected(title);
@@ -1245,63 +1250,60 @@ void LLTabContainer::draw()
LLPanel::draw();
- // Show all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ // if tabs are hidden, don't draw them and leave them in the invisible state
+ if (!mTabsHidden)
{
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
- }
-
- // Draw some of the buttons...
+ // Show all the buttons
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( TRUE );
+ }
- LLGLEnable scissor_test(has_scroll_arrows ? GL_SCISSOR_TEST : GL_FALSE);
- if( has_scroll_arrows )
- {
- // ...but clip them.
- S32 x1 = mLeftArrowBtn->getRect().mRight;
- S32 y1 = 0;
- S32 x2 = mRightArrowBtn->getRect().mLeft;
- S32 y2 = 1;
- if (mTabList.size() > 0)
+ // Draw some of the buttons...
+ LLRect clip_rect = getLocalRect();
+ if (has_scroll_arrows)
{
- y2 = mTabList[0]->mButton->getRect().mTop;
+ // ...but clip them.
+ clip_rect.mLeft = mLeftArrowBtn->getRect().mRight;
+ clip_rect.mRight = mRightArrowBtn->getRect().mLeft;
}
- LLUI::setScissorRegionLocal(LLRect(x1, y2, x2, y1));
- }
+ LLLocalClipRect clip(clip_rect);
- S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
- S32 idx = 0;
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
+ S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
+ S32 idx = 0;
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
- tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 );
- left += tuple->mButton->getRect().getWidth();
+ tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 );
+ left += tuple->mButton->getRect().getWidth();
- if( idx < mScrollPos )
- {
- if( tuple->mButton->getFlashing() )
+ if( idx < mScrollPos )
{
- mLeftArrowBtn->setFlashing( TRUE );
+ if( tuple->mButton->getFlashing() )
+ {
+ mLeftArrowBtn->setFlashing( TRUE );
+ }
}
- }
- else
- if( max_scroll_visible < idx )
- {
- if( tuple->mButton->getFlashing() )
+ else
+ if( max_scroll_visible < idx )
{
- mRightArrowBtn->setFlashing( TRUE );
+ if( tuple->mButton->getFlashing() )
+ {
+ mRightArrowBtn->setFlashing( TRUE );
+ }
}
- }
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
- tuple->mButton->draw();
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
+ tuple->mButton->draw();
+ }
+ LLUI::popMatrix();
+
+ idx++;
}
- LLUI::popMatrix();
-
- idx++;
}
mLeftArrowBtn->setFlashing(FALSE);
@@ -1628,12 +1630,12 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
}
-void LLTabContainer::setTabImage(LLPanel* child, std::string image_name)
+void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT);
+ tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
// remove current width from total tab strip width
@@ -1642,7 +1644,11 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name)
S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
tuple->mButton->getImageOverlay()->getWidth(0) :
0;
- tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + image_overlay_width, mMinTabWidth, mMaxTabWidth),
+
+ tuple->mPadding = image_overlay_width;
+
+ tuple->mButton->setRightHPad(tuple->mPadding + LLBUTTON_H_PAD);
+ tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
tuple->mButton->getRect().getHeight());
// add back in button width to total tab strip width
mTotalTabWidth += tuple->mButton->getRect().getWidth();
diff --git a/linden/indra/llui/lltabcontainer.h b/linden/indra/llui/lltabcontainer.h
index f3365c3..3056c0a 100644
--- a/linden/indra/llui/lltabcontainer.h
+++ b/linden/indra/llui/lltabcontainer.h
@@ -87,7 +87,7 @@ public:
BOOL placeholder = FALSE,
eInsertionPoint insertion_point = END) = 0;
virtual void addPlaceholder(LLPanel* child, const LLString& label);
- virtual void lockTabs();
+ virtual void lockTabs(S32 num_tabs = 0);
virtual void enableTabButton(S32 which, BOOL enable);
@@ -114,7 +114,7 @@ public:
BOOL getTabPanelFlashing(LLPanel* child);
void setTabPanelFlashing(LLPanel* child, BOOL state);
- virtual void setTabImage(LLPanel* child, std::string img_name);
+ virtual void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
void setTitle( const LLString& title );
const LLString getPanelTitle(S32 index);
@@ -155,7 +155,8 @@ protected:
mOnChangeCallback( cb ),
mUserData( userdata ),
mOldState(FALSE),
- mPlaceholderText(placeholder)
+ mPlaceholderText(placeholder),
+ mPadding(0)
{}
LLTabContainerCommon* mTabContainer;
@@ -165,11 +166,13 @@ protected:
void* mUserData;
BOOL mOldState;
LLTextBox* mPlaceholderText;
+ S32 mPadding;
};
typedef std::vector tuple_list_t;
tuple_list_t mTabList;
S32 mCurrentTabIdx;
+ BOOL mTabsHidden;
BOOL mScrolled;
LLFrameTimer mScrollTimer;
@@ -228,7 +231,7 @@ public:
/*virtual*/ void removeTabPanel( LLPanel* child );
/*virtual*/ void setPanelTitle(S32 index, const LLString& title);
- /*virtual*/ void setTabImage(LLPanel* child, std::string img_name);
+ /*virtual*/ void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
/*virtual*/ void setRightTabBtnOffset( S32 offset );
/*virtual*/ void setMinTabWidth(S32 width);
diff --git a/linden/indra/llui/lltabcontainervertical.cpp b/linden/indra/llui/lltabcontainervertical.cpp
index 317b7ca..e2d84a5 100644
--- a/linden/indra/llui/lltabcontainervertical.cpp
+++ b/linden/indra/llui/lltabcontainervertical.cpp
@@ -392,49 +392,47 @@ void LLTabContainerVertical::draw()
}
// Draw some of the buttons...
-
- LLGLEnable scissor_test(has_scroll_arrows ? GL_SCISSOR_TEST : GL_FALSE);
-
- if( has_scroll_arrows )
- {
- // ...but clip them.
- S32 x1 = mRect.mLeft;
- S32 y1 = mDownArrowBtn->getRect().mTop + 3*TABCNTRV_PAD;
- S32 x2 = mRect.mRight;
- S32 y2 = mUpArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD;
- LLUI::setScissorRegionLocal(LLRect(x1, y2, x2, y1));
- }
-
- //S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
- S32 idx = 0;
- for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
- LLTabTuple* tuple = *iter;
- tuple->mButton->translate( 0 , top - tuple->mButton->getRect().mTop);
- top -= BTN_HEIGHT + TABCNTRV_PAD;
-
- LLUI::pushMatrix();
+ LLRect clip_rect = getLocalRect();
+ if (has_scroll_arrows)
{
- LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
- tuple->mButton->draw();
+ // ...but clip them.
+ clip_rect.mBottom = mDownArrowBtn->getRect().mTop + 3*TABCNTRV_PAD;
+ clip_rect.mTop = mUpArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD;
}
- LLUI::popMatrix();
+ LLLocalClipRect clip(clip_rect);
- idx++;
- }
+ //S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
+ S32 idx = 0;
+ for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->translate( 0 , top - tuple->mButton->getRect().mTop);
+ top -= BTN_HEIGHT + TABCNTRV_PAD;
- if( has_scroll_arrows )
- {
- // Redraw the arrows so that they appears on top.
- glPushMatrix();
- glTranslatef((F32)mUpArrowBtn->getRect().mLeft, (F32)mUpArrowBtn->getRect().mBottom, 0.f);
- mUpArrowBtn->draw();
- glPopMatrix();
-
- glPushMatrix();
- glTranslatef((F32)mDownArrowBtn->getRect().mLeft, (F32)mDownArrowBtn->getRect().mBottom, 0.f);
- mDownArrowBtn->draw();
- glPopMatrix();
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
+ tuple->mButton->draw();
+ }
+ LLUI::popMatrix();
+
+ idx++;
+ }
+
+ if( has_scroll_arrows )
+ {
+ // Redraw the arrows so that they appears on top.
+ glPushMatrix();
+ glTranslatef((F32)mUpArrowBtn->getRect().mLeft, (F32)mUpArrowBtn->getRect().mBottom, 0.f);
+ mUpArrowBtn->draw();
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef((F32)mDownArrowBtn->getRect().mLeft, (F32)mDownArrowBtn->getRect().mBottom, 0.f);
+ mDownArrowBtn->draw();
+ glPopMatrix();
+ }
}
}
}
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index 513670b..f49b2db 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -103,9 +103,9 @@ BOOL LLTextCmd::hasExtCharValue( llwchar value )
}
// Utility funcs
-S32 LLTextCmd::insert(LLTextEditor* editor, S32 pos, const LLWString &utf8str)
+S32 LLTextCmd::insert(LLTextEditor* editor, S32 pos, const LLWString &wstr)
{
- return editor->insertStringNoUndo( pos, utf8str );
+ return editor->insertStringNoUndo( pos, wstr );
}
S32 LLTextCmd::remove(LLTextEditor* editor, S32 pos, S32 length)
{
@@ -122,29 +122,29 @@ class LLTextCmdInsert : public LLTextCmd
{
public:
LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws)
- : LLTextCmd(pos, group_with_next), mString(ws)
+ : LLTextCmd(pos, group_with_next), mWString(ws)
{
}
virtual BOOL execute( LLTextEditor* editor, S32* delta )
{
- *delta = insert(editor, mPos, mString );
- LLWString::truncate(mString, *delta);
- //mString = wstring_truncate(mString, *delta);
+ *delta = insert(editor, mPos, mWString );
+ LLWString::truncate(mWString, *delta);
+ //mWString = wstring_truncate(mWString, *delta);
return (*delta != 0);
}
virtual S32 undo( LLTextEditor* editor )
{
- remove(editor, mPos, mString.length() );
+ remove(editor, mPos, mWString.length() );
return mPos;
}
virtual S32 redo( LLTextEditor* editor )
{
- insert(editor, mPos, mString );
- return mPos + mString.length();
+ insert(editor, mPos, mWString );
+ return mPos + mWString.length();
}
private:
- LLWString mString;
+ LLWString mWString;
};
///////////////////////////////////////////////////////////////////
@@ -153,7 +153,7 @@ class LLTextCmdAddChar : public LLTextCmd
{
public:
LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc)
- : LLTextCmd(pos, group_with_next), mString(1, wc), mBlockExtensions(FALSE)
+ : LLTextCmd(pos, group_with_next), mWString(1, wc), mBlockExtensions(FALSE)
{
}
virtual void blockExtensions()
@@ -162,13 +162,13 @@ public:
}
virtual BOOL canExtend(S32 pos)
{
- return !mBlockExtensions && (pos == mPos + (S32)mString.length());
+ return !mBlockExtensions && (pos == mPos + (S32)mWString.length());
}
virtual BOOL execute( LLTextEditor* editor, S32* delta )
{
- *delta = insert(editor, mPos, mString);
- LLWString::truncate(mString, *delta);
- //mString = wstring_truncate(mString, *delta);
+ *delta = insert(editor, mPos, mWString);
+ LLWString::truncate(mWString, *delta);
+ //mWString = wstring_truncate(mWString, *delta);
return (*delta != 0);
}
virtual BOOL extendAndExecute( LLTextEditor* editor, S32 pos, llwchar wc, S32* delta )
@@ -179,23 +179,23 @@ public:
*delta = insert(editor, pos, ws);
if( *delta > 0 )
{
- mString += wc;
+ mWString += wc;
}
return (*delta != 0);
}
virtual S32 undo( LLTextEditor* editor )
{
- remove(editor, mPos, mString.length() );
+ remove(editor, mPos, mWString.length() );
return mPos;
}
virtual S32 redo( LLTextEditor* editor )
{
- insert(editor, mPos, mString );
- return mPos + mString.length();
+ insert(editor, mPos, mWString );
+ return mPos + mWString.length();
}
private:
- LLWString mString;
+ LLWString mWString;
BOOL mBlockExtensions;
};
@@ -242,14 +242,14 @@ public:
}
virtual BOOL execute( LLTextEditor* editor, S32* delta )
{
- mString = editor->getWSubString(mPos, mLen);
+ mWString = editor->getWSubString(mPos, mLen);
*delta = remove(editor, mPos, mLen );
return (*delta != 0);
}
virtual S32 undo( LLTextEditor* editor )
{
- insert(editor, mPos, mString );
- return mPos + mString.length();
+ insert(editor, mPos, mWString );
+ return mPos + mWString.length();
}
virtual S32 redo( LLTextEditor* editor )
{
@@ -257,7 +257,7 @@ public:
return mPos;
}
private:
- LLWString mString;
+ LLWString mWString;
S32 mLen;
};
@@ -3013,8 +3013,7 @@ void LLTextEditor::draw()
if( getVisible() )
{
{
- LLGLEnable scissor_test(GL_SCISSOR_TEST);
- LLUI::setScissorRegionLocal(LLRect(0, mRect.getHeight(), mRect.getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
+ LLLocalClipRect clip(LLRect(0, mRect.getHeight(), mRect.getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
bindEmbeddedChars( mGLFont );
diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h
index ebe8ac3..68c1d4a 100644
--- a/linden/indra/llui/lltexteditor.h
+++ b/linden/indra/llui/lltexteditor.h
@@ -329,7 +329,7 @@ protected:
S32 append(const LLWString &wstr, const BOOL group_with_next_op);
// direct operations
- S32 insertStringNoUndo(S32 pos, const LLWString &utf8str); // returns num of chars actually inserted
+ S32 insertStringNoUndo(S32 pos, const LLWString &wstr); // returns num of chars actually inserted
S32 removeStringNoUndo(S32 pos, S32 length);
S32 overwriteCharNoUndo(S32 pos, llwchar wc);
@@ -495,7 +495,7 @@ public:
virtual BOOL hasExtCharValue( llwchar value );
// Define these here so they can access LLTextEditor through the friend relationship
- S32 insert(LLTextEditor* editor, S32 pos, const LLWString &utf8str);
+ S32 insert(LLTextEditor* editor, S32 pos, const LLWString &wstr);
S32 remove(LLTextEditor* editor, S32 pos, S32 length);
S32 overwrite(LLTextEditor* editor, S32 pos, llwchar wc);
diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp
index a725281..d0815a7 100644
--- a/linden/indra/llui/llui.cpp
+++ b/linden/indra/llui/llui.cpp
@@ -77,6 +77,8 @@ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
LLWindow* LLUI::sWindow = NULL;
LLHtmlHelp* LLUI::sHtmlHelp = NULL;
BOOL LLUI::sShowXUINames = FALSE;
+std::stack LLUI::sClipRectStack;
+
//
// Functions
//
@@ -110,7 +112,7 @@ void make_ui_sound(const LLString& name)
{
llinfos << "ui sound name: " << name << llendl;
}
- LLUI::sAudioCallback(uuid, LLUI::sConfigGroup->getF32("AudioLevelUI"));
+ LLUI::sAudioCallback(uuid);
}
}
}
@@ -1811,3 +1813,59 @@ void LLUI::setHtmlHelp(LLHtmlHelp* html_help)
{
LLUI::sHtmlHelp = html_help;
}
+
+//static
+void LLUI::pushClipRect(const LLRect& rect)
+{
+ LLRect combined_clip_rect = rect;
+ if (!sClipRectStack.empty())
+ {
+ combined_clip_rect.intersectWith(sClipRectStack.top());
+ }
+ sClipRectStack.push(combined_clip_rect);
+ setScissorRegionScreen(combined_clip_rect);
+}
+
+//static
+void LLUI::popClipRect()
+{
+ sClipRectStack.pop();
+ if (!sClipRectStack.empty())
+ {
+ setScissorRegionScreen(sClipRectStack.top());
+ }
+}
+
+LLClipRect::LLClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled)
+{
+ if (mEnabled)
+ {
+ LLUI::pushClipRect(rect);
+ }
+}
+
+LLClipRect::~LLClipRect()
+{
+ if (mEnabled)
+ {
+ LLUI::popClipRect();
+ }
+}
+
+LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled)
+{
+ if (mEnabled)
+ {
+ LLRect scissor_rect = rect;
+ scissor_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY);
+ LLUI::pushClipRect(scissor_rect);
+ }
+}
+
+LLLocalClipRect::~LLLocalClipRect()
+{
+ if (mEnabled)
+ {
+ LLUI::popClipRect();
+ }
+}
diff --git a/linden/indra/llui/llui.h b/linden/indra/llui/llui.h
index 3085bd9..201d88f 100644
--- a/linden/indra/llui/llui.h
+++ b/linden/indra/llui/llui.h
@@ -36,6 +36,8 @@
#include "llrect.h"
#include "llcoord.h"
#include "llhtmlhelp.h"
+#include "llgl.h"
+#include
class LLColor4;
class LLVector3;
@@ -143,7 +145,7 @@ extern BOOL gShowTextEditCursor;
extern LLString gLanguage;
class LLImageProviderInterface;
-typedef void (*LLUIAudioCallback)(const LLUUID& uuid, F32 volume);
+typedef void (*LLUIAudioCallback)(const LLUUID& uuid);
class LLUI
{
@@ -164,8 +166,8 @@ public:
//helper functions (should probably move free standing rendering helper functions here)
static LLString locateSkin(const LLString& filename);
- static void setScissorRegionScreen(const LLRect& rect);
- static void setScissorRegionLocal(const LLRect& rect); // works assuming LLUI::translate has been called
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
static void setCursorPositionScreen(S32 x, S32 y);
static void setCursorPositionLocal(LLView* viewp, S32 x, S32 y);
static void setScaleFactor(const LLVector2& scale_factor);
@@ -173,6 +175,11 @@ public:
static LLUUID findAssetUUIDByName(const LLString& name);
static LLVector2 getWindowSize();
static void setHtmlHelp(LLHtmlHelp* html_help);
+
+private:
+ static void setScissorRegionScreen(const LLRect& rect);
+ static void setScissorRegionLocal(const LLRect& rect); // works assuming LLUI::translate has been called
+
public:
static LLControlGroup* sConfigGroup;
static LLControlGroup* sColorsGroup;
@@ -183,6 +190,8 @@ public:
static LLWindow* sWindow;
static BOOL sShowXUINames;
static LLHtmlHelp* sHtmlHelp;
+ static std::stack sClipRectStack;
+
};
// UI widgets
@@ -271,6 +280,7 @@ typedef enum e_widget_type
WIDGET_TYPE_TEXTURE_VIEW,
WIDGET_TYPE_MEMORY_VIEW,
WIDGET_TYPE_FRAME_STAT_VIEW,
+ WIDGET_TYPE_LAYOUT_STACK,
WIDGET_TYPE_DONTCARE,
WIDGET_TYPE_COUNT
} EWidgetType;
@@ -292,38 +302,38 @@ public:
}
// default show and hide methods
- static T* showInstance(const LLSD& seed)
+ static T* showInstance(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::getInstance(seed);
INSTANCE_ADAPTOR::show(instance);
return instance;
}
- static void hideInstance(const LLSD& seed)
+ static void hideInstance(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::getInstance(seed);
INSTANCE_ADAPTOR::hide(instance);
}
- static void toggleInstance(const LLSD& seed)
+ static void toggleInstance(const LLSD& seed = LLSD())
{
- if (!INSTANCE_ADAPTOR::instanceVisible(seed))
+ if (INSTANCE_ADAPTOR::instanceVisible(seed))
{
- INSTANCE_ADAPTOR::showInstance(seed);
+ INSTANCE_ADAPTOR::hideInstance(seed);
}
else
{
- INSTANCE_ADAPTOR::hideInstance(seed);
+ INSTANCE_ADAPTOR::showInstance(seed);
}
}
- static BOOL instanceVisible(const LLSD& seed)
+ static BOOL instanceVisible(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::findInstance(seed);
return instance != NULL && INSTANCE_ADAPTOR::visible(instance);
}
- static T* getInstance(const LLSD& seed)
+ static T* getInstance(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::findInstance(seed);
if (instance == NULL)
@@ -332,6 +342,7 @@ public:
}
return instance;
}
+
};
// Creates a UI singleton by ignoring the identifying parameter
@@ -346,12 +357,12 @@ public:
LLUISingleton() : LLUIInstanceMgr() { sInstance = (T*)this; }
~LLUISingleton() { sInstance = NULL; }
- static T* findInstance(const LLSD& seed)
+ static T* findInstance(const LLSD& seed = LLSD())
{
return sInstance;
}
- static T* createInstance(const LLSD& seed)
+ static T* createInstance(const LLSD& seed = LLSD())
{
if (sInstance == NULL)
{
@@ -366,4 +377,24 @@ protected:
template T* LLUISingleton::sInstance = NULL;
+class LLClipRect
+{
+public:
+ LLClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLClipRect();
+protected:
+ LLGLState mScissorState;
+ BOOL mEnabled;
+};
+
+class LLLocalClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLLocalClipRect();
+protected:
+ LLGLState mScissorState;
+ BOOL mEnabled;
+};
+
#endif
diff --git a/linden/indra/llui/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp
index 1762d7c..0ac3916 100644
--- a/linden/indra/llui/lluictrl.cpp
+++ b/linden/indra/llui/lluictrl.cpp
@@ -256,7 +256,7 @@ public:
/*virtual*/ void operator() (LLView * parent, viewList_t &children) const
{
children.sort(CompareByDefaultTabGroup(parent->getCtrlOrder(), parent->getDefaultTabGroup()));
- }
+ }
};
BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields)
diff --git a/linden/indra/llui/lluictrl.h b/linden/indra/llui/lluictrl.h
index 5056319..2060a0d 100644
--- a/linden/indra/llui/lluictrl.h
+++ b/linden/indra/llui/lluictrl.h
@@ -148,6 +148,9 @@ public:
}
};
+ // Returns TRUE if the user has modified this control. Editable controls should override this.
+ virtual BOOL isDirty() { return FALSE; };
+
protected:
virtual void onFocusReceived();
virtual void onFocusLost();
diff --git a/linden/indra/llui/lluictrlfactory.cpp b/linden/indra/llui/lluictrlfactory.cpp
index 79f7313..70f1e3e 100644
--- a/linden/indra/llui/lluictrlfactory.cpp
+++ b/linden/indra/llui/lluictrlfactory.cpp
@@ -89,7 +89,7 @@ const LLString LLUICtrlFactory::sUICtrlNames[WIDGET_TYPE_COUNT] =
LLString("web_browser"), //WIDGET_TYPE_WEBBROWSER
LLString("slider"), //WIDGET_TYPE_SLIDER, actually LLSliderCtrl
LLString("slider_bar"), //WIDGET_TYPE_SLIDER_BAR, actually LLSlider
- LLString("volume_slider"), //WIDGET_TYPE_VOLUME_SLIDER, actually LLVolumeSliderCtrl
+ LLString("volume_slider"), //WIDGET_TYPE_VOLUME_SLIDER, actually LLSlider + "volume" param
LLString("spinner"), //WIDGET_TYPE_SPINNER, actually LLSpinCtrl
LLString("text_editor"), //WIDGET_TYPE_TEXT_EDITOR
LLString("texture_picker"),//WIDGET_TYPE_TEXTURE_PICKER
@@ -155,6 +155,7 @@ const LLString LLUICtrlFactory::sUICtrlNames[WIDGET_TYPE_COUNT] =
LLString("texture_view"), //WIDGET_TYPE_TEXTURE_VIEW
LLString("memory_view"), //WIDGET_TYPE_MEMORY_VIEW
LLString("frame_stat_view"), //WIDGET_TYPE_FRAME_STAT_VIEW
+ LLString("layout_stack"), //WIDGET_TYPE_LAYOUT_STACK
LLString("DONT_CARE"), //WIDGET_TYPE_DONTCARE
};
@@ -197,6 +198,7 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator::registerCreator(LL_SCROLL_LIST_CTRL_TAG, this);
LLUICtrlCreator::registerCreator(LL_SLIDER_CTRL_TAG, this);
LLUICtrlCreator::registerCreator(LL_SLIDER_TAG, this);
+ LLUICtrlCreator::registerCreator(LL_VOLUME_SLIDER_CTRL_TAG, this);
LLUICtrlCreator::registerCreator(LL_SPIN_CTRL_TAG, this);
LLUICtrlCreator::registerCreator(LL_TEXT_BOX_TAG, this);
LLUICtrlCreator::registerCreator(LL_RADIO_GROUP_TAG, this);
@@ -210,6 +212,7 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator::registerCreator(LL_MENU_GL_TAG, this);
LLUICtrlCreator::registerCreator(LL_MENU_BAR_GL_TAG, this);
LLUICtrlCreator::registerCreator(LL_SCROLLING_PANEL_LIST_TAG, this);
+ LLUICtrlCreator::registerCreator(LL_LAYOUT_STACK_TAG, this);
setupPaths();
@@ -765,6 +768,37 @@ LLScrollingPanelList* LLUICtrlFactory::getScrollingPanelList(LLPanel* panelp, co
return (LLScrollingPanelList*)panelp->getCtrlByNameAndType(name, WIDGET_TYPE_SCROLLING_PANEL_LIST);
}
+
+LLCtrlListInterface* LLUICtrlFactory::getListInterfaceByName(LLPanel* panelp, const LLString& name)
+{
+ LLView* viewp = panelp->getCtrlByNameAndType(name, WIDGET_TYPE_DONTCARE);
+ if (viewp && viewp->isCtrl())
+ {
+ return ((LLUICtrl*)viewp)->getListInterface();
+ }
+ return NULL;
+}
+
+LLCtrlSelectionInterface* LLUICtrlFactory::getSelectionInterfaceByName(LLPanel* panelp, const LLString& name)
+{
+ LLView* viewp = panelp->getCtrlByNameAndType(name, WIDGET_TYPE_DONTCARE);
+ if (viewp && viewp->isCtrl())
+ {
+ return ((LLUICtrl*)viewp)->getSelectionInterface();
+ }
+ return NULL;
+}
+
+LLCtrlScrollInterface* LLUICtrlFactory::getScrollInterfaceByName(LLPanel* panelp, const LLString& name)
+{
+ LLView* viewp = panelp->getCtrlByNameAndType(name, WIDGET_TYPE_DONTCARE);
+ if (viewp && viewp->isCtrl())
+ {
+ return ((LLUICtrl*)viewp)->getScrollInterface();
+ }
+ return NULL;
+}
+
void LLUICtrlFactory::registerCreator(LLString ctrlname, creator_function_t function)
{
LLString::toLower(ctrlname);
diff --git a/linden/indra/llui/lluictrlfactory.h b/linden/indra/llui/lluictrlfactory.h
index eaae754..e12017d 100644
--- a/linden/indra/llui/lluictrlfactory.h
+++ b/linden/indra/llui/lluictrlfactory.h
@@ -65,6 +65,9 @@ class LLWebBrowserCtrl;
class LLViewBorder;
class LLColorSwatchCtrl;
class LLScrollingPanelList;
+class LLCtrlListInterface;
+class LLCtrlSelectionInterface;
+class LLCtrlScrollInterface;
// Widget
@@ -123,6 +126,11 @@ public:
static LLMenuItemCallGL* getMenuItemCallByName(LLPanel* panelp, const LLString& name);
static LLScrollingPanelList* getScrollingPanelList(LLPanel* panelp, const LLString& name);
+ // interface getters
+ static LLCtrlListInterface* getListInterfaceByName(LLPanel* panelp, const LLString& name);
+ static LLCtrlSelectionInterface* getSelectionInterfaceByName(LLPanel* panelp, const LLString& name);
+ static LLCtrlScrollInterface* getScrollInterfaceByName(LLPanel* panelp, const LLString& name);
+
LLPanel* createFactoryPanel(LLString name);
virtual LLView* createCtrlWidget(LLPanel *parent, LLXMLNodePtr node);
diff --git a/linden/indra/llui/lluistring.cpp b/linden/indra/llui/lluistring.cpp
index 49b6fca..cf1b0e0 100644
--- a/linden/indra/llui/lluistring.cpp
+++ b/linden/indra/llui/lluistring.cpp
@@ -30,6 +30,9 @@
#include "lluistring.h"
+const LLString::format_map_t LLUIString::sNullArgs;
+
+
// public
LLUIString::LLUIString(const LLString& instring, const LLString::format_map_t& args)
diff --git a/linden/indra/llui/lluistring.h b/linden/indra/llui/lluistring.h
index 37792aa..c5d9152 100644
--- a/linden/indra/llui/lluistring.h
+++ b/linden/indra/llui/lluistring.h
@@ -95,6 +95,8 @@ public:
void insert(S32 charidx, const LLWString& wchars);
void replace(S32 charidx, llwchar wc);
+ static const LLString::format_map_t sNullArgs;
+
private:
void format();
diff --git a/linden/indra/llui/lluixmltags.h b/linden/indra/llui/lluixmltags.h
index 08c5f67..7728d73 100644
--- a/linden/indra/llui/lluixmltags.h
+++ b/linden/indra/llui/lluixmltags.h
@@ -116,4 +116,5 @@
#define LL_JOYSTICK_SLIDE "joystick_slide"
#define LL_JOYSTICK_TURN "joystick_turn"
#define LL_GROUP_DROP_TARGET_TAG "group_drop_target"
+#define LL_LAYOUT_STACK_TAG "layout_stack"
#endif
diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp
index 0b04213..2a62602 100644
--- a/linden/indra/llui/llview.cpp
+++ b/linden/indra/llui/llview.cpp
@@ -325,6 +325,10 @@ void LLView::moveChildToFrontOfTabGroup(LLUICtrl* child)
void LLView::addChild(LLView* child, S32 tab_group)
{
+ if (mParentView == child)
+ {
+ llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
+ }
// remove from current parent
if (child->mParentView)
{
@@ -348,6 +352,10 @@ void LLView::addChild(LLView* child, S32 tab_group)
void LLView::addChildAtEnd(LLView* child, S32 tab_group)
{
+ if (mParentView == child)
+ {
+ llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
+ }
// remove from current parent
if (child->mParentView)
{
@@ -752,18 +760,22 @@ void LLView::setEnabled(BOOL enabled)
// virtual
void LLView::setVisible(BOOL visible)
{
- if( !visible && (gFocusMgr.getTopCtrl() == this) )
- {
- gFocusMgr.setTopCtrl( NULL );
- }
-
if ( mVisible != visible )
{
- // tell all children of this view that the visibility may have changed
- onVisibilityChange ( visible );
- }
+ if( !visible && (gFocusMgr.getTopCtrl() == this) )
+ {
+ gFocusMgr.setTopCtrl( NULL );
+ }
- mVisible = visible;
+ mVisible = visible;
+
+ // notify children of visibility change if root, or part of visible hierarchy
+ if (!getParent() || getParent()->isInVisibleChain())
+ {
+ // tell all children of this view that the visibility may have changed
+ onVisibilityChange( visible );
+ }
+ }
}
// virtual
@@ -778,7 +790,7 @@ BOOL LLView::setLabelArg(const LLString& key, const LLString& text)
return FALSE;
}
-void LLView::onVisibilityChange ( BOOL curVisibilityIn )
+void LLView::onVisibilityChange ( BOOL new_visibility )
{
for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
@@ -786,7 +798,7 @@ void LLView::onVisibilityChange ( BOOL curVisibilityIn )
// only views that are themselves visible will have their overall visibility affected by their ancestors
if (viewp->getVisible())
{
- viewp->onVisibilityChange ( curVisibilityIn );
+ viewp->onVisibilityChange ( new_visibility );
}
}
}
@@ -1390,64 +1402,61 @@ LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
void LLView::draw()
{
- if (getVisible())
+ if (sDebugRects)
{
- if (sDebugRects)
- {
- drawDebugRect();
+ drawDebugRect();
- // Check for bogus rectangle
- if (mRect.mRight <= mRect.mLeft
- || mRect.mTop <= mRect.mBottom)
- {
- llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
- }
+ // Check for bogus rectangle
+ if (mRect.mRight <= mRect.mLeft
+ || mRect.mTop <= mRect.mBottom)
+ {
+ llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
}
+ }
- LLRect rootRect = getRootView()->getRect();
- LLRect screenRect;
+ LLRect rootRect = getRootView()->getRect();
+ LLRect screenRect;
- // draw focused control on top of everything else
- LLView* focus_view = gFocusMgr.getKeyboardFocus();
- if (focus_view && focus_view->getParent() != this)
- {
- focus_view = NULL;
- }
+ // draw focused control on top of everything else
+ LLView* focus_view = gFocusMgr.getKeyboardFocus();
+ if (focus_view && focus_view->getParent() != this)
+ {
+ focus_view = NULL;
+ }
- for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
- {
- LLView *viewp = *child_iter;
- ++sDepth;
+ for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
+ {
+ LLView *viewp = *child_iter;
+ ++sDepth;
- if (viewp->getVisible() && viewp != focus_view)
+ if (viewp->getVisible() && viewp != focus_view)
+ {
+ // Only draw views that are within the root view
+ localRectToScreen(viewp->getRect(),&screenRect);
+ if ( rootRect.rectInRect(&screenRect) )
{
- // Only draw views that are within the root view
- localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect.rectInRect(&screenRect) )
+ glMatrixMode(GL_MODELVIEW);
+ LLUI::pushMatrix();
{
- glMatrixMode(GL_MODELVIEW);
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
- viewp->draw();
- }
- LLUI::popMatrix();
+ LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
+ viewp->draw();
}
+ LLUI::popMatrix();
}
-
- --sDepth;
}
- if (focus_view && focus_view->getVisible())
- {
- drawChild(focus_view);
- }
+ --sDepth;
+ }
- // HACK
- if (sEditingUI && this == sEditingUIView)
- {
- drawDebugRect();
- }
+ if (focus_view && focus_view->getVisible())
+ {
+ drawChild(focus_view);
+ }
+
+ // HACK
+ if (sEditingUI && this == sEditingUIView)
+ {
+ drawDebugRect();
}
}
@@ -1500,13 +1509,13 @@ void LLView::drawDebugRect()
}
}
-void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset)
+void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_draw)
{
if (childp && childp->getParent() == this)
{
++sDepth;
- if (childp->getVisible())
+ if (childp->getVisible() || force_draw)
{
glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
@@ -1636,7 +1645,7 @@ void LLView::updateRect()
LLView* viewp = *child_it;
if (viewp->getVisible())
{
- child_spanning_rect |= viewp->mRect;
+ child_spanning_rect.unionWith(viewp->mRect);
}
}
diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h
index c7664eb..053ef82 100644
--- a/linden/indra/llui/llview.h
+++ b/linden/indra/llui/llview.h
@@ -379,7 +379,7 @@ public:
virtual void draw();
void drawDebugRect();
- void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0);
+ void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);
virtual const LLString& getName() const;
diff --git a/linden/indra/llvfs/files.sunos5.lst b/linden/indra/llvfs/files.sunos5.lst
new file mode 100644
index 0000000..f1b74d8
--- /dev/null
+++ b/linden/indra/llvfs/files.sunos5.lst
@@ -0,0 +1 @@
+llvfs/lldir_solaris.cpp
diff --git a/linden/indra/llvfs/lldir.cpp b/linden/indra/llvfs/lldir.cpp
index d71224a..5f0efbe 100644
--- a/linden/indra/llvfs/lldir.cpp
+++ b/linden/indra/llvfs/lldir.cpp
@@ -45,6 +45,9 @@ LLDir_Win32 gDirUtil;
#elif LL_DARWIN
#include "lldir_mac.h"
LLDir_Mac gDirUtil;
+#elif LL_SOLARIS
+#include "lldir_solaris.h"
+LLDir_Solaris gDirUtil;
#else
#include "lldir_linux.h"
LLDir_Linux gDirUtil;
diff --git a/linden/indra/llvfs/lldir_linux.cpp b/linden/indra/llvfs/lldir_linux.cpp
index e3aada6..7cf1c2a 100644
--- a/linden/indra/llvfs/lldir_linux.cpp
+++ b/linden/indra/llvfs/lldir_linux.cpp
@@ -75,7 +75,16 @@ LLDir_Linux::LLDir_Linux()
mDirp = NULL;
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
- getcwd(tmp_str, LL_MAX_PATH);
+ if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
+ {
+ strcpy(tmp_str, "/tmp");
+ llwarns << "Could not get current directory; changing to "
+ << tmp_str << llendl;
+ if (chdir(tmp_str) == -1)
+ {
+ llerrs << "Could not change directory to " << tmp_str << llendl;
+ }
+ }
mExecutableFilename = "";
mExecutablePathAndName = "";
@@ -328,7 +337,11 @@ void LLDir_Linux::getRandomFileInDir(const std::string &dirname, const std::stri
std::string LLDir_Linux::getCurPath()
{
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
- getcwd(tmp_str, LL_MAX_PATH);
+ if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
+ {
+ llwarns << "Could not get current directory" << llendl;
+ tmp_str[0] = '\0';
+ }
return tmp_str;
}
diff --git a/linden/indra/llvfs/lldir_solaris.cpp b/linden/indra/llvfs/lldir_solaris.cpp
new file mode 100644
index 0000000..41262aa
--- /dev/null
+++ b/linden/indra/llvfs/lldir_solaris.cpp
@@ -0,0 +1,374 @@
+/**
+ * @file fmodwrapper.cpp
+ * @brief dummy source file for building a shared library to wrap libfmod.a
+ *
+ * Copyright (c) 2005-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#include "linden_common.h"
+
+#include "lldir_solaris.h"
+#include "llerror.h"
+#include "llrand.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define _STRUCTURED_PROC 1
+#include
+
+static std::string getCurrentUserHome(char* fallback)
+{
+ const uid_t uid = getuid();
+ struct passwd *pw;
+ char *result_cstr = fallback;
+
+ pw = getpwuid(uid);
+ if ((pw != NULL) && (pw->pw_dir != NULL))
+ {
+ result_cstr = (char*) pw->pw_dir;
+ }
+ else
+ {
+ llinfos << "Couldn't detect home directory from passwd - trying $HOME" << llendl;
+ const char *const home_env = getenv("HOME"); /* Flawfinder: ignore */
+ if (home_env)
+ {
+ result_cstr = (char*) home_env;
+ }
+ else
+ {
+ llwarns << "Couldn't detect home directory! Falling back to " << fallback << llendl;
+ }
+ }
+
+ return std::string(result_cstr);
+}
+
+
+LLDir_Solaris::LLDir_Solaris()
+{
+ mDirDelimiter = "/";
+ mCurrentDirIndex = -1;
+ mCurrentDirCount = -1;
+ mDirp = NULL;
+
+ char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
+ getcwd(tmp_str, LL_MAX_PATH);
+
+ mExecutableFilename = "";
+ mExecutablePathAndName = "";
+ mExecutableDir = strdup(tmp_str);
+ mWorkingDir = strdup(tmp_str);
+ mAppRODataDir = strdup(tmp_str);
+ mOSUserDir = getCurrentUserHome(tmp_str);
+ mOSUserAppDir = "";
+ mLindenUserDir = tmp_str;
+
+ char path [LL_MAX_PATH]; /* Flawfinder: ignore */
+
+ sprintf(path, "/proc/%d/psinfo", (int)getpid());
+ int proc_fd = -1;
+ if((proc_fd = open(path, O_RDONLY)) == -1){
+ llwarns << "unable to open " << path << llendl;
+ return;
+ }
+ psinfo_t proc_psinfo;
+ if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
+ llwarns << "Unable to read " << path << llendl;
+ close(proc_fd);
+ return;
+ }
+
+ close(proc_fd);
+
+ mExecutableFilename = strdup(proc_psinfo.pr_fname);
+ llinfos << "mExecutableFilename = [" << mExecutableFilename << "]" << llendl;
+
+ sprintf(path, "/proc/%d/path/a.out", (int)getpid());
+
+ char execpath[LL_MAX_PATH];
+ if(readlink(path, execpath, LL_MAX_PATH) == -1){
+ llwarns << "Unable to read link from " << path << llendl;
+ return;
+ }
+
+ mExecutablePathAndName = strdup(execpath);
+ llinfos << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << llendl;
+
+ // plunk a null at last '/' to get exec dir
+ char *s = execpath + strlen(execpath) -1;
+ while(*s != '/' && s != execpath){
+ --s;
+ }
+
+ if(s != execpath){
+ *s = (char)NULL;
+
+ mExecutableDir = strdup(execpath);
+ llinfos << "mExecutableDir = [" << mExecutableDir << "]" << llendl;
+ }
+
+ // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
+ mTempDir = "/tmp";
+}
+
+LLDir_Solaris::~LLDir_Solaris()
+{
+}
+
+// Implementation
+
+
+void LLDir_Solaris::initAppDirs(const std::string &app_name)
+{
+ mAppName = app_name;
+
+ LLString upper_app_name(app_name);
+ LLString::toUpper(upper_app_name);
+
+ char* app_home_env = getenv((upper_app_name + "_USER_DIR").c_str()); /* Flawfinder: ignore */
+ if (app_home_env)
+ {
+ // user has specified own userappdir i.e. $SECONDLIFE_USER_DIR
+ mOSUserAppDir = app_home_env;
+ }
+ else
+ {
+ // traditionally on unixoids, MyApp gets ~/.myapp dir for data
+ mOSUserAppDir = mOSUserDir;
+ mOSUserAppDir += "/";
+ mOSUserAppDir += ".";
+ LLString lower_app_name(app_name);
+ LLString::toLower(lower_app_name);
+ mOSUserAppDir += lower_app_name;
+ }
+
+ // create any directories we expect to write to.
+
+ int res = LLFile::mkdir(mOSUserAppDir.c_str());
+ if (res == -1)
+ {
+ if (errno != EEXIST)
+ {
+ llwarns << "Couldn't create app user dir " << mOSUserAppDir << llendl;
+ llwarns << "Default to base dir" << mOSUserDir << llendl;
+ mOSUserAppDir = mOSUserDir;
+ }
+ }
+
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,"").c_str());
+ if (res == -1)
+ {
+ if (errno != EEXIST)
+ {
+ llwarns << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << llendl;
+ }
+ }
+
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,"").c_str());
+ if (res == -1)
+ {
+ if (errno != EEXIST)
+ {
+ llwarns << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << llendl;
+ }
+ }
+
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,"").c_str());
+ if (res == -1)
+ {
+ if (errno != EEXIST)
+ {
+ llwarns << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << llendl;
+ }
+ }
+
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"").c_str());
+ if (res == -1)
+ {
+ if (errno != EEXIST)
+ {
+ llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
+ }
+ }
+
+ mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
+}
+
+U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string &mask)
+{
+ U32 file_count = 0;
+ glob_t g;
+
+ std::string tmp_str;
+ tmp_str = dirname;
+ tmp_str += mask;
+
+ if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
+ {
+ file_count = g.gl_pathc;
+
+ globfree(&g);
+ }
+
+ return (file_count);
+}
+
+// get the next file in the directory
+// automatically wrap if we've hit the end
+BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
+{
+ glob_t g;
+ BOOL result = FALSE;
+ fname = "";
+
+ if(!(dirname == mCurrentDir))
+ {
+ // different dir specified, close old search
+ mCurrentDirIndex = -1;
+ mCurrentDirCount = -1;
+ mCurrentDir = dirname;
+ }
+
+ std::string tmp_str;
+ tmp_str = dirname;
+ tmp_str += mask;
+
+ if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
+ {
+ if(g.gl_pathc > 0)
+ {
+ if((int)g.gl_pathc != mCurrentDirCount)
+ {
+ // Number of matches has changed since the last search, meaning a file has been added or deleted.
+ // Reset the index.
+ mCurrentDirIndex = -1;
+ mCurrentDirCount = g.gl_pathc;
+ }
+
+ mCurrentDirIndex++;
+
+ if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
+ {
+ mCurrentDirIndex = 0;
+ }
+
+ if(mCurrentDirIndex < (int)g.gl_pathc)
+ {
+// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
+
+ // The API wants just the filename, not the full path.
+ //fname = g.gl_pathv[mCurrentDirIndex];
+
+ char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/');
+
+ if(s == NULL)
+ s = g.gl_pathv[mCurrentDirIndex];
+ else if(s[0] == '/')
+ s++;
+
+ fname = s;
+
+ result = TRUE;
+ }
+ }
+
+ globfree(&g);
+ }
+
+ return(result);
+}
+
+
+// get a random file in the directory
+// automatically wrap if we've hit the end
+void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
+{
+ S32 num_files;
+ S32 which_file;
+ DIR *dirp;
+ dirent *entryp = NULL;
+
+ fname = "";
+
+ num_files = countFilesInDir(dirname,mask);
+ if (!num_files)
+ {
+ return;
+ }
+
+ which_file = ll_rand(num_files);
+
+// llinfos << "Random select file #" << which_file << llendl;
+
+ // which_file now indicates the (zero-based) index to which file to play
+
+ if (!((dirp = opendir(dirname.c_str()))))
+ {
+ while (which_file--)
+ {
+ if (!((entryp = readdir(dirp))))
+ {
+ return;
+ }
+ }
+
+ if ((!which_file) && entryp)
+ {
+ fname = entryp->d_name;
+ }
+
+ closedir(dirp);
+ }
+}
+
+std::string LLDir_Solaris::getCurPath()
+{
+ char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
+ getcwd(tmp_str, LL_MAX_PATH);
+ return tmp_str;
+}
+
+
+BOOL LLDir_Solaris::fileExists(const std::string &filename)
+{
+ struct stat stat_data;
+ // Check the age of the file
+ // Now, we see if the files we've gathered are recent...
+ int res = stat(filename.c_str(), &stat_data);
+ if (!res)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
diff --git a/linden/indra/llvfs/lldir_solaris.h b/linden/indra/llvfs/lldir_solaris.h
new file mode 100644
index 0000000..4a8feed
--- /dev/null
+++ b/linden/indra/llvfs/lldir_solaris.h
@@ -0,0 +1,61 @@
+/**
+ * @file fmodwrapper.cpp
+ * @brief dummy source file for building a shared library to wrap libfmod.a
+ *
+ * Copyright (c) 2005-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ */
+
+#ifndef LL_LLDIR_SOLARIS_H
+#define LL_LLDIR_SOLARIS_H
+
+#include "lldir.h"
+
+#include
+#include
+#include
+
+class LLDir_Solaris : public LLDir
+{
+public:
+ LLDir_Solaris();
+ virtual ~LLDir_Solaris();
+
+ virtual void initAppDirs(const std::string &app_name);
+public:
+ virtual std::string getCurPath();
+ virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
+ virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
+ virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
+ /*virtual*/ BOOL fileExists(const std::string &filename);
+
+private:
+ DIR *mDirp;
+ int mCurrentDirIndex;
+ int mCurrentDirCount;
+ std::string mCurrentDir;
+};
+
+#endif // LL_LLDIR_SOLARIS_H
+
+
diff --git a/linden/indra/llvfs/llvfs.cpp b/linden/indra/llvfs/llvfs.cpp
index dd5854c..a05d1b9 100644
--- a/linden/indra/llvfs/llvfs.cpp
+++ b/linden/indra/llvfs/llvfs.cpp
@@ -35,6 +35,10 @@
#include