Merge branch 'master' of https://vcs.firestormviewer.org/phoenix-firestorm
# Conflicts: # indra/newview/llviewermenu.cppmaster
commit
455b750cde
|
|
@ -111,3 +111,5 @@ compile_commands.json
|
|||
# ignore tracy for now
|
||||
indra/tracy
|
||||
firestorm.code-workspace
|
||||
|
||||
.cache/clangd/index/
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ build_Linux_Doxygen = true
|
|||
# Need viewer-build-variables as well as other shared repositories
|
||||
buildscripts_shared_more_NAMEs="build_secrets build_variables git_hooks"
|
||||
|
||||
# Python 3 / SL-15742
|
||||
BUILDSCRIPTS_PY3 = "true"
|
||||
|
||||
################################################################
|
||||
#### Examples of how to set the viewer_channel ####
|
||||
#
|
||||
|
|
@ -36,6 +39,7 @@ buildscripts_shared_more_NAMEs="build_secrets build_variables git_hooks"
|
|||
################################################################
|
||||
viewer_channel = "Second Life Test"
|
||||
|
||||
|
||||
################################################################
|
||||
# Special packaging parameters.
|
||||
# These parameters can be used to create additional packages
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
First, make sure gcc-5.4 and g++-5.4 are installed.
|
||||
First, make sure gcc-7.5.0 and g++-7.5.0 are installed.
|
||||
|
||||
If you want to use licensed FMOD or KDU build libraries (they are optional) you have to provision these yourself.
|
||||
If you're licensing these with Phoenix/Firestorm, ask for the libraries for fmod and kdu. Put them into:
|
||||
|
|
@ -27,6 +27,12 @@ Other examples:
|
|||
autobuild build -A64 -c ReleaseFS --no-configure -- --clean # Clean rebuild
|
||||
autobuild build -A64 -c ReleaseFS -- --package # Complete a build and package it into a tarball
|
||||
|
||||
When using the --package switch you can set the XZ_DEFAULTS variable to -T0 to use all available CPU cores
|
||||
to create the .tar.xz file. This can significantly reduce the time needed to create the archive, but it will
|
||||
use a lot more memory. For example:
|
||||
export XZ_DEFAULTS="-T0"
|
||||
autobuild build -A64 -c ReleaseFS_open -- --package
|
||||
|
||||
If you want to build with clang you can call autobuild like this:
|
||||
CC=clang CXX=clang++ autobuild configure -A64 -c ReleaseFS
|
||||
|
||||
|
|
|
|||
288
autobuild.xml
288
autobuild.xml
|
|
@ -3,6 +3,118 @@
|
|||
<map>
|
||||
<key>installables</key>
|
||||
<map>
|
||||
<key>gstreamer10</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/></string>
|
||||
<key>license</key>
|
||||
<string>LGPL</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/gstreamer.txt</string>
|
||||
<key>name</key>
|
||||
<string>gstreamer10</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>01f39ecf80dae64e30402ac384035b3e</string>
|
||||
<key>url</key>
|
||||
<string>http://downloads.phoenixviewer.com/gstreamer10-1.6.3.201605191852-linux-201605191852.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>0.10.6.294903</string>
|
||||
</map>
|
||||
<key>breakpad</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) google</string>
|
||||
<key>license</key>
|
||||
<string>BSD</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/google_breakpad.txt</string>
|
||||
<key>name</key>
|
||||
<string>breakpad</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>482c2b25bbfd25edc058a02f82da39b2</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/breakpad-4708e6fb-linux64_bionic-220392253.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.48.0</string>
|
||||
</map>
|
||||
<key>glib</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) glib project</string>
|
||||
<key>license</key>
|
||||
<string>LGPL</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/glib.txt</string>
|
||||
<key>name</key>
|
||||
<string>glib</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9c93ba8b8af97fc8379f77de77e1540a</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/glib-2.48.0.202301938-linux64-202301938.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.48.0</string>
|
||||
</map>
|
||||
<key>fltk</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) fltk project</string>
|
||||
<key>license</key>
|
||||
<string>LGPL/fltk</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/fltk.txt</string>
|
||||
<key>name</key>
|
||||
<string>fltk</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>81fe1e927e4fe3c5e5f15ce6219ca883</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/fltk-1.3.5.202282121-linux64-202282121.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.3.5</string>
|
||||
</map>
|
||||
<key>jemalloc</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
@ -424,9 +536,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>29eb0d338020242454b77b278c11d3e7</string>
|
||||
<string>401f317fbb67623c97a7b9d8b6627ef1</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/boost-1.72-linux64-202021511.tar.bz2</string>
|
||||
<string>http://3p.firestormviewer.org/boost-1.72-linux64_bionic-220402045.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -549,26 +661,14 @@
|
|||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>d83896f28716f34b7b49d61a23283c4c</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/colladadom-2.3.180871403-linux-180871403.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>df6fe4c80b96ec20b5ee6f56419e6b9f</string>
|
||||
<string>88ee58d6548deae6c306f125b6461d61</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/colladadom-2.3.202021526-linux64-202021526.tar.bz2</string>
|
||||
<string>http://3p.firestormviewer.org/colladadom-2.3.220402056-linux64_bionic-220402056.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -720,9 +820,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>96dd770f246917589b776300a2d07f9e</string>
|
||||
<string>0bcccd248a5e4084af4026eee439816b</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/curl-7.54.1.212891029-linux64-212891029.tar.bz2</string>
|
||||
<string>http://3p.firestormviewer.org/curl-7.81.0.220511906-linux64_bionic-220511906.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -787,48 +887,6 @@
|
|||
<key>version</key>
|
||||
<string>5.1.25</string>
|
||||
</map>
|
||||
<key>dbus_glib</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) Red Hat Inc.</string>
|
||||
<key>description</key>
|
||||
<string>D-Bus bindings for glib</string>
|
||||
<key>license</key>
|
||||
<string>Academic Free License v. 2.1</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/dbus-glib.txt</string>
|
||||
<key>name</key>
|
||||
<string>dbus_glib</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9591dcb7efce2a770d77e907705e1492</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/dbus_glib-0.76-linux-180871236.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>5a685a65a7066937ef580dcd5a90f9dc</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/dbus_glib-0.76-linux64-180841549.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>0.76</string>
|
||||
</map>
|
||||
<key>dictionaries</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
@ -914,9 +972,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2f8fdc6950620cee3a526ede27e068aa</string>
|
||||
<string>8d532edd648448d78e6daa0cc5f821f9</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/dullahan-1.12.2.202109282040_91.1.23_g04c8d56_chromium-91.0.4472.164-linux64-212711840.tar.bz2</string>
|
||||
<string>http://3p.firestormviewer.org/dullahan-1.12.2.202202071031_91.1.23_g04c8d56_chromium-91.0.4472.164-linux64-220380931.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -1058,11 +1116,11 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>bde9eb3e53001584edb1af44e3b265a2</string>
|
||||
<string>2db00aa4126d4ee8152fc49b03bb3fe1</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>file:///opt/firestorm/fmodstudio-2.02.04-darwin-213491614.tar.bz2</string>
|
||||
<string>file:///opt/firestorm/fmodstudio-2.02.05-darwin-220160006.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin</string>
|
||||
|
|
@ -1577,46 +1635,6 @@
|
|||
<key>version</key>
|
||||
<string>0.10.6.314267</string>
|
||||
</map>
|
||||
<key>gtk-atk-pango-glib</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (various, see sources)</string>
|
||||
<key>license</key>
|
||||
<string>lgpl</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/gtk-atk-pango-glib.txt</string>
|
||||
<key>name</key>
|
||||
<string>gtk-atk-pango-glib</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>fb047d496c32cc3b9f99793ee6ebb1e3</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/gtk_atk_pango_glib-2.1-linux-180871647.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>d918d894430c1d1d869b9f2e06570c65</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/gtk_atk_pango_glib-2.1-linux64-180841902.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.1</string>
|
||||
</map>
|
||||
<key>havok-source</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
@ -2443,18 +2461,18 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>35f42f538f4dc3abdfc2b2c4a915d004</string>
|
||||
<string>95cb09a712b7b61e992fe68ab7bf8c72</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87228/802959/llca-202109010216.563493-common-563493.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/92744/837149/llca-202201010217.567162-common-567162.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>common</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>202109010216.563493</string>
|
||||
<string>202201010217.567162</string>
|
||||
</map>
|
||||
<key>llphysicsextensions_source</key>
|
||||
<map>
|
||||
|
|
@ -2473,9 +2491,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>14fac452271ebfba37ba5ddcf5bffa54</string>
|
||||
<string>da57838d80cf332f4a3026713a13f086</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54842/510078/llphysicsextensions_source-1.0.538972-darwin64-538972.tar.bz2</string>
|
||||
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/90708/824484/llphysicsextensions_source-1.0.565754-darwin64-565754.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2497,16 +2515,16 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f3c066c1aebed8a6519a3e5ce64b9a3c</string>
|
||||
<string>28ad884012aa0bb70cf4101853af2f9a</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54982/511796/llphysicsextensions_source-1.0.538972-windows-538972.tar.bz2</string>
|
||||
<string>https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/90733/824570/llphysicsextensions_source-1.0.565768-windows-565768.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.0.538972</string>
|
||||
<string>1.0.565768</string>
|
||||
</map>
|
||||
<key>llphysicsextensions_stub</key>
|
||||
<map>
|
||||
|
|
@ -3424,9 +3442,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c42575ac8997de979eadb082c33a578e</string>
|
||||
<string>b97d0f6570104277de92d0d3f2d1111d</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81322/765512/uriparser-0.9.4-darwin64-559132.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89474/816487/uriparser-0.9.4-darwin64-564957.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3460,9 +3478,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>901b1063556fc6b2575e745eef2bf744</string>
|
||||
<string>e2600c798e220cc98c1cc77341aee00d</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81323/765528/uriparser-0.9.4-windows-559132.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89476/816496/uriparser-0.9.4-windows-564957.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3472,9 +3490,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>962c01d553f286c430102998129fb0d6</string>
|
||||
<string>50d857117d31844fc8b84b07b795fd00</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81324/765527/uriparser-0.9.4-windows64-559132.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89475/816497/uriparser-0.9.4-windows64-564957.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -3502,9 +3520,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>a3c8357a2f5a62cd7de43181b02553bc</string>
|
||||
<string>33ed1bb3e24fbd3462da04fb3e917e94</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/91396/829032/viewer_manager-2.0.566227-darwin64-566227.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/94814/850320/viewer_manager-3.0.568552-darwin64-568552.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3538,9 +3556,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>0654b449d9bdf3507664cf5caa67336f</string>
|
||||
<string>2ad8e04965ac8bddb7d351abe09bee07</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/91397/829041/viewer_manager-2.0.566227-windows-566227.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/94813/850316/viewer_manager-3.0.568552-windows-568552.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3551,7 +3569,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>2.0.566227</string>
|
||||
<string>3.0.568552</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
|
|
@ -3577,30 +3595,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9f9582031af3b78d6153ec296d6dde9f</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/vlc_bin-2.2.3-linux-201607071822-r16.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>5eace400c487011a678493fc520be24d</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/vlc_bin-2.2.3-linux-x64-201610182130-r16.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ Beq Janus
|
|||
SL-14766
|
||||
SL-14927
|
||||
SL-11300
|
||||
SL-16021
|
||||
Beth Walcher
|
||||
Bezilon Kasei
|
||||
Biancaluce Robbiani
|
||||
|
|
@ -1113,6 +1114,7 @@ Nicky Dasmijn
|
|||
OPEN-187
|
||||
STORM-1937
|
||||
OPEN-187
|
||||
SL-15234
|
||||
STORM-2010
|
||||
STORM-2082
|
||||
MAINT-6665
|
||||
|
|
@ -1122,6 +1124,7 @@ Nicky Dasmijn
|
|||
SL-11072
|
||||
SL-13141
|
||||
SL-13642
|
||||
SL-16438
|
||||
Nicky Perian
|
||||
OPEN-1
|
||||
STORM-1087
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ if (NOT USE_BUGSPLAT)
|
|||
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
|
||||
endif (NOT USE_BUGSPLAT)
|
||||
|
||||
if( LINUX )
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llui)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
|
||||
|
|
@ -159,6 +163,10 @@ endif (USE_BUGSPLAT)
|
|||
add_subdirectory(${VIEWER_PREFIX}newview)
|
||||
add_dependencies(viewer firestorm-bin)
|
||||
|
||||
set_target_properties(
|
||||
firestorm-bin PROPERTIES
|
||||
VS_DEBUGGER_WORKING_DIRECTORY "..\\..\\indra\\newview")
|
||||
|
||||
add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
|
||||
|
||||
if (LL_TESTS)
|
||||
|
|
|
|||
|
|
@ -165,11 +165,6 @@ endif (WINDOWS)
|
|||
if (LINUX)
|
||||
set(CMAKE_SKIP_RPATH TRUE)
|
||||
|
||||
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0.0 )
|
||||
message( FATAL_ERROR "GCC greater 9.4.0 is not supported. Recompile boost for support of GCC 10.0.0 and up." )
|
||||
endif()
|
||||
|
||||
# <FS:ND/>
|
||||
# And another hack for FORTIFY_SOURCE. Some distributions (for example Gentoo) define FORTIFY_SOURCE by default.
|
||||
# Check if this is the case, if yes, do not define it again.
|
||||
|
|
@ -225,10 +220,6 @@ if (LINUX)
|
|||
endif (NOT USESYSTEMLIBS)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
|
||||
if( NOT (CMAKE_CXX_COMPILER MATCHES ".*clang") )
|
||||
set( CMAKE_CXX_FLAGS "-fabi-version=9 ${CMAKE_CXX_FLAGS}" )
|
||||
endif()
|
||||
endif (LINUX)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,34 +19,23 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
|
|||
message(STATUS "Revision (from autobuild environment): ${VIEWER_VERSION_REVISION}")
|
||||
|
||||
else (DEFINED ENV{revision})
|
||||
find_program(MERCURIAL hg)
|
||||
find_program(SED sed)
|
||||
if (DEFINED MERCURIAL AND DEFINED SED)
|
||||
find_program(GIT git)
|
||||
if (DEFINED GIT )
|
||||
execute_process(
|
||||
# <FS:TS> FIRE-11737: Reverting to old revisions shows tip in build string
|
||||
# This command gets the revision number of the current
|
||||
# repository tip. This leads to confusion when
|
||||
# building an earlier revision. Instead, we use
|
||||
# "hg identify -n" to get the local revision number
|
||||
# of the actual state of the repository.
|
||||
#COMMAND ${MERCURIAL} log -r tip:0 --template '\\n'
|
||||
#COMMAND ${WORDCOUNT} -l
|
||||
#COMMAND ${SED} "s/ //g"
|
||||
COMMAND ${MERCURIAL} identify -n
|
||||
COMMAND ${SED} "s/+//" # [CR] Strip off any + from the revision number
|
||||
COMMAND ${GIT} rev-list --count HEAD
|
||||
OUTPUT_VARIABLE VIEWER_VERSION_REVISION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
|
||||
message(STATUS "Revision (from hg) ${VIEWER_VERSION_REVISION}")
|
||||
message(STATUS "Revision (from git) ${VIEWER_VERSION_REVISION}")
|
||||
else ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
|
||||
message(STATUS "Revision not set (repository not found?); using 0")
|
||||
set(VIEWER_VERSION_REVISION 0 )
|
||||
endif ("${VIEWER_VERSION_REVISION}" MATCHES "^[0-9]+$")
|
||||
else (DEFINED MERCURIAL AND DEFINED SED)
|
||||
message(STATUS "Revision not set: 'hg' or 'sed' not found; using 0")
|
||||
else (DEFINED GIT )
|
||||
message(STATUS "Revision not set: 'git' found; using 0")
|
||||
set(VIEWER_VERSION_REVISION 0)
|
||||
endif (DEFINED MERCURIAL AND DEFINED SED)
|
||||
endif (DEFINED GIT)
|
||||
endif (DEFINED ENV{revision})
|
||||
message(STATUS "Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
|
||||
else ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ set(cmake_SOURCE_FILES
|
|||
ConfigurePkgConfig.cmake
|
||||
CURL.cmake
|
||||
Copy3rdPartyLibs.cmake
|
||||
DBusGlib.cmake
|
||||
GLIB.cmake
|
||||
DeploySharedLibs.cmake
|
||||
Discord.cmake # <FS:LO> Discord rich presence
|
||||
DragDrop.cmake
|
||||
|
|
|
|||
|
|
@ -245,16 +245,9 @@ elseif(LINUX)
|
|||
# have to deal with
|
||||
if (NOT USESYSTEMLIBS)
|
||||
set(release_files
|
||||
#libapr-1.so.0
|
||||
#libaprutil-1.so.0
|
||||
libatk-1.0.so
|
||||
#libdb-5.1.so
|
||||
${EXPAT_COPY}
|
||||
#libfreetype.so.6.6.2
|
||||
#libfreetype.so.6
|
||||
#libGLOD.so
|
||||
libgmodule-2.0.so
|
||||
libgobject-2.0.so
|
||||
libhunspell-1.3.so.0.0.0
|
||||
libopenal.so
|
||||
#libopenjpeg.so
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindPkgConfig)
|
||||
|
||||
pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1)
|
||||
|
||||
elseif (LINUX)
|
||||
use_prebuilt_binary(dbus_glib)
|
||||
set(DBUSGLIB_FOUND ON FORCE BOOL)
|
||||
set(DBUSGLIB_INCLUDE_DIRS
|
||||
${LIBS_PREBUILT_DIR}/include/dbus
|
||||
)
|
||||
# We don't need to explicitly link against dbus-glib itself, because
|
||||
# the viewer probes for the system's copy at runtime.
|
||||
set(DBUSGLIB_LIBRARIES
|
||||
gobject-2.0
|
||||
glib-2.0
|
||||
)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (DBUSGLIB_FOUND)
|
||||
set(DBUSGLIB ON CACHE BOOL "Build with dbus-glib message bus support.")
|
||||
endif (DBUSGLIB_FOUND)
|
||||
|
||||
if (DBUSGLIB)
|
||||
add_definitions(-DLL_DBUS_ENABLED=1)
|
||||
endif (DBUSGLIB)
|
||||
|
|
@ -9,7 +9,11 @@ else (USESYSTEMLIBS)
|
|||
use_prebuilt_binary(freetype)
|
||||
set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
|
||||
set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/freetype2) #<FS:ND/> Also add freetype2 to search dir, or some includes will fail.
|
||||
set(FREETYPE_LIBRARIES freetype)
|
||||
# <FS:ND> Linux links this via UI.cmake
|
||||
if( NOT LINUX )
|
||||
set(FREETYPE_LIBRARIES freetype)
|
||||
endif()
|
||||
# </FS:ND>
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
link_directories(${FREETYPE_LIBRARY_DIRS})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
include(Prebuilt)
|
||||
|
||||
if( LINUX )
|
||||
use_prebuilt_binary(glib)
|
||||
set(GLIB_FOUND ON CACHE BOOL "Build against glib 2")
|
||||
set(GLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/glib-2.0 ${LIBS_PREBUILT_DIR}/lib/release/glib-2.0/include )
|
||||
set(GLIB_LIBRARIES libgobject-2.0.a libglib-2.0.a libffi.a libpcre.a)
|
||||
set(GIO_LIBRARIES libgio-2.0.a libgmodule-2.0.a -lresolv ${GLIB_LIBRARIES} )
|
||||
add_definitions(-DLL_GLIB=1)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
include(GLIB)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindPkgConfig)
|
||||
|
||||
pkg_check_modules(GSTREAMER10 REQUIRED gstreamer-1.0)
|
||||
pkg_check_modules(GSTREAMER10_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0)
|
||||
elseif (LINUX OR WINDOWS)
|
||||
use_prebuilt_binary(gstreamer10)
|
||||
use_prebuilt_binary(libxml2)
|
||||
set(GSTREAMER10_FOUND ON FORCE BOOL)
|
||||
set(GSTREAMER10_PLUGINS_BASE_FOUND ON FORCE BOOL)
|
||||
set(GSTREAMER10_INCLUDE_DIRS
|
||||
${GLIB_INCLUDE_DIRS}
|
||||
${LIBS_PREBUILT_DIR}/include/gstreamer-1.0
|
||||
${LIBS_PREBUILT_DIR}/include/libxml2
|
||||
)
|
||||
# We don't need to explicitly link against gstreamer itself, because
|
||||
# LLMediaImplGStreamer probes for the system's copy at runtime.
|
||||
set(GSTREAMER10_LIBRARIES)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND)
|
||||
set(GSTREAMER10 ON CACHE BOOL "Build with GStreamer-1.0 streaming media support.")
|
||||
endif (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND)
|
||||
|
||||
if (GSTREAMER10)
|
||||
add_definitions(-DLL_GSTREAMER10_ENABLED=1)
|
||||
endif (GSTREAMER10)
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ else (USESYSTEMLIBS)
|
|||
elseif(DARWIN)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3)
|
||||
elseif(LINUX)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3)
|
||||
set(HUNSPELL_LIBRARY libhunspell-1.3.a)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid platform")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,26 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# <FS:ND> Try to find pulse header, if we got them we can use the linux volume catcher
|
||||
if (LINUX)
|
||||
include(GLIB)
|
||||
|
||||
include_directories( ${GLIB_INCLUDE_DIRS} )
|
||||
|
||||
foreach( PULSE_FILE pulse/introspect.h pulse/context.h pulse/subscribe.h pulse/glib-mainloop.h )
|
||||
find_path( PULSE_FILE_${PULSE_FILE}_FOUND ${PULSE_FILE} NO_CACHE)
|
||||
if( NOT PULSE_FILE_${PULSE_FILE}_FOUND )
|
||||
message( "Looking for ${PULSE_FILE} ... not found")
|
||||
message( FATAL_ERROR "Pulse header not found" )
|
||||
else()
|
||||
message( "Looking for ${PULSE_FILE} ... found")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message( "Building with linux volume catcher" )
|
||||
set(LINUX_VOLUME_CATCHER linux_volume_catcher.cpp)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/media_plugins/base/
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@ include(Linking)
|
|||
include(Prebuilt)
|
||||
|
||||
if (LINUX)
|
||||
set(OPENAL ON CACHE BOOL "Enable OpenAL")
|
||||
use_prebuilt_binary(openal) #Always need the .so for voice
|
||||
set(OPENAL OFF CACHE BOOL "Enable OpenAL")
|
||||
else (LINUX)
|
||||
set(OPENAL OFF CACHE BOOL "Enable OpenAL")
|
||||
endif (LINUX)
|
||||
|
||||
if (OPENAL)
|
||||
message( WARNING "Using OpenAL is discouraged due to no maintenance of the viewers openal integration, possible memory leaks and no support for streaming audio. Switch to fmodstudio if possible" )
|
||||
set(OPENAL_LIB_INCLUDE_DIRS "${LIBS_PREBUILT_DIR}/include/AL")
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindPkgConfig)
|
||||
|
|
|
|||
|
|
@ -16,3 +16,21 @@ endif (BUILD_HEADLESS)
|
|||
|
||||
include(FindOpenGL)
|
||||
|
||||
if(LINUX)
|
||||
if( NOT OPENGL_FOUND )
|
||||
message( FATAL_ERROR "OpenGL not found, install mesa-common-dev libgl1-mesa-dev" )
|
||||
endif()
|
||||
|
||||
find_file( GLUH "GL/glu.h" )
|
||||
if( NOT GLUH )
|
||||
message( FATAL_ERROR "GL/glu.h not found, install libglu1-mesa-dev" )
|
||||
endif()
|
||||
find_library( XINERAMA Xinerama )
|
||||
if( NOT XINERAMA )
|
||||
message( FATAL_ERROR "Cannot link with -lXinerame, install libxinerama-dev" )
|
||||
endif()
|
||||
find_library( XRANDR Xrandr)
|
||||
if( NOT XRANDR )
|
||||
message( FATAL_ERROR "Cannot link with -lXrandr, install libxrandr-dev" )
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -14,50 +14,28 @@ if (WINDOWS)
|
|||
)
|
||||
else()
|
||||
find_program(PYTHON_EXECUTABLE
|
||||
NAMES python25.exe python23.exe python.exe
|
||||
NAMES python.exe
|
||||
NO_DEFAULT_PATH # added so that cmake does not find cygwin python
|
||||
PATHS
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.8\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.8\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.8\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.9\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.10\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.11\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.8\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.9\\InstallPath]
|
||||
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.10\\InstallPath]
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.11\\InstallPath]
|
||||
)
|
||||
endif()
|
||||
elseif (EXISTS /etc/debian_version)
|
||||
# On Debian and Ubuntu, avoid Python 2.4 if possible.
|
||||
|
||||
find_program(PYTHON_EXECUTABLE python PATHS /usr/bin)
|
||||
include(FindPythonInterp)
|
||||
else()
|
||||
find_program(PYTHON_EXECUTABLE python3)
|
||||
|
||||
if (PYTHON_EXECUTABLE)
|
||||
set(PYTHONINTERP_FOUND ON)
|
||||
endif (PYTHON_EXECUTABLE)
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# On MAC OS X be sure to search standard locations first
|
||||
|
||||
string(REPLACE ":" ";" PATH_LIST "$ENV{PATH}")
|
||||
find_program(PYTHON_EXECUTABLE
|
||||
NAMES python python25 python24 python23
|
||||
NO_DEFAULT_PATH # Avoid searching non-standard locations first
|
||||
PATHS
|
||||
/bin
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
${PATH_LIST}
|
||||
)
|
||||
|
||||
if (PYTHON_EXECUTABLE)
|
||||
set(PYTHONINTERP_FOUND ON)
|
||||
endif (PYTHON_EXECUTABLE)
|
||||
else (WINDOWS)
|
||||
include(FindPythonInterp)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (NOT PYTHON_EXECUTABLE)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,34 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
include(FreeType)
|
||||
include(GLIB)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindPkgConfig)
|
||||
|
||||
if( NOT GTK_VERSION )
|
||||
set( GTK_VERSION 2.0 )
|
||||
endif()
|
||||
if (LINUX)
|
||||
set(PKGCONFIG_PACKAGES
|
||||
atk
|
||||
cairo
|
||||
gdk-2.0
|
||||
gdk-${GTK_VERSION}
|
||||
gdk-pixbuf-2.0
|
||||
glib-2.0
|
||||
gmodule-2.0
|
||||
gtk+-2.0
|
||||
gtk+-${GTK_VERSION}
|
||||
gthread-2.0
|
||||
libpng
|
||||
pango
|
||||
pangoft2
|
||||
pangox
|
||||
pangoxft
|
||||
sdl
|
||||
sdl2
|
||||
)
|
||||
if( GTK_VERSION LESS "3.0" )
|
||||
LIST( APPEND PKGCONFIG_PACKAGES pangoxft )
|
||||
else()
|
||||
add_definitions( -DGTK_DISABLE_DEPRECATED)
|
||||
endif()
|
||||
endif (LINUX)
|
||||
|
||||
foreach(pkg ${PKGCONFIG_PACKAGES})
|
||||
|
|
@ -31,29 +38,16 @@ if (USESYSTEMLIBS)
|
|||
list(APPEND UI_LIBRARIES ${${pkg}_LIBRARIES})
|
||||
add_definitions(${${pkg}_CFLAGS_OTHERS})
|
||||
endforeach(pkg)
|
||||
list(APPEND UI_LIBRARIES X11)
|
||||
else (USESYSTEMLIBS)
|
||||
if (LINUX)
|
||||
use_prebuilt_binary(gtk-atk-pango-glib)
|
||||
use_prebuilt_binary(fltk)
|
||||
endif (LINUX)
|
||||
|
||||
if (LINUX)
|
||||
set(UI_LIB_NAMES
|
||||
freetype
|
||||
atk-1.0
|
||||
gdk-x11-2.0
|
||||
gdk_pixbuf-2.0
|
||||
glib-2.0
|
||||
gmodule-2.0
|
||||
gobject-2.0
|
||||
gthread-2.0
|
||||
gtk-x11-2.0
|
||||
pango-1.0
|
||||
pangoft2-1.0
|
||||
pangox-1.0
|
||||
#pangoxft-1.0
|
||||
gio-2.0
|
||||
pangocairo-1.0
|
||||
ffi
|
||||
libfltk.a
|
||||
libfreetype.a
|
||||
)
|
||||
|
||||
foreach(libname ${UI_LIB_NAMES})
|
||||
|
|
@ -68,6 +62,7 @@ else (USESYSTEMLIBS)
|
|||
endforeach(libname)
|
||||
|
||||
set(UI_LIBRARIES ${UI_LIBRARIES} Xinerama)
|
||||
include_directories ( ${GLIB_INCLUDE_DIRS} )
|
||||
endif (LINUX)
|
||||
|
||||
include_directories (
|
||||
|
|
@ -80,5 +75,5 @@ else (USESYSTEMLIBS)
|
|||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (LINUX)
|
||||
add_definitions(-DLL_GTK=1 -DLL_X11=1)
|
||||
add_definitions(-DLL_X11=1 -DLL_FLTK=1)
|
||||
endif (LINUX)
|
||||
|
|
|
|||
|
|
@ -12,17 +12,19 @@ endif (INSTALL_PROPRIETARY)
|
|||
if (USE_BUGSPLAT)
|
||||
if (NOT USESYSTEMLIBS)
|
||||
include(Prebuilt)
|
||||
use_prebuilt_binary(bugsplat)
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(bugsplat)
|
||||
set(BUGSPLAT_LIBRARIES
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib
|
||||
)
|
||||
elseif (DARWIN)
|
||||
use_prebuilt_binary(bugsplat)
|
||||
find_library(BUGSPLAT_LIBRARIES BugsplatMac REQUIRED
|
||||
NO_DEFAULT_PATH PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
|
||||
message("Bugsplat for OSX not fully implemented, please adapt llappdelegate-objc.mm to honor options of sending user name and settings.xml.")
|
||||
else (WINDOWS)
|
||||
message(FATAL_ERROR "BugSplat is not supported; add -DUSE_BUGSPLAT=OFF")
|
||||
use_prebuilt_binary(breakpad)
|
||||
set(BUGSPLAT_LIBRARIES ${ARCH_PREBUILT_DIRS_RELEASE}/libbreakpad.a ${ARCH_PREBUILT_DIRS_RELEASE}/libbreakpad_client.a )
|
||||
endif (WINDOWS)
|
||||
else (NOT USESYSTEMLIBS)
|
||||
set(BUGSPLAT_FIND_QUIETLY ON)
|
||||
|
|
@ -32,7 +34,14 @@ if (USE_BUGSPLAT)
|
|||
|
||||
set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name")
|
||||
|
||||
set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat)
|
||||
if( LINUX )
|
||||
set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/breakpad)
|
||||
# <FS:ND/> Sadly we cannot have the nice things yet and need add_definitions for older cmake
|
||||
#add_compile_definitions(__STDC_FORMAT_MACROS)
|
||||
add_definitions(-D__STDC_FORMAT_MACROS)
|
||||
else()
|
||||
set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat)
|
||||
endif()
|
||||
set(BUGSPLAT_DEFINE "LL_BUGSPLAT")
|
||||
endif (USE_BUGSPLAT)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file run_build_test.py
|
||||
@author Nat Goodspeed
|
||||
|
|
@ -17,7 +17,7 @@ line.
|
|||
|
||||
Example:
|
||||
|
||||
python run_build_test.py -DFOO=bar myprog somearg otherarg
|
||||
python3 run_build_test.py -DFOO=bar myprog somearg otherarg
|
||||
|
||||
sets environment variable FOO=bar, then runs:
|
||||
myprog somearg otherarg
|
||||
|
|
@ -47,7 +47,7 @@ $/LicenseInfo$
|
|||
import os
|
||||
import sys
|
||||
import errno
|
||||
import HTMLParser
|
||||
import html.parser
|
||||
import re
|
||||
import signal
|
||||
import subprocess
|
||||
|
|
@ -111,10 +111,10 @@ def main(command, arguments=[], libpath=[], vars={}):
|
|||
# Now handle arbitrary environment variables. The tricky part is ensuring
|
||||
# that all the keys and values we try to pass are actually strings.
|
||||
if vars:
|
||||
for key, value in vars.items():
|
||||
for key, value in list(vars.items()):
|
||||
# As noted a few lines above, facilitate copy-paste rerunning.
|
||||
log.info("%s='%s' \\" % (key, value))
|
||||
os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()]))
|
||||
os.environ.update(dict([(str(key), str(value)) for key, value in vars.items()]))
|
||||
# Run the child process.
|
||||
command_list = [command]
|
||||
command_list.extend(arguments)
|
||||
|
|
@ -194,7 +194,7 @@ def translate_rc(rc):
|
|||
strc = str(rc)
|
||||
return "terminated by signal %s" % strc
|
||||
|
||||
class TableParser(HTMLParser.HTMLParser):
|
||||
class TableParser(html.parser.HTMLParser):
|
||||
"""
|
||||
This HTMLParser subclass is designed to parse the table we know exists
|
||||
in windows-rcs.html, hopefully without building in too much knowledge of
|
||||
|
|
@ -204,9 +204,7 @@ class TableParser(HTMLParser.HTMLParser):
|
|||
whitespace = re.compile(r'\s*$')
|
||||
|
||||
def __init__(self):
|
||||
# Because Python 2.x's HTMLParser is an old-style class, we must use
|
||||
# old-style syntax to forward the __init__() call -- not super().
|
||||
HTMLParser.HTMLParser.__init__(self)
|
||||
super().__init__()
|
||||
# this will collect all the data, eventually
|
||||
self.table = []
|
||||
# Stack whose top (last item) indicates where to append current
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file start-client.py
|
||||
|
||||
|
|
@ -28,12 +28,12 @@ import os
|
|||
import llstart
|
||||
|
||||
def usage():
|
||||
print """start-client.py
|
||||
print("""start-client.py
|
||||
|
||||
--grid <grid>
|
||||
--farm <grid>
|
||||
--region <starting region name>
|
||||
"""
|
||||
""")
|
||||
|
||||
def start_client(grid, slurl, build_config, my_args):
|
||||
login_url = "https://login.%s.lindenlab.com/cgi-bin/login.cgi" % (grid)
|
||||
|
|
@ -42,7 +42,7 @@ def start_client(grid, slurl, build_config, my_args):
|
|||
"--loginuri" : login_url }
|
||||
viewer_args.update(my_args)
|
||||
# *sigh* We must put --url at the end of the argument list.
|
||||
if viewer_args.has_key("--url"):
|
||||
if "--url" in viewer_args:
|
||||
slurl = viewer_args["--url"]
|
||||
del(viewer_args["--url"])
|
||||
viewer_args = llstart.get_args_from_dict(viewer_args)
|
||||
|
|
@ -54,7 +54,7 @@ def start_client(grid, slurl, build_config, my_args):
|
|||
# but the exe is at indra/build-<xxx>/newview/<target>
|
||||
build_path = os.path.dirname(os.getcwd());
|
||||
f = open("start-client.log", "w")
|
||||
print >>f, "Viewer startup arguments:"
|
||||
print("Viewer startup arguments:", file=f)
|
||||
llstart.start("viewer", "../../newview",
|
||||
"%s/newview/%s/firestorm-bin.exe" % (build_path, build_config),
|
||||
viewer_args, f)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# other commands to guarantee full compatibility
|
||||
# with the version specified
|
||||
## prior to 2.8, the add_custom_target commands used in setting the version did not work correctly
|
||||
cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
|
||||
|
||||
set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING
|
||||
"The root project/makefile/solution name. Defaults to SecondLife.")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
##
|
||||
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
## Second Life Viewer Source Code
|
||||
|
|
@ -27,7 +27,7 @@ import glob
|
|||
|
||||
def delete_file_types(path, filetypes):
|
||||
if os.path.exists(path):
|
||||
print 'Cleaning: ' + path
|
||||
print('Cleaning: ' + path)
|
||||
orig_dir = os.getcwd();
|
||||
os.chdir(path)
|
||||
filelist = []
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ THE SOFTWARE.
|
|||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
from compatibility import Incompatible, Older, Newer, Same
|
||||
from tokenstream import TokenStream
|
||||
from .compatibility import Incompatible, Older, Newer, Same
|
||||
from .tokenstream import TokenStream
|
||||
|
||||
###
|
||||
### Message Template
|
||||
|
|
@ -42,8 +42,8 @@ class Template:
|
|||
|
||||
def compatibleWithBase(self, base):
|
||||
messagenames = (
|
||||
frozenset(self.messages.keys())
|
||||
| frozenset(base.messages.keys())
|
||||
frozenset(list(self.messages.keys()))
|
||||
| frozenset(list(base.messages.keys()))
|
||||
)
|
||||
|
||||
compatibility = Same()
|
||||
|
|
@ -142,7 +142,7 @@ class Message:
|
|||
baselen = len(base.blocks)
|
||||
samelen = min(selflen, baselen)
|
||||
|
||||
for i in xrange(0, samelen):
|
||||
for i in range(0, samelen):
|
||||
selfblock = self.blocks[i]
|
||||
baseblock = base.blocks[i]
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ class Block(object):
|
|||
selflen = len(self.variables)
|
||||
baselen = len(base.variables)
|
||||
|
||||
for i in xrange(0, min(selflen, baselen)):
|
||||
for i in range(0, min(selflen, baselen)):
|
||||
selfvar = self.variables[i]
|
||||
basevar = base.variables[i]
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class ParseError(Exception):
|
|||
return "line %d: %s @ ... %s" % (
|
||||
self.line, self.reason, self._contextString())
|
||||
|
||||
def __nonzero__(self):
|
||||
def __bool__(self):
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ $/LicenseInfo$
|
|||
"""
|
||||
|
||||
from collections import namedtuple, defaultdict
|
||||
import commands
|
||||
import subprocess
|
||||
import errno
|
||||
import filecmp
|
||||
import fnmatch
|
||||
|
|
@ -85,6 +85,7 @@ def proper_windows_path(path, current_platform = sys.platform):
|
|||
def get_default_platform(dummy):
|
||||
return {'linux2':'linux',
|
||||
'linux1':'linux',
|
||||
'linux':'linux',
|
||||
'cygwin':'windows',
|
||||
'win32':'windows',
|
||||
'darwin':'darwin'
|
||||
|
|
@ -164,20 +165,20 @@ BASE_ARGUMENTS=[
|
|||
|
||||
def usage(arguments, srctree=""):
|
||||
nd = {'name':sys.argv[0]}
|
||||
print """Usage:
|
||||
print("""Usage:
|
||||
%(name)s [options] [destdir]
|
||||
Options:
|
||||
""" % nd
|
||||
""" % 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" % (
|
||||
print("\t--%s Default: %s\n\t%s\n" % (
|
||||
arg['name'],
|
||||
default,
|
||||
arg['description'] % nd)
|
||||
arg['description'] % nd))
|
||||
|
||||
def main(extra=[]):
|
||||
## print ' '.join((("'%s'" % item) if ' ' in item else item)
|
||||
|
|
@ -202,10 +203,10 @@ def main(extra=[]):
|
|||
for k in 'artwork build dest source'.split():
|
||||
args[k] = os.path.normpath(args[k])
|
||||
|
||||
print "Source tree:", args['source']
|
||||
print "Artwork tree:", args['artwork']
|
||||
print "Build tree:", args['build']
|
||||
print "Destination tree:", args['dest']
|
||||
print("Source tree:", args['source'])
|
||||
print("Artwork tree:", args['artwork'])
|
||||
print("Build tree:", args['build'])
|
||||
print("Destination tree:", args['dest'])
|
||||
|
||||
# early out for help
|
||||
if 'help' in args:
|
||||
|
|
@ -228,7 +229,7 @@ def main(extra=[]):
|
|||
vf = open(args['versionfile'], 'r')
|
||||
args['version'] = vf.read().strip().split('.')
|
||||
except:
|
||||
print "Unable to read versionfile '%s'" % args['versionfile']
|
||||
print("Unable to read versionfile '%s'" % args['versionfile'])
|
||||
# <FS:ND> This will break copy_w_viewer_manifest on Windows 32 and 64 bit builds, the versionfile will not create until the firestorm project.
|
||||
# As copy_w_viewer_manifest does not seem to need the version attribute, we supress the exception for now.
|
||||
# raise
|
||||
|
|
@ -242,7 +243,7 @@ def main(extra=[]):
|
|||
|
||||
# debugging
|
||||
for opt in args:
|
||||
print "Option:", opt, "=", args[opt]
|
||||
print("Option:", opt, "=", args[opt])
|
||||
|
||||
# pass in sourceid as an argument now instead of an environment variable
|
||||
args['sourceid'] = os.environ.get("sourceid", "")
|
||||
|
|
@ -250,18 +251,18 @@ def main(extra=[]):
|
|||
# Build base package.
|
||||
touch = args.get('touch')
|
||||
if touch:
|
||||
print '================ Creating base package'
|
||||
print('================ Creating base package')
|
||||
else:
|
||||
print '================ Starting base copy'
|
||||
print('================ Starting base copy')
|
||||
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
|
||||
wm.do(*args['actions'])
|
||||
# Store package file for later if making touched file.
|
||||
base_package_file = ""
|
||||
if touch:
|
||||
print '================ Created base package ', wm.package_file
|
||||
print('================ Created base package ', wm.package_file)
|
||||
base_package_file = "" + wm.package_file
|
||||
else:
|
||||
print '================ Finished base copy'
|
||||
print('================ Finished base copy')
|
||||
|
||||
# handle multiple packages if set
|
||||
# ''.split() produces empty list
|
||||
|
|
@ -288,26 +289,26 @@ def main(extra=[]):
|
|||
args['sourceid'] = os.environ.get(package_id + "_sourceid")
|
||||
args['dest'] = base_dest_template.format(package_id)
|
||||
if touch:
|
||||
print '================ Creating additional package for "', package_id, '" in ', args['dest']
|
||||
print('================ Creating additional package for "', package_id, '" in ', args['dest'])
|
||||
else:
|
||||
print '================ Starting additional copy for "', package_id, '" in ', args['dest']
|
||||
print('================ Starting additional copy for "', package_id, '" in ', args['dest'])
|
||||
try:
|
||||
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
|
||||
wm.do(*args['actions'])
|
||||
except Exception as err:
|
||||
sys.exit(str(err))
|
||||
if touch:
|
||||
print '================ Created additional package ', wm.package_file, ' for ', package_id
|
||||
print('================ Created additional package ', wm.package_file, ' for ', package_id)
|
||||
with open(base_touch_template.format(package_id), 'w') as fp:
|
||||
fp.write('set package_file=%s\n' % wm.package_file)
|
||||
else:
|
||||
print '================ Finished additional copy "', package_id, '" in ', args['dest']
|
||||
print('================ Finished additional copy "', package_id, '" in ', args['dest'])
|
||||
# Write out the package file in this format, so that it can easily be called
|
||||
# and used in a .bat file - yeah, it sucks, but this is the simplest...
|
||||
if touch:
|
||||
with open(touch, 'w') as fp:
|
||||
fp.write('set package_file=%s\n' % base_package_file)
|
||||
print 'touched', touch
|
||||
print('touched', touch)
|
||||
return 0
|
||||
|
||||
class LLManifestRegistry(type):
|
||||
|
|
@ -319,8 +320,7 @@ class LLManifestRegistry(type):
|
|||
|
||||
MissingFile = namedtuple("MissingFile", ("pattern", "tried"))
|
||||
|
||||
class LLManifest(object):
|
||||
__metaclass__ = LLManifestRegistry
|
||||
class LLManifest(object, metaclass=LLManifestRegistry):
|
||||
manifests = {}
|
||||
def for_platform(self, platform, arch = None):
|
||||
if arch:
|
||||
|
|
@ -412,8 +412,8 @@ class LLManifest(object):
|
|||
def display_stacks(self):
|
||||
width = 1 + max(len(stack) for stack in self.PrefixManager.stacks)
|
||||
for stack in self.PrefixManager.stacks:
|
||||
print "{} {}".format((stack + ':').ljust(width),
|
||||
os.path.join(*getattr(self, stack)))
|
||||
print("{} {}".format((stack + ':').ljust(width),
|
||||
os.path.join(*getattr(self, stack))))
|
||||
|
||||
class PrefixManager(object):
|
||||
# stack attributes we manage in this LLManifest (sub)class
|
||||
|
|
@ -430,7 +430,7 @@ class LLManifest(object):
|
|||
self.prevlen = { stack: len(getattr(self.manifest, stack)) - 1
|
||||
for stack in self.stacks }
|
||||
|
||||
def __nonzero__(self):
|
||||
def __bool__(self):
|
||||
# If the caller wrote:
|
||||
# if self.prefix(...):
|
||||
# then a value of this class had better evaluate as 'True'.
|
||||
|
|
@ -456,7 +456,7 @@ class LLManifest(object):
|
|||
# if we restore the length of each stack to what it was before the
|
||||
# current prefix() block, it doesn't matter whether end_prefix()
|
||||
# was called or not.
|
||||
for stack, prevlen in self.prevlen.items():
|
||||
for stack, prevlen in list(self.prevlen.items()):
|
||||
# find the attribute in 'self.manifest' named by 'stack', and
|
||||
# truncate that list back to 'prevlen'
|
||||
del getattr(self.manifest, stack)[prevlen:]
|
||||
|
|
@ -475,7 +475,7 @@ class LLManifest(object):
|
|||
build = self.build_prefix.pop()
|
||||
dst = self.dst_prefix.pop()
|
||||
if descr and not(src == descr or build == descr or dst == descr):
|
||||
raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'"
|
||||
raise ValueError("End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'")
|
||||
|
||||
def get_src_prefix(self):
|
||||
""" Returns the current source prefix."""
|
||||
|
|
@ -542,7 +542,7 @@ class LLManifest(object):
|
|||
Runs an external command.
|
||||
Raises ManifestError exception if the command returns a nonzero status.
|
||||
"""
|
||||
print "Running command:", command
|
||||
print("Running command:", command)
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
subprocess.check_call(command)
|
||||
|
|
@ -556,7 +556,7 @@ class LLManifest(object):
|
|||
Runs an external command.
|
||||
Raises ManifestError exception if the command returns a nonzero status.
|
||||
"""
|
||||
print "Running command:", command
|
||||
print("Running command:", command)
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
subprocess.check_call(command, shell=True)
|
||||
|
|
@ -570,18 +570,15 @@ class LLManifest(object):
|
|||
a) verify that you really have created it
|
||||
b) schedule it for cleanup"""
|
||||
if not os.path.exists(path):
|
||||
raise ManifestError, "Should be something at path " + path
|
||||
raise ManifestError("Should be something at path " + path)
|
||||
self.created_paths.append(path)
|
||||
|
||||
def put_in_file(self, contents, dst, src=None):
|
||||
# write contents as dst
|
||||
dst_path = self.dst_path_of(dst)
|
||||
self.cmakedirs(os.path.dirname(dst_path))
|
||||
f = open(dst_path, "wb")
|
||||
try:
|
||||
with open(dst_path, 'wb') as f:
|
||||
f.write(contents)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
# Why would we create a file in the destination tree if not to include
|
||||
# it in the installer? The default src=None (plus the fact that the
|
||||
|
|
@ -594,13 +591,12 @@ class LLManifest(object):
|
|||
if dst == None:
|
||||
dst = src
|
||||
# read src
|
||||
f = open(self.src_path_of(src), "rbU")
|
||||
contents = f.read()
|
||||
f.close()
|
||||
with open(self.src_path_of(src), "r") as f:
|
||||
contents = f.read()
|
||||
# apply dict replacements
|
||||
for old, new in searchdict.iteritems():
|
||||
for old, new in searchdict.items():
|
||||
contents = contents.replace(old, new)
|
||||
self.put_in_file(contents, dst)
|
||||
self.put_in_file(contents.encode(), dst)
|
||||
self.created_paths.append(dst)
|
||||
|
||||
def copy_action(self, src, dst):
|
||||
|
|
@ -610,7 +606,7 @@ class LLManifest(object):
|
|||
self.created_paths.append(dst)
|
||||
self.ccopymumble(src, dst)
|
||||
else:
|
||||
print "Doesn't exist:", src
|
||||
print("Doesn't exist:", src)
|
||||
|
||||
def package_action(self, src, dst):
|
||||
pass
|
||||
|
|
@ -628,8 +624,8 @@ class LLManifest(object):
|
|||
# file error until all were resolved. This way permits the developer
|
||||
# to resolve them all at once.
|
||||
if self.missing:
|
||||
print '*' * 72
|
||||
print "Missing files:"
|
||||
print('*' * 72)
|
||||
print("Missing files:")
|
||||
# Instead of just dumping each missing file and all the places we
|
||||
# looked for it, group by common sets of places we looked. Use a
|
||||
# set to store the 'tried' directories, to avoid mismatches due to
|
||||
|
|
@ -640,13 +636,13 @@ class LLManifest(object):
|
|||
organize[frozenset(missingfile.tried)].add(missingfile.pattern)
|
||||
# Now dump all the patterns sought in each group of 'tried'
|
||||
# directories.
|
||||
for tried, patterns in organize.items():
|
||||
print " Could not find in:"
|
||||
for tried, patterns in list(organize.items()):
|
||||
print(" Could not find in:")
|
||||
for dir in sorted(tried):
|
||||
print " %s" % dir
|
||||
print(" %s" % dir)
|
||||
for pattern in sorted(patterns):
|
||||
print " %s" % pattern
|
||||
print '*' * 72
|
||||
print(" %s" % pattern)
|
||||
print('*' * 72)
|
||||
raise MissingError('%s patterns could not be found' % len(self.missing))
|
||||
|
||||
def copy_finish(self):
|
||||
|
|
@ -659,7 +655,7 @@ class LLManifest(object):
|
|||
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
|
||||
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
|
||||
|
|
@ -670,7 +666,7 @@ class LLManifest(object):
|
|||
""" 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
|
||||
print("Cleaning up " + c)
|
||||
|
||||
def process_either(self, src, dst):
|
||||
# If it's a real directory, recurse through it --
|
||||
|
|
@ -719,7 +715,7 @@ class LLManifest(object):
|
|||
def remove(self, *paths):
|
||||
for path in paths:
|
||||
if os.path.exists(path):
|
||||
print "Removing path", path
|
||||
print("Removing path", path)
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
else:
|
||||
|
|
@ -781,7 +777,7 @@ class LLManifest(object):
|
|||
except (IOError, os.error) as why:
|
||||
errors.append((srcname, dstname, why))
|
||||
if errors:
|
||||
raise ManifestError, errors
|
||||
raise ManifestError(errors)
|
||||
|
||||
|
||||
def cmakedirs(self, path):
|
||||
|
|
@ -893,13 +889,13 @@ class LLManifest(object):
|
|||
break
|
||||
else:
|
||||
# no more prefixes left to try
|
||||
print("\nunable to find '%s'; looked in:\n %s" % (src, '\n '.join(try_prefixes)))
|
||||
print(("\nunable to find '%s'; looked in:\n %s" % (src, '\n '.join(try_prefixes))))
|
||||
self.missing.append(MissingFile(pattern=src, tried=try_prefixes))
|
||||
# At this point 'count' might never have been successfully
|
||||
# assigned! Even if it was, though, we can be sure it is 0.
|
||||
return 0
|
||||
|
||||
print "%d files" % count
|
||||
print("%d files" % count)
|
||||
|
||||
# Let caller check whether we processed as many files as expected. In
|
||||
# particular, let caller notice 0.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file test_win32_manifest.py
|
||||
@brief Test an assembly binding version and uniqueness in a windows dll or exe.
|
||||
|
|
@ -44,10 +44,10 @@ class NoMatchingAssemblyException(AssemblyTestException):
|
|||
pass
|
||||
|
||||
def get_HKLM_registry_value(key_str, value_str):
|
||||
import _winreg
|
||||
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||
key = _winreg.OpenKey(reg, key_str)
|
||||
value = _winreg.QueryValueEx(key, value_str)[0]
|
||||
import winreg
|
||||
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
|
||||
key = winreg.OpenKey(reg, key_str)
|
||||
value = winreg.QueryValueEx(key, value_str)[0]
|
||||
#print 'Found: %s' % value
|
||||
return value
|
||||
|
||||
|
|
@ -64,12 +64,12 @@ def find_vc_dir():
|
|||
(product, version))
|
||||
try:
|
||||
return get_HKLM_registry_value(key_str, value_str)
|
||||
except WindowsError, err:
|
||||
except WindowsError as err:
|
||||
x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\%s\%s\Setup\VC' % (product, version))
|
||||
try:
|
||||
return get_HKLM_registry_value(x64_key_str, value_str)
|
||||
except:
|
||||
print >> sys.stderr, "Didn't find MS %s version %s " % (product,version)
|
||||
print("Didn't find MS %s version %s " % (product,version), file=sys.stderr)
|
||||
|
||||
raise
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ def find_mt_path():
|
|||
return mt_path
|
||||
|
||||
def test_assembly_binding(src_filename, assembly_name, assembly_ver):
|
||||
print "checking %s dependency %s..." % (src_filename, assembly_name)
|
||||
print("checking %s dependency %s..." % (src_filename, assembly_name))
|
||||
|
||||
(tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
|
||||
tmp_file = os.fdopen(tmp_file_fd)
|
||||
|
|
@ -90,10 +90,10 @@ def test_assembly_binding(src_filename, assembly_name, assembly_ver):
|
|||
if os.path.splitext(src_filename)[1].lower() == ".dll":
|
||||
resource_id = ";#2"
|
||||
system_call = '%s -nologo -inputresource:%s%s -out:%s > NUL' % (mt_path, src_filename, resource_id, tmp_file_name)
|
||||
print "Executing: %s" % system_call
|
||||
print("Executing: %s" % system_call)
|
||||
mt_result = os.system(system_call)
|
||||
if mt_result == 31:
|
||||
print "No manifest found in %s" % src_filename
|
||||
print("No manifest found in %s" % src_filename)
|
||||
raise NoManifestException()
|
||||
|
||||
manifest_dom = parse(tmp_file_name)
|
||||
|
|
@ -105,30 +105,30 @@ def test_assembly_binding(src_filename, assembly_name, assembly_ver):
|
|||
versions.append(node.getAttribute('version'))
|
||||
|
||||
if len(versions) == 0:
|
||||
print "No matching assemblies found in %s" % src_filename
|
||||
print("No matching assemblies found in %s" % src_filename)
|
||||
raise NoMatchingAssemblyException()
|
||||
|
||||
#elif len(versions) > 1:
|
||||
# print "Multiple bindings to %s found:" % assembly_name
|
||||
# print versions
|
||||
# print
|
||||
# print("Multiple bindings to %s found:" % assembly_name)
|
||||
# print(versions)
|
||||
# print()
|
||||
# raise MultipleBindingsException(versions)
|
||||
|
||||
#elif versions[0] != assembly_ver:
|
||||
# print "Unexpected version found for %s:" % assembly_name
|
||||
# print "Wanted %s, found %s" % (assembly_ver, versions[0])
|
||||
# print
|
||||
# print("Unexpected version found for %s:" % assembly_name)
|
||||
# print("Wanted %s, found %s" % (assembly_ver, versions[0]))
|
||||
# print()
|
||||
# raise UnexpectedVersionException(assembly_ver, versions[0])
|
||||
|
||||
os.remove(tmp_file_name)
|
||||
|
||||
print "SUCCESS: %s OK!" % src_filename
|
||||
print
|
||||
print("SUCCESS: %s OK!" % src_filename)
|
||||
print()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print
|
||||
print "Running test_win32_manifest.py..."
|
||||
print()
|
||||
print("Running test_win32_manifest.py...")
|
||||
|
||||
usage = 'test_win32_manfest <srcFileName> <assemblyName> <assemblyVersion>'
|
||||
|
||||
|
|
@ -137,9 +137,9 @@ if __name__ == '__main__':
|
|||
assembly_name = sys.argv[2]
|
||||
assembly_ver = sys.argv[3]
|
||||
except:
|
||||
print "Usage:"
|
||||
print usage
|
||||
print
|
||||
print("Usage:")
|
||||
print(usage)
|
||||
print()
|
||||
raise
|
||||
|
||||
test_assembly_binding(src_filename, assembly_name, assembly_ver)
|
||||
|
|
|
|||
|
|
@ -3,18 +3,11 @@
|
|||
project(linux_crash_logger)
|
||||
|
||||
include(00-Common)
|
||||
include(GLH)
|
||||
include(LLCoreHttp)
|
||||
include(LLCommon)
|
||||
include(LLCrashLogger)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLFileSystem)
|
||||
include(LLXML)
|
||||
include(Linking)
|
||||
include(UI)
|
||||
include(FreeType)
|
||||
include(Boost)
|
||||
include(CURL)
|
||||
include(OpenSSL)
|
||||
include(ZLIB)
|
||||
|
||||
include_directories(
|
||||
${LLCOREHTTP_INCLUDE_DIRS}
|
||||
|
|
@ -36,7 +29,6 @@ include_directories(SYSTEM
|
|||
|
||||
set(linux_crash_logger_SOURCE_FILES
|
||||
linux_crash_logger.cpp
|
||||
llcrashloggerlinux.cpp
|
||||
)
|
||||
|
||||
set(linux_crash_logger_HEADER_FILES
|
||||
|
|
@ -61,19 +53,13 @@ set(LIBRT_LIBRARY rt)
|
|||
|
||||
|
||||
target_link_libraries(linux-crash-logger
|
||||
${LLCRASHLOGGER_LIBRARIES}
|
||||
${LLFILESYSTEM_LIBRARIES}
|
||||
${LLXML_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLCOREHTTP_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${BOOST_FIBER_LIBRARY}
|
||||
${BOOST_CONTEXT_LIBRARY}
|
||||
${UI_LIBRARIES}
|
||||
${DB_LIBRARIES}
|
||||
${FREETYPE_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${LIBRT_LIBRARY}
|
||||
X11
|
||||
)
|
||||
|
||||
add_custom_target(linux-crash-logger-target ALL
|
||||
|
|
|
|||
|
|
@ -24,35 +24,77 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llcrashloggerlinux.h"
|
||||
#include "llsdutil.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <curl/curl.h>
|
||||
#include <FL/fl_ask.H>
|
||||
|
||||
/* Called via
|
||||
execl( gCrashLogger.c_str(), gCrashLogger.c_str(), descriptor.path(), gVersion.c_str(), gBugsplatDB.c_str(), nullptr );
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
LL_INFOS() << "Starting crash reporter." << LL_ENDL;
|
||||
std::cerr << "linux crash logger called: ";
|
||||
for( int i = 1; i < argc; ++i )
|
||||
std::cerr << argv[i] << " ";
|
||||
|
||||
LLCrashLoggerLinux app;
|
||||
app.parseCommandOptions(argc, argv);
|
||||
std::cerr << std::endl;
|
||||
|
||||
LLSD options = LLApp::instance()->getOptionData(
|
||||
LLApp::PRIORITY_COMMAND_LINE);
|
||||
//LLApp::PRIORITY_RUNTIME_OVERRIDE);
|
||||
|
||||
|
||||
if (!(options.has("pid") && options.has("dumpdir")))
|
||||
if( argc < 4 )
|
||||
{
|
||||
LL_WARNS() << "Insufficient parameters to crash report." << LL_ENDL;
|
||||
std::cerr << argv[0] << "Not enough arguments" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! app.init())
|
||||
std::string dmpFile{ argv[1] };
|
||||
std::string version{ argv[2] };
|
||||
std::string strDb{ argv[3] };
|
||||
std::string strAsk{ argv[4] };
|
||||
|
||||
if( strAsk == "ask" )
|
||||
{
|
||||
LL_WARNS() << "Unable to initialize application." << LL_ENDL;
|
||||
return 1;
|
||||
auto choice = fl_choice( "Firestorm has crashed, submit the minidump?", "No", "Yes", nullptr );
|
||||
if( choice == 0 )
|
||||
{
|
||||
std::cerr << "Abort send due to users choice" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
return 0;
|
||||
std::string url{ "https://" };
|
||||
url += strDb;
|
||||
url += ".bugsplat.com/post/bp/crash/crashpad.php";
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
auto curl = curl_easy_init();
|
||||
if( curl)
|
||||
{
|
||||
auto form = curl_mime_init(curl);
|
||||
|
||||
auto field = curl_mime_addpart(form);
|
||||
curl_mime_name(field, "upload_file_minidump");
|
||||
curl_mime_filedata(field, dmpFile.c_str() );
|
||||
|
||||
field = curl_mime_addpart(form);
|
||||
curl_mime_name(field, "product");
|
||||
curl_mime_data(field, "Firestorm-Releasex64", CURL_ZERO_TERMINATED);
|
||||
|
||||
field = curl_mime_addpart(form);
|
||||
curl_mime_name(field, "version");
|
||||
curl_mime_data(field, version.c_str(), CURL_ZERO_TERMINATED);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
|
||||
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
|
||||
|
||||
auto res = curl_easy_perform(curl);
|
||||
|
||||
if(res != CURLE_OK)
|
||||
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
curl_mime_free(form);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,171 +0,0 @@
|
|||
/**
|
||||
* @file llcrashloggerlinux.cpp
|
||||
* @brief Linux crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llcrashloggerlinux.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
|
||||
#include "llerror.h"
|
||||
#include "llfile.h"
|
||||
#include "lltimer.h"
|
||||
#include "llstring.h"
|
||||
#include "lldir.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
#if LL_GTK
|
||||
# include "gtk/gtk.h"
|
||||
#endif // LL_GTK
|
||||
|
||||
#define MAX_LOADSTRING 100
|
||||
|
||||
// <FS:ND> Fire-901 / Crashreporting: Brand for FS, add URL to privacy policy
|
||||
|
||||
// These need to be localized.
|
||||
// static const char dialog_text[] =
|
||||
// "Second Life appears to have crashed or frozen last time it ran.\n"
|
||||
// "This crash reporter collects information about your computer's hardware, operating system, and some Second Life logs, all of which are used for debugging purposes only.\n"
|
||||
// "\n"
|
||||
// "Send crash report?";
|
||||
//
|
||||
// static const char dialog_title[] =
|
||||
// "Second Life Crash Logger";
|
||||
|
||||
static const char dialog_text[] =
|
||||
"Firestorm appears to have crashed or frozen last time it ran.\n"
|
||||
"This crash reporter collects information about your computer's hardware, operating system which are used for debugging purposes only. SecondLife logs are not collected.\n"
|
||||
"This report will be send to firestormviewer.org. Review our privacy policy at http://www.firestormviewer.org/privacy-policy for more information.\n"
|
||||
"\n"
|
||||
"Send crash report?";
|
||||
|
||||
static const char dialog_title[] =
|
||||
"Firestorm Crash Logger";
|
||||
|
||||
// </FS:ND>
|
||||
|
||||
#if 0
|
||||
|
||||
#if LL_GTK
|
||||
static void response_callback (GtkDialog *dialog,
|
||||
gint arg1,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint *response = (gint*)user_data;
|
||||
*response = arg1;
|
||||
gtk_widget_destroy(GTK_WIDGET(dialog));
|
||||
gtk_main_quit();
|
||||
}
|
||||
#endif // LL_GTK
|
||||
|
||||
static BOOL do_ask_dialog(void)
|
||||
{
|
||||
#if LL_GTK
|
||||
gtk_disable_setlocale();
|
||||
if (!gtk_init_check(NULL, NULL)) {
|
||||
LL_INFOS() << "Could not initialize GTK for 'ask to send crash report' dialog; not sending report." << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkWidget *win = NULL;
|
||||
GtkDialogFlags flags = GTK_DIALOG_MODAL;
|
||||
GtkMessageType messagetype = GTK_MESSAGE_QUESTION;
|
||||
GtkButtonsType buttons = GTK_BUTTONS_YES_NO;
|
||||
gint response = GTK_RESPONSE_NONE;
|
||||
|
||||
win = gtk_message_dialog_new(NULL,
|
||||
flags, messagetype, buttons,
|
||||
"%s", dialog_text);
|
||||
gtk_window_set_type_hint(GTK_WINDOW(win),
|
||||
GDK_WINDOW_TYPE_HINT_DIALOG);
|
||||
gtk_window_set_title(GTK_WINDOW(win), dialog_title);
|
||||
g_signal_connect (win,
|
||||
"response",
|
||||
G_CALLBACK (response_callback),
|
||||
&response);
|
||||
gtk_widget_show_all (win);
|
||||
gtk_main();
|
||||
|
||||
return (GTK_RESPONSE_OK == response ||
|
||||
GTK_RESPONSE_YES == response ||
|
||||
GTK_RESPONSE_APPLY == response);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif // LL_GTK
|
||||
}
|
||||
#endif
|
||||
|
||||
LLCrashLoggerLinux::LLCrashLoggerLinux(void)
|
||||
{
|
||||
}
|
||||
|
||||
LLCrashLoggerLinux::~LLCrashLoggerLinux(void)
|
||||
{
|
||||
}
|
||||
|
||||
void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
|
||||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerLinux::frame()
|
||||
{
|
||||
// <FS:ND> Get around the crash logger popping up all the time.
|
||||
// Right now there seems to be no easy way to test if there's logs from a real crash to send. Which
|
||||
// would be preferred, as then asking for sending in data makes sense. Right now the dialog will just open always.
|
||||
|
||||
// bool send_logs = true;
|
||||
// if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
|
||||
// {
|
||||
// send_logs = do_ask_dialog();
|
||||
// }
|
||||
// else if(CRASH_BEHAVIOR_NEVER_SEND == getCrashBehavior())
|
||||
// {
|
||||
// send_logs = false;
|
||||
// }
|
||||
|
||||
bool send_logs = (CRASH_BEHAVIOR_NEVER_SEND == getCrashBehavior());
|
||||
|
||||
// </FS:ND>
|
||||
|
||||
if(send_logs)
|
||||
{
|
||||
sendCrashLogs();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLCrashLoggerLinux::cleanup()
|
||||
{
|
||||
commonCleanup();
|
||||
mKeyMaster.releaseMaster();
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLCrashLoggerLinux::updateApplication(const std::string& message)
|
||||
{
|
||||
LLCrashLogger::updateApplication(message);
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ include(LLMath)
|
|||
include(LLMessage)
|
||||
include(LLFileSystem)
|
||||
|
||||
include_directories(
|
||||
include_directories( SYSTEM
|
||||
${LLAUDIO_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ include(Copy3rdPartyLibs)
|
|||
include(ZLIB)
|
||||
include(URIPARSER)
|
||||
|
||||
include_directories(
|
||||
include_directories( SYSTEM
|
||||
${EXPAT_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${JSONCPP_INCLUDE_DIR}
|
||||
|
|
|
|||
|
|
@ -544,8 +544,6 @@ namespace
|
|||
protected:
|
||||
Globals();
|
||||
public:
|
||||
std::ostringstream messageStream;
|
||||
bool messageStreamInUse;
|
||||
std::string mFatalMessage;
|
||||
|
||||
void addCallSite(LLError::CallSite&);
|
||||
|
|
@ -562,7 +560,9 @@ namespace
|
|||
};
|
||||
|
||||
Globals::Globals()
|
||||
: mSettingsConfig(new SettingsConfig())
|
||||
:
|
||||
callSites(),
|
||||
mSettingsConfig(new SettingsConfig())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1449,7 +1449,10 @@ namespace LLError
|
|||
if (site.mLevel == LEVEL_ERROR)
|
||||
{
|
||||
g->mFatalMessage = message;
|
||||
s->mCrashFunction(message);
|
||||
if (s->mCrashFunction)
|
||||
{
|
||||
s->mCrashFunction(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ const int LL_ERR_NOERR = 0;
|
|||
|
||||
#endif // !_DEBUG
|
||||
|
||||
#define llassert_always_msg(func, msg) if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << msg << ")" << LL_ENDL
|
||||
#define llassert_always_msg(func, msg) if (LL_UNLIKELY(!(func))) { LL_ERRS() << "ASSERT (" << msg << ")" << LL_ENDL; /*<FS:ND> call abort, this will not be reached but signaled GCC after this line the program exists*/ std::abort(); }
|
||||
|
||||
#define llassert_always(func) llassert_always_msg(func, #func)
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public:
|
|||
// notice Python specially: we provide Python LLSD serialization
|
||||
// support, so there's a pretty good reason to implement plugins
|
||||
// in that language.
|
||||
if (cparams.args.size() && (desclower == "python" || desclower == "python.exe"))
|
||||
if (cparams.args.size() && (desclower == "python" || desclower == "python3" || desclower == "python.exe"))
|
||||
{
|
||||
mDesc = LLProcess::basename(cparams.args()[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,7 +189,6 @@ LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
|
|||
void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
|
||||
{
|
||||
incrementCurrentCount() ;
|
||||
(*sd)[getCurrentLabelName()]["Name"] = mName ;
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@
|
|||
#include <set>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
// <FS:ND> Suppress warnings about the string fiddling
|
||||
#if LL_LINUX
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
#endif
|
||||
// </FS:ND>
|
||||
|
||||
// U32
|
||||
LLSD ll_sd_from_U32(const U32 val)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ LLOSInfo::LLOSInfo() :
|
|||
|
||||
#if LL_WINDOWS
|
||||
|
||||
if (IsWindows10OrGreater())
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
mMajorVer = 10;
|
||||
mMinorVer = 0;
|
||||
|
|
@ -248,13 +248,24 @@ LLOSInfo::LLOSInfo() :
|
|||
}
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Windows 11 detection
|
||||
if (mBuild >= 22000)
|
||||
{
|
||||
mMajorVer = 11;
|
||||
LLStringUtil::replaceString(mOSStringSimple, "10", "11");
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
if (mBuild >= 22000)
|
||||
{
|
||||
// At release Windows 11 version was 10.0.22000.194
|
||||
// Windows 10 version was 10.0.19043.1266
|
||||
// There is no warranty that Win10 build won't increase,
|
||||
// so until better solution is found or Microsoft updates
|
||||
// SDK with IsWindows11OrGreater(), indicate "10/11"
|
||||
//
|
||||
// Current alternatives:
|
||||
// Query WMI's Win32_OperatingSystem for OS string. Slow
|
||||
// and likely to return 'compatibility' string.
|
||||
// Check presence of dlls/libs or may be their version.
|
||||
// <FS:Ansariel> Windows 11 detection
|
||||
//mOSStringSimple = "Microsoft Windows 10/11";
|
||||
mMajorVer = 11;
|
||||
LLStringUtil::replaceString(mOSStringSimple, "10", "11");
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
}
|
||||
|
||||
mOSString = mOSStringSimple;
|
||||
|
|
@ -1262,18 +1273,12 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
|
|||
LLFILE *dst = NULL;
|
||||
S32 bytes = 0;
|
||||
tmpfile = dstfile + ".t";
|
||||
|
||||
// <FS:ND> Proper UTF8->UTF16 handling for Windows
|
||||
// src = gzopen(srcfile.c_str(), "rb");
|
||||
#if LL_WINDOWS
|
||||
std::string utf8filename = srcfile;
|
||||
llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
|
||||
src = gzopen_w(utf16filename.c_str(), "rb");
|
||||
#ifdef LL_WINDOWS
|
||||
llutf16string utf16filename = utf8str_to_utf16str(srcfile);
|
||||
src = gzopen_w(utf16filename.c_str(), "rb");
|
||||
#else
|
||||
src = gzopen(srcfile.c_str(), "rb");/* Flawfinder: ignore */
|
||||
src = gzopen(srcfile.c_str(), "rb");
|
||||
#endif
|
||||
// </FS:ND>
|
||||
|
||||
if (! src) goto err;
|
||||
dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
|
||||
if (! dst) goto err;
|
||||
|
|
@ -1308,17 +1313,13 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
|
|||
S32 bytes = 0;
|
||||
tmpfile = dstfile + ".t";
|
||||
|
||||
// <FS:ND> Proper UTF8->UTF16 handling for Windows
|
||||
// dst = gzopen(tmpfile.c_str(), "wb"); /* Flawfinder: ignore */
|
||||
#if LL_WINDOWS
|
||||
std::string utf8filename = tmpfile;
|
||||
llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
|
||||
dst = gzopen_w(utf16filename.c_str(), "wb");
|
||||
#ifdef LL_WINDOWS
|
||||
llutf16string utf16filename = utf8str_to_utf16str(tmpfile);
|
||||
dst = gzopen_w(utf16filename.c_str(), "wb");
|
||||
#else
|
||||
dst = gzopen(tmpfile.c_str(), "wb");/* Flawfinder: ignore */
|
||||
dst = gzopen(tmpfile.c_str(), "wb");
|
||||
#endif
|
||||
// </FS:ND>
|
||||
|
||||
|
||||
if (! dst) goto err;
|
||||
src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
|
||||
if (! src) goto err;
|
||||
|
|
|
|||
|
|
@ -145,13 +145,13 @@ namespace tut
|
|||
" data = ''.join(parts)\n"
|
||||
" assert len(data) == length\n"
|
||||
" try:\n"
|
||||
" return llsd.parse(data)\n"
|
||||
" return llsd.parse(data.encode())\n"
|
||||
// Seems the old indra.base.llsd module didn't properly
|
||||
// convert IndexError (from running off end of string) to
|
||||
// LLSDParseError.
|
||||
" except (IndexError, llsd.LLSDParseError), e:\n"
|
||||
" except (IndexError, llsd.LLSDParseError) as e:\n"
|
||||
" msg = 'Bad received packet (%s)' % e\n"
|
||||
" print >>sys.stderr, '%s, %s bytes:' % (msg, len(data))\n"
|
||||
" print('%s, %s bytes:' % (msg, len(data)), file=sys.stderr)\n"
|
||||
" showmax = 40\n"
|
||||
// We've observed failures with very large packets;
|
||||
// dumping the entire packet wastes time and space.
|
||||
|
|
@ -167,12 +167,12 @@ namespace tut
|
|||
" data = data[:trunc]\n"
|
||||
" ellipsis = '... (%s more)' % (length - trunc)\n"
|
||||
" offset = -showmax\n"
|
||||
" for offset in xrange(0, len(data)-showmax, showmax):\n"
|
||||
" print >>sys.stderr, '%04d: %r +' % \\\n"
|
||||
" (offset, data[offset:offset+showmax])\n"
|
||||
" for offset in range(0, len(data)-showmax, showmax):\n"
|
||||
" print('%04d: %r +' % \\\n"
|
||||
" (offset, data[offset:offset+showmax]), file=sys.stderr)\n"
|
||||
" offset += showmax\n"
|
||||
" print >>sys.stderr, '%04d: %r%s' % \\\n"
|
||||
" (offset, data[offset:], ellipsis)\n"
|
||||
" print('%04d: %r%s' % \\\n"
|
||||
" (offset, data[offset:], ellipsis), file=sys.stderr)\n"
|
||||
" raise ParseError(msg, data)\n"
|
||||
"\n"
|
||||
"# deal with initial stdin message\n"
|
||||
|
|
@ -189,7 +189,7 @@ namespace tut
|
|||
" sys.stdout.flush()\n"
|
||||
"\n"
|
||||
"def send(pump, data):\n"
|
||||
" put(llsd.format_notation(dict(pump=pump, data=data)))\n"
|
||||
" put(llsd.format_notation(dict(pump=pump, data=data)).decode())\n"
|
||||
"\n"
|
||||
"def request(pump, data):\n"
|
||||
" # we expect 'data' is a dict\n"
|
||||
|
|
@ -253,7 +253,7 @@ namespace tut
|
|||
{
|
||||
set_test_name("bad stdout protocol");
|
||||
NamedTempFile script("py",
|
||||
"print 'Hello from Python!'\n");
|
||||
"print('Hello from Python!')\n");
|
||||
CaptureLog log(LLError::LEVEL_WARN);
|
||||
waitfor(LLLeap::create(get_test_name(),
|
||||
sv(list_of(PYTHON)(script.getName()))));
|
||||
|
|
@ -438,8 +438,8 @@ namespace tut
|
|||
// guess how many messages it will take to
|
||||
// accumulate BUFFERED_LENGTH
|
||||
"count = int(" << BUFFERED_LENGTH << "/samplen)\n"
|
||||
"print >>sys.stderr, 'Sending %s requests' % count\n"
|
||||
"for i in xrange(count):\n"
|
||||
"print('Sending %s requests' % count, file=sys.stderr)\n"
|
||||
"for i in range(count):\n"
|
||||
" request('" << api.getName() << "', dict(reqid=i))\n"
|
||||
// The assumption in this specific test that
|
||||
// replies will arrive in the same order as
|
||||
|
|
@ -450,7 +450,7 @@ namespace tut
|
|||
// arbitrary order, and we'd have to tick them
|
||||
// off from a set.
|
||||
"result = ''\n"
|
||||
"for i in xrange(count):\n"
|
||||
"for i in range(count):\n"
|
||||
" resp = get()\n"
|
||||
" if resp['data']['reqid'] != i:\n"
|
||||
" result = 'expected reqid=%s in %s' % (i, resp)\n"
|
||||
|
|
@ -476,13 +476,13 @@ namespace tut
|
|||
"desired = int(sys.argv[1])\n"
|
||||
// 7 chars per item: 6 digits, 1 comma
|
||||
"count = int((desired - 50)/7)\n"
|
||||
"large = ''.join('%06d,' % i for i in xrange(count))\n"
|
||||
"large = ''.join('%06d,' % i for i in range(count))\n"
|
||||
// Pass 'large' as reqid because we know the API
|
||||
// will echo reqid, and we want to receive it back.
|
||||
"request('" << api.getName() << "', dict(reqid=large))\n"
|
||||
"try:\n"
|
||||
" resp = get()\n"
|
||||
"except ParseError, e:\n"
|
||||
"except ParseError as e:\n"
|
||||
" # try to find where e.data diverges from expectation\n"
|
||||
// Normally we'd expect a 'pump' key in there,
|
||||
// too, with value replypump(). But Python
|
||||
|
|
@ -493,17 +493,18 @@ namespace tut
|
|||
// strange.
|
||||
" expect = llsd.format_notation(dict(data=dict(reqid=large)))\n"
|
||||
" chunk = 40\n"
|
||||
" for offset in xrange(0, max(len(e.data), len(expect)), chunk):\n"
|
||||
" for offset in range(0, max(len(e.data), len(expect)), chunk):\n"
|
||||
" if e.data[offset:offset+chunk] != \\\n"
|
||||
" expect[offset:offset+chunk]:\n"
|
||||
" print >>sys.stderr, 'Offset %06d: expect %r,\\n'\\\n"
|
||||
" print('Offset %06d: expect %r,\\n'\\\n"
|
||||
" ' get %r' %\\\n"
|
||||
" (offset,\n"
|
||||
" expect[offset:offset+chunk],\n"
|
||||
" e.data[offset:offset+chunk])\n"
|
||||
" e.data[offset:offset+chunk]),\n"
|
||||
" file=sys.stderr)\n"
|
||||
" break\n"
|
||||
" else:\n"
|
||||
" print >>sys.stderr, 'incoming data matches expect?!'\n"
|
||||
" print('incoming data matches expect?!', file=sys.stderr)\n"
|
||||
" send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n"
|
||||
" sys.exit(1)\n"
|
||||
"\n"
|
||||
|
|
@ -512,7 +513,7 @@ namespace tut
|
|||
" send('" << result.getName() << "', '')\n"
|
||||
" sys.exit(0)\n"
|
||||
// Here we know echoed did NOT match; try to find where
|
||||
"for i in xrange(count):\n"
|
||||
"for i in range(count):\n"
|
||||
" start = 7*i\n"
|
||||
" end = 7*(i+1)\n"
|
||||
" if end > len(echoed)\\\n"
|
||||
|
|
|
|||
|
|
@ -360,10 +360,10 @@ namespace tut
|
|||
"import time" EOL
|
||||
EOL
|
||||
"time.sleep(2)" EOL
|
||||
"print >>sys.stdout, 'stdout after wait'" EOL
|
||||
"print('stdout after wait', file=sys.stdout)" EOL
|
||||
"sys.stdout.flush()" EOL
|
||||
"time.sleep(2)" EOL
|
||||
"print >>sys.stderr, 'stderr after wait'" EOL
|
||||
"print('stderr after wait', file=sys.stderr)" EOL
|
||||
"sys.stderr.flush()" EOL
|
||||
);
|
||||
|
||||
|
|
@ -381,7 +381,11 @@ namespace tut
|
|||
|
||||
std::vector<const char*> argv;
|
||||
apr_proc_t child;
|
||||
#if defined(LL_WINDOWS)
|
||||
argv.push_back("python");
|
||||
#else
|
||||
argv.push_back("python3");
|
||||
#endif
|
||||
// Have to have a named copy of this std::string so its c_str() value
|
||||
// will persist.
|
||||
std::string scriptname(script.getName());
|
||||
|
|
@ -573,7 +577,7 @@ namespace tut
|
|||
// note nonstandard output-file arg!
|
||||
"with open(sys.argv[3], 'w') as f:\n"
|
||||
" for arg in sys.argv[1:]:\n"
|
||||
" print >>f, arg\n");
|
||||
" print(arg, file=f)\n");
|
||||
// We expect that PythonProcessLauncher has already appended
|
||||
// its own NamedTempFile to mParams.args (sys.argv[0]).
|
||||
py.mParams.args.add("first arg"); // sys.argv[1]
|
||||
|
|
@ -742,7 +746,7 @@ namespace tut
|
|||
"with open(sys.argv[1], 'w') as f:\n"
|
||||
" f.write('ok')\n"
|
||||
"# wait for 'go' from test program\n"
|
||||
"for i in xrange(60):\n"
|
||||
"for i in range(60):\n"
|
||||
" time.sleep(1)\n"
|
||||
" with open(sys.argv[2]) as f:\n"
|
||||
" go = f.read()\n"
|
||||
|
|
@ -804,7 +808,7 @@ namespace tut
|
|||
"with open(sys.argv[1], 'w') as f:\n"
|
||||
" f.write('ok')\n"
|
||||
"# wait for 'go' from test program\n"
|
||||
"for i in xrange(60):\n"
|
||||
"for i in range(60):\n"
|
||||
" time.sleep(1)\n"
|
||||
" with open(sys.argv[2]) as f:\n"
|
||||
" go = f.read()\n"
|
||||
|
|
@ -857,7 +861,7 @@ namespace tut
|
|||
set_test_name("'bogus' test");
|
||||
CaptureLog recorder;
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"print 'Hello world'\n");
|
||||
"print('Hello world')\n");
|
||||
py.mParams.files.add(LLProcess::FileParam("bogus"));
|
||||
py.mPy = LLProcess::create(py.mParams);
|
||||
ensure("should have rejected 'bogus'", ! py.mPy);
|
||||
|
|
@ -872,7 +876,7 @@ namespace tut
|
|||
// Replace this test with one or more real 'file' tests when we
|
||||
// implement 'file' support
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"print 'Hello world'\n");
|
||||
"print('Hello world')\n");
|
||||
py.mParams.files.add(LLProcess::FileParam());
|
||||
py.mParams.files.add(LLProcess::FileParam("file"));
|
||||
py.mPy = LLProcess::create(py.mParams);
|
||||
|
|
@ -887,7 +891,7 @@ namespace tut
|
|||
// implement 'tpipe' support
|
||||
CaptureLog recorder;
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"print 'Hello world'\n");
|
||||
"print('Hello world')\n");
|
||||
py.mParams.files.add(LLProcess::FileParam());
|
||||
py.mParams.files.add(LLProcess::FileParam("tpipe"));
|
||||
py.mPy = LLProcess::create(py.mParams);
|
||||
|
|
@ -904,7 +908,7 @@ namespace tut
|
|||
// implement 'npipe' support
|
||||
CaptureLog recorder;
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"print 'Hello world'\n");
|
||||
"print('Hello world')\n");
|
||||
py.mParams.files.add(LLProcess::FileParam());
|
||||
py.mParams.files.add(LLProcess::FileParam());
|
||||
py.mParams.files.add(LLProcess::FileParam("npipe"));
|
||||
|
|
@ -980,7 +984,7 @@ namespace tut
|
|||
{
|
||||
set_test_name("get*Pipe() validation");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"print 'this output is expected'\n");
|
||||
"print('this output is expected)'\n");
|
||||
py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stdin
|
||||
py.mParams.files.add(LLProcess::FileParam()); // inherit stdout
|
||||
py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr
|
||||
|
|
@ -1001,13 +1005,13 @@ namespace tut
|
|||
set_test_name("talk to stdin/stdout");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"import sys, time\n"
|
||||
"print 'ok'\n"
|
||||
"print('ok')\n"
|
||||
"sys.stdout.flush()\n"
|
||||
"# wait for 'go' from test program\n"
|
||||
"go = sys.stdin.readline()\n"
|
||||
"if go != 'go\\n':\n"
|
||||
" sys.exit('expected \"go\", saw %r' % go)\n"
|
||||
"print 'ack'\n");
|
||||
"print('ack')\n");
|
||||
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin
|
||||
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
|
||||
py.launch();
|
||||
|
|
@ -1118,7 +1122,7 @@ namespace tut
|
|||
{
|
||||
set_test_name("ReadPipe \"eof\" event");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"print 'Hello from Python!'\n");
|
||||
"print('Hello from Python!')\n");
|
||||
py.mParams.files.add(LLProcess::FileParam()); // stdin
|
||||
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
|
||||
py.launch();
|
||||
|
|
|
|||
|
|
@ -1795,7 +1795,7 @@ namespace tut
|
|||
set_test_name("verify NamedTempFile");
|
||||
python("platform",
|
||||
"import sys\n"
|
||||
"print 'Running on', sys.platform\n");
|
||||
"print('Running on', sys.platform)\n");
|
||||
}
|
||||
|
||||
// helper for test<3>
|
||||
|
|
@ -1825,14 +1825,14 @@ namespace tut
|
|||
const char pydata[] =
|
||||
"def verify(iterable):\n"
|
||||
" it = iter(iterable)\n"
|
||||
" assert it.next() == 17\n"
|
||||
" assert abs(it.next() - 3.14) < 0.01\n"
|
||||
" assert it.next() == '''\\\n"
|
||||
" assert next(it) == 17\n"
|
||||
" assert abs(next(it) - 3.14) < 0.01\n"
|
||||
" assert next(it) == '''\\\n"
|
||||
"This string\n"
|
||||
"has several\n"
|
||||
"lines.'''\n"
|
||||
" try:\n"
|
||||
" it.next()\n"
|
||||
" next(it)\n"
|
||||
" except StopIteration:\n"
|
||||
" pass\n"
|
||||
" else:\n"
|
||||
|
|
@ -1855,7 +1855,7 @@ namespace tut
|
|||
" yield llsd.parse(item)\n" <<
|
||||
pydata <<
|
||||
// Don't forget raw-string syntax for Windows pathnames.
|
||||
"verify(parse_each(open(r'" << file.getName() << "')))\n");
|
||||
"verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
|
|
@ -1870,7 +1870,6 @@ namespace tut
|
|||
|
||||
python("write Python notation",
|
||||
placeholders::arg1 <<
|
||||
"from __future__ import with_statement\n" <<
|
||||
import_llsd <<
|
||||
"DATA = [\n"
|
||||
" 17,\n"
|
||||
|
|
@ -1884,7 +1883,7 @@ namespace tut
|
|||
// N.B. Using 'print' implicitly adds newlines.
|
||||
"with open(r'" << file.getName() << "', 'w') as f:\n"
|
||||
" for item in DATA:\n"
|
||||
" print >>f, llsd.format_notation(item)\n");
|
||||
" print(llsd.format_notation(item).decode(), file=f)\n");
|
||||
|
||||
std::ifstream inf(file.getName().c_str());
|
||||
LLSD item;
|
||||
|
|
|
|||
|
|
@ -508,7 +508,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle());
|
||||
|
||||
// <FS:ND/> Newer versions of curl are stricter with checkinng Cotent-Encoding: header
|
||||
// Aws returns Content-Encoding: binary/octet-stream which is no valid scheme defined by HTTP/1.1 (compress,deflate, gzip)
|
||||
#if LIBCURL_VERSION_NUM < 0x075100
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
|
||||
#endif
|
||||
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
|
||||
|
|
|
|||
|
|
@ -289,8 +289,12 @@ CURL *getCurlTemplateHandle()
|
|||
check_curl_code(result, CURLOPT_NOSIGNAL);
|
||||
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_NOPROGRESS, 1);
|
||||
check_curl_code(result, CURLOPT_NOPROGRESS);
|
||||
// <FS:ND/> Newer versions of curl are stricter with checkinng Cotent-Encoding: header
|
||||
// Aws returns Content-Encoding: binary/octet-stream which is no valid scheme defined by HTTP/1.1 (compress,deflate, gzip)
|
||||
#if LIBCURL_VERSION_NUM < 0x075100
|
||||
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_ENCODING, "");
|
||||
check_curl_code(result, CURLOPT_ENCODING);
|
||||
#endif
|
||||
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_AUTOREFERER, 1);
|
||||
check_curl_code(result, CURLOPT_AUTOREFERER);
|
||||
result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
|
|
|
|||
|
|
@ -135,7 +135,9 @@ public:
|
|||
}
|
||||
}
|
||||
std::ostringstream str;
|
||||
str << "Required header # " << i << " found in response";
|
||||
str << "Required header #" << i << " "
|
||||
<< mHeadersRequired[i].first << "=" << mHeadersRequired[i].second
|
||||
<< " not found in response";
|
||||
ensure(str.str(), found);
|
||||
}
|
||||
}
|
||||
|
|
@ -154,7 +156,9 @@ public:
|
|||
mHeadersDisallowed[i].second))
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << "Disallowed header # " << i << " not found in response";
|
||||
str << "Disallowed header #" << i << " "
|
||||
<< mHeadersDisallowed[i].first << "=" << mHeadersDisallowed[i].second
|
||||
<< " found in response";
|
||||
ensure(str.str(), false);
|
||||
}
|
||||
}
|
||||
|
|
@ -2127,6 +2131,17 @@ void HttpRequestTestObjectType::test<18>()
|
|||
template <> template <>
|
||||
void HttpRequestTestObjectType::test<19>()
|
||||
{
|
||||
// It appears that HttpRequest is fully capable of sending duplicate header values in violation of
|
||||
// this test's expectations. Something needs to budge: is sending duplicate header values desired?
|
||||
//
|
||||
// Test server /reflect/ response headers (mirrored from request)
|
||||
//
|
||||
// X-Reflect-content-type: text/plain
|
||||
// X-Reflect-content-type: text/html
|
||||
// X-Reflect-content-type: application/llsd+xml
|
||||
//
|
||||
skip("FIXME: Bad assertions or broken functionality.");
|
||||
|
||||
ScopedCurlInit ready;
|
||||
|
||||
// Warmup boost::regex to pre-alloc memory for memory size tests
|
||||
|
|
@ -2307,6 +2322,17 @@ void HttpRequestTestObjectType::test<19>()
|
|||
template <> template <>
|
||||
void HttpRequestTestObjectType::test<20>()
|
||||
{
|
||||
// It appears that HttpRequest is fully capable of sending duplicate header values in violation of
|
||||
// this test's expectations. Something needs to budge: is sending duplicate header values desired?
|
||||
//
|
||||
// Test server /reflect/ response headers (mirrored from request)
|
||||
//
|
||||
// X-Reflect-content-type: text/plain
|
||||
// X-Reflect-content-type: text/html
|
||||
// X-Reflect-content-type: application/llsd+xml
|
||||
//
|
||||
skip("FIXME: Bad assertions or broken functionality.");
|
||||
|
||||
ScopedCurlInit ready;
|
||||
|
||||
// Warmup boost::regex to pre-alloc memory for memory size tests
|
||||
|
|
@ -2512,6 +2538,17 @@ void HttpRequestTestObjectType::test<20>()
|
|||
template <> template <>
|
||||
void HttpRequestTestObjectType::test<21>()
|
||||
{
|
||||
// It appears that HttpRequest is fully capable of sending duplicate header values in violation of
|
||||
// this test's expectations. Something needs to budge: is sending duplicate header values desired?
|
||||
//
|
||||
// Test server /reflect/ response headers (mirrored from request)
|
||||
//
|
||||
// X-Reflect-content-type: text/plain
|
||||
// X-Reflect-content-type: text/html
|
||||
// X-Reflect-content-type: application/llsd+xml
|
||||
//
|
||||
skip("FIXME: Bad assertions or broken functionality.");
|
||||
|
||||
ScopedCurlInit ready;
|
||||
|
||||
// Warmup boost::regex to pre-alloc memory for memory size tests
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file test_llsdmessage_peer.py
|
||||
@author Nat Goodspeed
|
||||
|
|
@ -34,11 +34,9 @@ import sys
|
|||
import time
|
||||
import select
|
||||
import getopt
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||
from io import StringIO
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
|
||||
from llbase.fastest_elementtree import parse as xml_parse
|
||||
from llbase import llsd
|
||||
|
|
@ -97,13 +95,13 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
except (KeyError, ValueError):
|
||||
return ""
|
||||
max_chunk_size = 10*1024*1024
|
||||
L = []
|
||||
L = bytes()
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, max_chunk_size)
|
||||
chunk = self.rfile.read(chunk_size)
|
||||
L.append(chunk)
|
||||
L += chunk
|
||||
size_remaining -= len(chunk)
|
||||
return ''.join(L)
|
||||
return L.decode("utf-8")
|
||||
# end of swiped read() logic
|
||||
|
||||
def read_xml(self):
|
||||
|
|
@ -127,8 +125,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
try:
|
||||
self.answer(dict(reply="success", status=200,
|
||||
reason="Your GET operation worked"))
|
||||
except self.ignore_exceptions, e:
|
||||
print >> sys.stderr, "Exception during GET (ignoring): %s" % str(e)
|
||||
except self.ignore_exceptions as e:
|
||||
print("Exception during GET (ignoring): %s" % str(e), file=sys.stderr)
|
||||
|
||||
def do_POST(self):
|
||||
# Read the provided POST data.
|
||||
|
|
@ -136,8 +134,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
try:
|
||||
self.answer(dict(reply="success", status=200,
|
||||
reason=self.read()))
|
||||
except self.ignore_exceptions, e:
|
||||
print >> sys.stderr, "Exception during POST (ignoring): %s" % str(e)
|
||||
except self.ignore_exceptions as e:
|
||||
print("Exception during POST (ignoring): %s" % str(e), file=sys.stderr)
|
||||
|
||||
def do_PUT(self):
|
||||
# Read the provided PUT data.
|
||||
|
|
@ -145,8 +143,8 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
try:
|
||||
self.answer(dict(reply="success", status=200,
|
||||
reason=self.read()))
|
||||
except self.ignore_exceptions, e:
|
||||
print >> sys.stderr, "Exception during PUT (ignoring): %s" % str(e)
|
||||
except self.ignore_exceptions as e:
|
||||
print("Exception during PUT (ignoring): %s" % str(e), file=sys.stderr)
|
||||
|
||||
def answer(self, data, withdata=True):
|
||||
debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
|
||||
|
|
@ -221,7 +219,7 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
self.send_header("Content-type", "text/plain")
|
||||
self.end_headers()
|
||||
if body:
|
||||
self.wfile.write(body)
|
||||
self.wfile.write(body.encode("utf-8"))
|
||||
elif "fail" not in self.path:
|
||||
data = data.copy() # we're going to modify
|
||||
# Ensure there's a "reply" key in data, even if there wasn't before
|
||||
|
|
@ -255,9 +253,9 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
self.end_headers()
|
||||
|
||||
def reflect_headers(self):
|
||||
for name in self.headers.keys():
|
||||
# print "Header: %s: %s" % (name, self.headers[name])
|
||||
self.send_header("X-Reflect-" + name, self.headers[name])
|
||||
for (name, val) in self.headers.items():
|
||||
# print("Header: %s %s" % (name, val), file=sys.stderr)
|
||||
self.send_header("X-Reflect-" + name, val)
|
||||
|
||||
if not VERBOSE:
|
||||
# When VERBOSE is set, skip both these overrides because they exist to
|
||||
|
|
@ -283,10 +281,10 @@ class Server(HTTPServer):
|
|||
# default behavior which *shouldn't* cause the program to return
|
||||
# a failure status.
|
||||
def handle_error(self, request, client_address):
|
||||
print '-'*40
|
||||
print 'Ignoring exception during processing of request from',
|
||||
print client_address
|
||||
print '-'*40
|
||||
print('-'*40)
|
||||
print('Ignoring exception during processing of request from %' % (client_address))
|
||||
print('-'*40)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
do_valgrind = False
|
||||
|
|
@ -307,7 +305,7 @@ if __name__ == "__main__":
|
|||
# "Then there's Windows"
|
||||
# Instantiate a Server(TestHTTPRequestHandler) on the first free port
|
||||
# in the specified port range.
|
||||
httpd, port = freeport(xrange(8000, 8020), make_server)
|
||||
httpd, port = freeport(range(8000, 8020), make_server)
|
||||
|
||||
# Pass the selected port number to the subject test program via the
|
||||
# environment. We don't want to impose requirements on the test program's
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
|
|||
llassert(0);
|
||||
}
|
||||
|
||||
if (prefix.empty())
|
||||
if (prefix.empty() && location != LL_PATH_NONE) // <FS:Beq/> avoid pointless warning when LL_PATH_NONE is used.
|
||||
{
|
||||
LL_WARNS() << ELLPathToString(location)
|
||||
<< ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
|
||||
|
|
|
|||
|
|
@ -37,15 +37,22 @@
|
|||
struct FolderEntry : public LLDictionaryEntry
|
||||
{
|
||||
FolderEntry(const std::string &type_name, // 8 character limit!
|
||||
bool is_protected) // can the viewer change categories of this type?
|
||||
bool is_protected, // can the viewer change categories of this type?
|
||||
bool is_automatic, // always made before first login?
|
||||
bool is_singleton // should exist as a unique copy under root
|
||||
)
|
||||
:
|
||||
LLDictionaryEntry(type_name),
|
||||
mIsProtected(is_protected)
|
||||
mIsProtected(is_protected),
|
||||
mIsAutomatic(is_automatic),
|
||||
mIsSingleton(is_singleton)
|
||||
{
|
||||
llassert(type_name.length() <= 8);
|
||||
}
|
||||
|
||||
const bool mIsProtected;
|
||||
const bool mIsAutomatic;
|
||||
const bool mIsSingleton;
|
||||
};
|
||||
|
||||
class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
|
||||
|
|
@ -59,52 +66,66 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
// Folder types
|
||||
//
|
||||
// PROTECTED means that folders of this type can't be moved, deleted
|
||||
// or otherwise modified by the viewer.
|
||||
//
|
||||
// SINGLETON means that there should always be exactly one folder of
|
||||
// this type, and it should be the root or a child of the root. This
|
||||
// is true for most types of folders.
|
||||
//
|
||||
// AUTOMATIC means that a copy of this folder should be created under
|
||||
// the root before the user ever logs in, and should never be created
|
||||
// from the viewer. A missing AUTOMATIC folder should be treated as a
|
||||
// fatal error by the viewer, since it indicates either corrupted
|
||||
// inventory or a failure in the inventory services.
|
||||
//
|
||||
LLFolderDictionary::LLFolderDictionary()
|
||||
{
|
||||
// TYPE NAME PROTECTED
|
||||
// |-----------|---------|
|
||||
addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE));
|
||||
addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE));
|
||||
addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE));
|
||||
addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE));
|
||||
addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE));
|
||||
addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE));
|
||||
addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE));
|
||||
addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", TRUE));
|
||||
addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE));
|
||||
addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE));
|
||||
addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE));
|
||||
addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE));
|
||||
addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE));
|
||||
addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE));
|
||||
addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE));
|
||||
addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE));
|
||||
// TYPE NAME, PROTECTED, AUTOMATIC, SINGLETON
|
||||
addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE, TRUE, FALSE));
|
||||
addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE, FALSE, FALSE));
|
||||
addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE, FALSE, TRUE));
|
||||
addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE, TRUE, TRUE));
|
||||
addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE, FALSE, TRUE));
|
||||
|
||||
for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++)
|
||||
{
|
||||
addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE));
|
||||
addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE, FALSE, FALSE)); // Not used
|
||||
}
|
||||
|
||||
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE));
|
||||
addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE));
|
||||
addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE));
|
||||
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE, FALSE, TRUE));
|
||||
addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE, FALSE, FALSE));
|
||||
addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE, FALSE, TRUE));
|
||||
|
||||
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
|
||||
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE, FALSE, FALSE)); // Not used?
|
||||
|
||||
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
|
||||
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", FALSE)); // <FS:Ansariel> Make obsolete Merchant Outbox folder deletable
|
||||
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE, FALSE, TRUE));
|
||||
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", FALSE, FALSE, FALSE)); // <FS:Ansariel> Make obsolete Merchant Outbox folder deletable
|
||||
|
||||
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
|
||||
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE, FALSE, FALSE));
|
||||
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE));
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE));
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE));
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE, FALSE, FALSE));
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE, FALSE, FALSE));
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE, FALSE, FALSE));
|
||||
|
||||
addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE));
|
||||
addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE, FALSE, TRUE));
|
||||
|
||||
addEntry(LLFolderType::FT_MY_SUITCASE, new FolderEntry("suitcase", TRUE)); // <FS:Ansariel> OpenSim HG-support
|
||||
addEntry(LLFolderType::FT_MY_SUITCASE, new FolderEntry("suitcase", TRUE, FALSE, TRUE)); // <FS:Ansariel> OpenSim HG-support
|
||||
|
||||
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
|
||||
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE, FALSE, FALSE));
|
||||
};
|
||||
|
||||
// static
|
||||
|
|
@ -128,8 +149,8 @@ const std::string &LLFolderType::lookup(LLFolderType::EType folder_type)
|
|||
}
|
||||
|
||||
// static
|
||||
// Only ensembles and plain folders aren't protected. "Protected" means
|
||||
// you can't change certain properties such as their type.
|
||||
// Only plain folders and a few other types aren't protected. "Protected" means
|
||||
// you can't move, deleted, or change certain properties such as their type.
|
||||
bool LLFolderType::lookupIsProtectedType(EType folder_type)
|
||||
{
|
||||
const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
|
||||
|
|
@ -140,6 +161,32 @@ bool LLFolderType::lookupIsProtectedType(EType folder_type)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
// Is this folder type automatically created outside the viewer?
|
||||
bool LLFolderType::lookupIsAutomaticType(EType folder_type)
|
||||
{
|
||||
const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
|
||||
const FolderEntry *entry = dict->lookup(folder_type);
|
||||
if (entry)
|
||||
{
|
||||
return entry->mIsAutomatic;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
// Should this folder always exist as a single copy under (or as) the root?
|
||||
bool LLFolderType::lookupIsSingletonType(EType folder_type)
|
||||
{
|
||||
const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
|
||||
const FolderEntry *entry = dict->lookup(folder_type);
|
||||
if (entry)
|
||||
{
|
||||
return entry->mIsSingleton;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLFolderType::lookupIsEnsembleType(EType folder_type)
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ public:
|
|||
static const std::string& lookup(EType folder_type);
|
||||
|
||||
static bool lookupIsProtectedType(EType folder_type);
|
||||
static bool lookupIsAutomaticType(EType folder_type);
|
||||
static bool lookupIsSingletonType(EType folder_type);
|
||||
static bool lookupIsEnsembleType(EType folder_type);
|
||||
|
||||
static LLAssetType::EType folderTypeToAssetType(LLFolderType::EType folder_type);
|
||||
|
|
|
|||
|
|
@ -2458,7 +2458,14 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
|
|||
|
||||
|
||||
//copy out indices
|
||||
face.resizeIndices(idx.size()/2);
|
||||
S32 num_indices = idx.size() / 2;
|
||||
face.resizeIndices(num_indices);
|
||||
|
||||
if (num_indices > 2 && !face.mIndices)
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate " << num_indices << " indices for face index: " << i << " Total: " << face_count << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (idx.empty() || face.mNumIndices < 3)
|
||||
{ //why is there an empty index list?
|
||||
|
|
@ -2477,6 +2484,13 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
|
|||
U32 num_verts = pos.size()/(3*2);
|
||||
face.resizeVertices(num_verts);
|
||||
|
||||
if (num_verts > 0 && !face.mPositions)
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate " << num_verts << " vertices for face index: " << i << " Total: " << face_count << LL_ENDL;
|
||||
face.resizeIndices(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
LLVector3 minp;
|
||||
LLVector3 maxp;
|
||||
LLVector2 min_tc;
|
||||
|
|
@ -2578,6 +2592,13 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
|
|||
if (mdl[i].has("Weights"))
|
||||
{
|
||||
face.allocateWeights(num_verts);
|
||||
if (!face.mWeights && num_verts)
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate " << num_verts << " weights for face index: " << i << " Total: " << face_count << LL_ENDL;
|
||||
face.resizeIndices(0);
|
||||
face.resizeVertices(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
LLSD::Binary weights = mdl[i]["Weights"];
|
||||
|
||||
|
|
@ -5376,22 +5397,23 @@ bool LLVolumeFace::cacheOptimize()
|
|||
{
|
||||
triangle_data.resize(mNumIndices / 3);
|
||||
vertex_data.resize(mNumVertices);
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LL_WARNS("LLVOLUME") << "Resize failed" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < mNumIndices; i++)
|
||||
{ //populate vertex data and triangle data arrays
|
||||
U16 idx = mIndices[i];
|
||||
U32 tri_idx = i/3;
|
||||
for (U32 i = 0; i < mNumIndices; i++)
|
||||
{ //populate vertex data and triangle data arrays
|
||||
U16 idx = mIndices[i];
|
||||
U32 tri_idx = i / 3;
|
||||
|
||||
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
|
||||
vertex_data[idx].mIdx = idx;
|
||||
triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]);
|
||||
}
|
||||
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
|
||||
vertex_data[idx].mIdx = idx;
|
||||
triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]);
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
// resize or push_back failed
|
||||
LL_WARNS("LLVOLUME") << "Resize for " << mNumVertices << " vertices failed" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*F32 pre_acmr = 1.f;
|
||||
//measure cache misses from before rebuild
|
||||
|
|
@ -6435,8 +6457,18 @@ void LLVolumeFace::resizeVertices(S32 num_verts)
|
|||
mTexCoords = NULL;
|
||||
}
|
||||
|
||||
mNumVertices = num_verts;
|
||||
mNumAllocatedVertices = num_verts;
|
||||
|
||||
if (mPositions)
|
||||
{
|
||||
mNumVertices = num_verts;
|
||||
mNumAllocatedVertices = num_verts;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either num_verts is zero or allocation failure
|
||||
mNumVertices = 0;
|
||||
mNumAllocatedVertices = 0;
|
||||
}
|
||||
|
||||
// Force update
|
||||
mJointRiggingInfoTab.clear();
|
||||
|
|
@ -6537,7 +6569,15 @@ void LLVolumeFace::resizeIndices(S32 num_indices)
|
|||
mIndices = NULL;
|
||||
}
|
||||
|
||||
mNumIndices = num_indices;
|
||||
if (mIndices)
|
||||
{
|
||||
mNumIndices = num_indices;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either num_indices is zero or allocation failure
|
||||
mNumIndices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LLVolumeFace::pushIndex(const U16& idx)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@
|
|||
#include "llstring.h"
|
||||
#include "llstringtable.h"
|
||||
|
||||
// <FS:ND> Suppress warnings about the string fiddling
|
||||
#if LL_LINUX
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
#endif
|
||||
// </FS:ND>
|
||||
|
||||
// Anonymous enumeration to provide constants in this file.
|
||||
// *NOTE: These values may be used in sscanf statements below as their
|
||||
// value-1, so search for '2047' if you cange NV_BUFFER_LEN or '63' if
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file test_llsdmessage_peer.py
|
||||
@author Nat Goodspeed
|
||||
|
|
@ -31,7 +31,7 @@ $/LicenseInfo$
|
|||
|
||||
import os
|
||||
import sys
|
||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
from llbase.fastest_elementtree import parse as xml_parse
|
||||
from llbase import llsd
|
||||
|
|
@ -165,7 +165,7 @@ if __name__ == "__main__":
|
|||
# "Then there's Windows"
|
||||
# Instantiate a Server(TestHTTPRequestHandler) on the first free port
|
||||
# in the specified port range.
|
||||
httpd, port = freeport(xrange(8000, 8020), make_server)
|
||||
httpd, port = freeport(range(8000, 8020), make_server)
|
||||
|
||||
# Pass the selected port number to the subject test program via the
|
||||
# environment. We don't want to impose requirements on the test program's
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""\
|
||||
@file testrunner.py
|
||||
@author Nat Goodspeed
|
||||
|
|
@ -41,7 +41,7 @@ VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE)
|
|||
|
||||
if VERBOSE:
|
||||
def debug(fmt, *args):
|
||||
print fmt % args
|
||||
print(fmt % args)
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
debug = lambda *args: None
|
||||
|
|
@ -99,14 +99,14 @@ def freeport(portlist, expr):
|
|||
# error because we can't return meaningful values. We have no 'port',
|
||||
# therefore no 'expr(port)'.
|
||||
portiter = iter(portlist)
|
||||
port = portiter.next()
|
||||
port = next(portiter)
|
||||
|
||||
while True:
|
||||
try:
|
||||
# If this value of port works, return as promised.
|
||||
value = expr(port)
|
||||
|
||||
except socket.error, err:
|
||||
except socket.error as err:
|
||||
# Anything other than 'Address already in use', propagate
|
||||
if err.args[0] != errno.EADDRINUSE:
|
||||
raise
|
||||
|
|
@ -117,9 +117,9 @@ def freeport(portlist, expr):
|
|||
type, value, tb = sys.exc_info()
|
||||
try:
|
||||
try:
|
||||
port = portiter.next()
|
||||
port = next(portiter)
|
||||
except StopIteration:
|
||||
raise type, value, tb
|
||||
raise type(value).with_traceback(tb)
|
||||
finally:
|
||||
# Clean up local traceback, see docs for sys.exc_info()
|
||||
del tb
|
||||
|
|
@ -138,7 +138,7 @@ def freeport(portlist, expr):
|
|||
# If we've actually arrived at this point, portiter.next() delivered a
|
||||
# new port value. Loop back to pass that to expr(port).
|
||||
|
||||
except Exception, err:
|
||||
except Exception as err:
|
||||
debug("*** freeport() raising %s: %s", err.__class__.__name__, err)
|
||||
raise
|
||||
|
||||
|
|
@ -227,13 +227,13 @@ def test_freeport():
|
|||
def exc(exception_class, *args):
|
||||
try:
|
||||
yield
|
||||
except exception_class, err:
|
||||
except exception_class as err:
|
||||
for i, expected_arg in enumerate(args):
|
||||
assert expected_arg == err.args[i], \
|
||||
"Raised %s, but args[%s] is %r instead of %r" % \
|
||||
(err.__class__.__name__, i, err.args[i], expected_arg)
|
||||
print "Caught expected exception %s(%s)" % \
|
||||
(err.__class__.__name__, ', '.join(repr(arg) for arg in err.args))
|
||||
print("Caught expected exception %s(%s)" % \
|
||||
(err.__class__.__name__, ', '.join(repr(arg) for arg in err.args)))
|
||||
else:
|
||||
assert False, "Failed to raise " + exception_class.__class__.__name__
|
||||
|
||||
|
|
@ -270,18 +270,18 @@ def test_freeport():
|
|||
# This is the magic exception that should prompt us to retry
|
||||
inuse = socket.error(errno.EADDRINUSE, 'Address already in use')
|
||||
# Get the iterator to our ports list so we can check later if we've used all
|
||||
ports = iter(xrange(5))
|
||||
ports = iter(range(5))
|
||||
with exc(socket.error, errno.EADDRINUSE):
|
||||
freeport(ports, lambda port: raiser(inuse))
|
||||
# did we entirely exhaust 'ports'?
|
||||
with exc(StopIteration):
|
||||
ports.next()
|
||||
next(ports)
|
||||
|
||||
ports = iter(xrange(2))
|
||||
ports = iter(range(2))
|
||||
# Any exception but EADDRINUSE should quit immediately
|
||||
with exc(SomeError):
|
||||
freeport(ports, lambda port: raiser(SomeError()))
|
||||
assert_equals(ports.next(), 1)
|
||||
assert_equals(next(ports), 1)
|
||||
|
||||
# ----------- freeport() with platform-dependent socket stuff ------------
|
||||
# This is what we should've had unit tests to begin with (see CHOP-661).
|
||||
|
|
@ -290,14 +290,14 @@ def test_freeport():
|
|||
sock.bind(('127.0.0.1', port))
|
||||
return sock
|
||||
|
||||
bound0, port0 = freeport(xrange(7777, 7780), newbind)
|
||||
bound0, port0 = freeport(range(7777, 7780), newbind)
|
||||
assert_equals(port0, 7777)
|
||||
bound1, port1 = freeport(xrange(7777, 7780), newbind)
|
||||
bound1, port1 = freeport(range(7777, 7780), newbind)
|
||||
assert_equals(port1, 7778)
|
||||
bound2, port2 = freeport(xrange(7777, 7780), newbind)
|
||||
bound2, port2 = freeport(range(7777, 7780), newbind)
|
||||
assert_equals(port2, 7779)
|
||||
with exc(socket.error, errno.EADDRINUSE):
|
||||
bound3, port3 = freeport(xrange(7777, 7780), newbind)
|
||||
bound3, port3 = freeport(range(7777, 7780), newbind)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_freeport()
|
||||
|
|
|
|||
|
|
@ -82,8 +82,29 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
|
||||
class LLPluginProcessCreationThread : public LLThread
|
||||
{
|
||||
public:
|
||||
LLPluginProcessCreationThread(LLPluginProcessParent *parent) :
|
||||
LLThread("LLPluginProcessCreationThread", gAPRPoolp),
|
||||
pParent(parent)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
// Inherited from LLThread, should run once
|
||||
/*virtual*/ void run(void)
|
||||
{
|
||||
pParent->createPluginProcess();
|
||||
}
|
||||
private:
|
||||
LLPluginProcessParent *pParent;
|
||||
|
||||
};
|
||||
|
||||
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
|
||||
mIncomingQueueMutex()
|
||||
mIncomingQueueMutex(),
|
||||
pProcessCreationThread(NULL)
|
||||
{
|
||||
if(!sInstancesMutex)
|
||||
{
|
||||
|
|
@ -112,6 +133,18 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
|
|||
LLPluginProcessParent::~LLPluginProcessParent()
|
||||
{
|
||||
LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
|
||||
if (pProcessCreationThread)
|
||||
{
|
||||
if (!pProcessCreationThread->isStopped())
|
||||
{
|
||||
// Shouldn't happen at this stage
|
||||
LL_WARNS("Plugin") << "Shutting down active pProcessCreationThread" << LL_ENDL;
|
||||
pProcessCreationThread->shutdown();
|
||||
ms_sleep(20);
|
||||
}
|
||||
delete pProcessCreationThread;
|
||||
pProcessCreationThread = NULL;
|
||||
}
|
||||
|
||||
// Destroy any remaining shared memory regions
|
||||
sharedMemoryRegionsType::iterator iter;
|
||||
|
|
@ -162,6 +195,7 @@ void LLPluginProcessParent::shutdown()
|
|||
&& state != STATE_ERROR)
|
||||
{
|
||||
(*it).second->setState(STATE_GOODBYE);
|
||||
(*it).second->mOwner = NULL;
|
||||
}
|
||||
if (state != STATE_DONE)
|
||||
{
|
||||
|
|
@ -321,6 +355,35 @@ bool LLPluginProcessParent::accept()
|
|||
return result;
|
||||
}
|
||||
|
||||
bool LLPluginProcessParent::createPluginProcess()
|
||||
{
|
||||
if (!mProcess)
|
||||
{
|
||||
// Only argument to the launcher is the port number we're listening on
|
||||
mProcessParams.args.add(stringize(mBoundPort));
|
||||
mProcess = LLProcess::create(mProcessParams);
|
||||
return mProcess != NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLPluginProcessParent::clearProcessCreationThread()
|
||||
{
|
||||
if (pProcessCreationThread)
|
||||
{
|
||||
if (!pProcessCreationThread->isStopped())
|
||||
{
|
||||
pProcessCreationThread->shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pProcessCreationThread;
|
||||
pProcessCreationThread = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPluginProcessParent::idle(void)
|
||||
{
|
||||
bool idle_again;
|
||||
|
|
@ -328,8 +391,9 @@ void LLPluginProcessParent::idle(void)
|
|||
do
|
||||
{
|
||||
// process queued messages
|
||||
mIncomingQueueMutex.lock();
|
||||
while(!mIncomingQueue.empty())
|
||||
// Inside main thread, it is preferable not to block it on mutex.
|
||||
bool locked = mIncomingQueueMutex.trylock();
|
||||
while(locked && !mIncomingQueue.empty())
|
||||
{
|
||||
LLPluginMessage message = mIncomingQueue.front();
|
||||
mIncomingQueue.pop();
|
||||
|
|
@ -337,10 +401,13 @@ void LLPluginProcessParent::idle(void)
|
|||
|
||||
receiveMessage(message);
|
||||
|
||||
mIncomingQueueMutex.lock();
|
||||
locked = mIncomingQueueMutex.trylock();
|
||||
}
|
||||
|
||||
mIncomingQueueMutex.unlock();
|
||||
if (locked)
|
||||
{
|
||||
mIncomingQueueMutex.unlock();
|
||||
}
|
||||
|
||||
// Give time to network processing
|
||||
if(mMessagePipe)
|
||||
|
|
@ -349,7 +416,10 @@ void LLPluginProcessParent::idle(void)
|
|||
mMessagePipe->pumpOutput();
|
||||
|
||||
// Only do input processing here if this instance isn't in a pollset.
|
||||
if(!mPolledInput)
|
||||
// If viewer and plugin are both shutting down, don't process further
|
||||
// input, viewer won't be able to handle it.
|
||||
if(!mPolledInput
|
||||
&& !(mState >= STATE_GOODBYE && LLApp::isExiting()))
|
||||
{
|
||||
mMessagePipe->pumpInput();
|
||||
}
|
||||
|
|
@ -488,15 +558,30 @@ void LLPluginProcessParent::idle(void)
|
|||
case STATE_LISTENING:
|
||||
{
|
||||
// Launch the plugin process.
|
||||
if (mDebug && !pProcessCreationThread)
|
||||
{
|
||||
createPluginProcess();
|
||||
if (!mProcess)
|
||||
{
|
||||
errorState();
|
||||
}
|
||||
}
|
||||
else if (pProcessCreationThread == NULL)
|
||||
{
|
||||
// exe plugin process allocation can be hindered by a number
|
||||
// of factors, don't hold whole viewer because of it, use thread
|
||||
pProcessCreationThread = new LLPluginProcessCreationThread(this);
|
||||
pProcessCreationThread->start();
|
||||
}
|
||||
else if (!mProcess && pProcessCreationThread->isStopped())
|
||||
{
|
||||
delete pProcessCreationThread;
|
||||
pProcessCreationThread = NULL;
|
||||
errorState();
|
||||
}
|
||||
|
||||
|
||||
// Only argument to the launcher is the port number we're listening on
|
||||
mProcessParams.args.add(stringize(mBoundPort));
|
||||
|
||||
if (! (mProcess = LLProcess::create(mProcessParams)))
|
||||
{
|
||||
errorState();
|
||||
}
|
||||
else
|
||||
if (mProcess)
|
||||
{
|
||||
if(mDebug)
|
||||
{
|
||||
|
|
@ -525,6 +610,15 @@ void LLPluginProcessParent::idle(void)
|
|||
// This will allow us to time out if the process never starts.
|
||||
mHeartbeat.start();
|
||||
mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
|
||||
|
||||
// pProcessCreationThread should have stopped by this point,
|
||||
// but check just in case it paused on statistics sync
|
||||
if (pProcessCreationThread && pProcessCreationThread->isStopped())
|
||||
{
|
||||
delete pProcessCreationThread;
|
||||
pProcessCreationThread = NULL;
|
||||
}
|
||||
|
||||
setState(STATE_LAUNCHED);
|
||||
}
|
||||
}
|
||||
|
|
@ -627,6 +721,7 @@ void LLPluginProcessParent::idle(void)
|
|||
killSockets();
|
||||
setState(STATE_DONE);
|
||||
dirtyPollSet();
|
||||
clearProcessCreationThread();
|
||||
break;
|
||||
|
||||
case STATE_DONE:
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ public:
|
|||
const std::string &plugin_filename,
|
||||
bool debug);
|
||||
|
||||
// Creates a process
|
||||
// returns true if process already exists or if created,
|
||||
// false if failed to create
|
||||
bool createPluginProcess();
|
||||
|
||||
void idle(void);
|
||||
|
||||
// returns true if the plugin is on its way to steady state
|
||||
|
|
@ -163,12 +168,15 @@ private:
|
|||
|
||||
bool accept();
|
||||
|
||||
void clearProcessCreationThread();
|
||||
|
||||
LLSocket::ptr_t mListenSocket;
|
||||
LLSocket::ptr_t mSocket;
|
||||
U32 mBoundPort;
|
||||
|
||||
LLProcess::Params mProcessParams;
|
||||
LLProcessPtr mProcess;
|
||||
LLThread *pProcessCreationThread;
|
||||
|
||||
std::string mPluginFile;
|
||||
std::string mPluginDir;
|
||||
|
|
|
|||
|
|
@ -242,6 +242,17 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
|
|||
}
|
||||
|
||||
LLVolumeFace::VertexMapData::PointMap point_map;
|
||||
|
||||
if (idx_stride <= 0
|
||||
|| (pos_source && pos_offset >= idx_stride)
|
||||
|| (tc_source && tc_offset >= idx_stride)
|
||||
|| (norm_source && norm_offset >= idx_stride))
|
||||
{
|
||||
// Looks like these offsets should fit inside idx_stride
|
||||
// Might be good idea to also check idx.getCount()%idx_stride != 0
|
||||
LL_WARNS() << "Invalid pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
|
||||
return LLModel::BAD_ELEMENT;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < idx.getCount(); i += idx_stride)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -606,6 +606,58 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
// Same as toggleInstanceOrBringToFront but does not close floater.
|
||||
// unlike showInstance() does not trigger onOpen() if already open
|
||||
void LLFloaterReg::showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key)
|
||||
{
|
||||
std::string name = sdname.asString();
|
||||
LLFloater* instance = getInstance(name, key);
|
||||
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// If hosted, we need to take that into account
|
||||
LLFloater* host = instance->getHost();
|
||||
|
||||
if (host)
|
||||
{
|
||||
if (host->isMinimized() || !host->isShown() || !host->isFrontmost())
|
||||
{
|
||||
host->setMinimized(FALSE);
|
||||
instance->openFloater(key);
|
||||
instance->setVisibleAndFrontmost(true, key);
|
||||
}
|
||||
else if (!instance->getVisible())
|
||||
{
|
||||
instance->openFloater(key);
|
||||
instance->setVisibleAndFrontmost(true, key);
|
||||
instance->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (instance->isMinimized())
|
||||
{
|
||||
instance->setMinimized(FALSE);
|
||||
instance->setVisibleAndFrontmost(true, key);
|
||||
}
|
||||
else if (!instance->isShown())
|
||||
{
|
||||
instance->openFloater(key);
|
||||
instance->setVisibleAndFrontmost(true, key);
|
||||
}
|
||||
else if (!instance->isFrontmost())
|
||||
{
|
||||
instance->setVisibleAndFrontmost(true, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLFloaterReg::getVisibleFloaterInstanceCount()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ public:
|
|||
|
||||
// Callback wrappers
|
||||
static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD());
|
||||
static void showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD());
|
||||
|
||||
// Typed find / get / show
|
||||
template <class T>
|
||||
|
|
|
|||
|
|
@ -261,6 +261,8 @@ LLFolderView::LLFolderView(const Params& p)
|
|||
mPopupMenuHandle = menu->getHandle();
|
||||
|
||||
mViewModelItem->openItem();
|
||||
|
||||
mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited.
|
||||
}
|
||||
|
||||
// Destroys the object
|
||||
|
|
|
|||
|
|
@ -139,7 +139,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
|
|||
mCutGeneration(0),
|
||||
mLabelStyle( LLFontGL::NORMAL ),
|
||||
mHasVisibleChildren(FALSE),
|
||||
mIsFolderComplete(true),
|
||||
mLocalIndentation(p.folder_indentation),
|
||||
mIndentation(0),
|
||||
mItemHeight(p.item_height),
|
||||
|
|
@ -1118,11 +1117,11 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
|
|||
mCurHeight(0.f),
|
||||
mTargetHeight(0.f),
|
||||
mAutoOpenCountdown(0.f),
|
||||
mIsFolderComplete(false), // folder might have children that are not loaded yet.
|
||||
mAreChildrenInited(false), // folder might have children that are not built yet.
|
||||
mLastArrangeGeneration( -1 ),
|
||||
mLastCalculatedWidth(0)
|
||||
{
|
||||
// folder might have children that are not loaded yet. Mark it as incomplete until chance to check it.
|
||||
mIsFolderComplete = false;
|
||||
}
|
||||
|
||||
void LLFolderViewFolder::updateLabelRotation()
|
||||
|
|
@ -1178,13 +1177,16 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
|
|||
{
|
||||
// Sort before laying out contents
|
||||
// Note that we sort from the root (CHUI-849)
|
||||
getRoot()->getFolderViewModel()->sort(this);
|
||||
if (mAreChildrenInited)
|
||||
{
|
||||
getRoot()->getFolderViewModel()->sort(this);
|
||||
}
|
||||
|
||||
LL_RECORD_BLOCK_TIME(FTM_ARRANGE);
|
||||
|
||||
// evaluate mHasVisibleChildren
|
||||
mHasVisibleChildren = false;
|
||||
if (getViewModelItem()->descendantsPassedFilter())
|
||||
if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter())
|
||||
{
|
||||
// We have to verify that there's at least one child that's not filtered out
|
||||
bool found = false;
|
||||
|
|
@ -1210,7 +1212,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
|
|||
|
||||
mHasVisibleChildren = found;
|
||||
}
|
||||
if (!mIsFolderComplete)
|
||||
if (!mIsFolderComplete && mAreChildrenInited)
|
||||
{
|
||||
mIsFolderComplete = getFolderViewModel()->isFolderComplete(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ protected:
|
|||
F32 mControlLabelRotation;
|
||||
LLFolderView* mRoot;
|
||||
bool mHasVisibleChildren,
|
||||
mIsFolderComplete, // indicates that some children were not loaded/added yet
|
||||
mIsCurSelection,
|
||||
mDragAndDropTarget,
|
||||
mIsMouseOverTitle,
|
||||
|
|
@ -229,7 +228,10 @@ public:
|
|||
BOOL hasVisibleChildren() { return mHasVisibleChildren; }
|
||||
|
||||
// true if object can't have children
|
||||
BOOL isFolderComplete() { return mIsFolderComplete; }
|
||||
virtual bool isFolderComplete() { return true; }
|
||||
// true if object can't have children
|
||||
virtual bool areChildrenInited() { return true; }
|
||||
virtual void setChildrenInited(bool inited) { }
|
||||
|
||||
// Call through to the viewed object and return true if it can be
|
||||
// removed. Returns true if it's removed.
|
||||
|
|
@ -349,6 +351,8 @@ protected:
|
|||
S32 mLastArrangeGeneration;
|
||||
S32 mLastCalculatedWidth;
|
||||
// bool mNeedsSort; <FS:ND/> Unused.
|
||||
bool mIsFolderComplete; // indicates that some children were not loaded/added yet
|
||||
bool mAreChildrenInited; // indicates that no children were initialized
|
||||
|
||||
public:
|
||||
typedef enum e_recurse_type
|
||||
|
|
@ -400,6 +404,13 @@ public:
|
|||
// destroys this folder, and all children
|
||||
virtual void destroyView();
|
||||
|
||||
// whether known children are fully loaded (arrange sets to true)
|
||||
virtual bool isFolderComplete() { return mIsFolderComplete; }
|
||||
|
||||
// whether known children are fully built
|
||||
virtual bool areChildrenInited() { return mAreChildrenInited; }
|
||||
virtual void setChildrenInited(bool inited) { mAreChildrenInited = inited; }
|
||||
|
||||
// extractItem() removes the specified item from the folder, but
|
||||
// doesn't delete it.
|
||||
virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true);
|
||||
|
|
|
|||
|
|
@ -500,8 +500,7 @@ LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) :
|
|||
mResponderObj(NULL),
|
||||
mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()),
|
||||
mOfferFromAgent(p.offer_from_agent),
|
||||
mIsDND(p.is_dnd),
|
||||
mIsFromStorage(false)// <FS:Ansariel> FIRE-11339: Persisted group notifications get logged to IM on each login
|
||||
mIsDND(p.is_dnd)
|
||||
{
|
||||
if (p.functor.name.isChosen())
|
||||
{
|
||||
|
|
@ -1710,6 +1709,20 @@ void LLNotifications::add(const LLNotificationPtr pNotif)
|
|||
updateItem(LLSD().with("sigtype", "add").with("id", pNotif->id()), pNotif);
|
||||
}
|
||||
|
||||
void LLNotifications::load(const LLNotificationPtr pNotif)
|
||||
{
|
||||
if (pNotif == NULL) return;
|
||||
|
||||
// first see if we already have it -- if so, that's a problem
|
||||
LLNotificationSet::iterator it=mItems.find(pNotif);
|
||||
if (it != mItems.end())
|
||||
{
|
||||
LL_ERRS() << "Notification loaded a second time to the master notification channel." << LL_ENDL;
|
||||
}
|
||||
|
||||
updateItem(LLSD().with("sigtype", "load").with("id", pNotif->id()), pNotif);
|
||||
}
|
||||
|
||||
void LLNotifications::cancel(LLNotificationPtr pNotif)
|
||||
{
|
||||
if (pNotif == NULL || pNotif->isCancelled()) return;
|
||||
|
|
|
|||
|
|
@ -399,7 +399,6 @@ private:
|
|||
LLNotificationResponderPtr mResponder;
|
||||
bool mOfferFromAgent;
|
||||
bool mIsDND;
|
||||
bool mIsFromStorage; // <FS:Ansariel> FIRE-11339: Persisted group notifications get logged to IM on each login
|
||||
|
||||
// a reference to the template
|
||||
LLNotificationTemplatePtr mTemplatep;
|
||||
|
|
@ -557,18 +556,6 @@ public:
|
|||
mIsDND = flag;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> FIRE-11339: Persisted group notifications get logged to IM on each login
|
||||
bool isFromStorage() const
|
||||
{
|
||||
return mIsFromStorage;
|
||||
}
|
||||
|
||||
void setIsFromStorage(bool logged)
|
||||
{
|
||||
mIsFromStorage = logged;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
std::string getType() const;
|
||||
std::string getMessage() const;
|
||||
std::string getFooter() const;
|
||||
|
|
@ -936,6 +923,7 @@ public:
|
|||
LLNotificationPtr add(const LLNotification::Params& p);
|
||||
|
||||
void add(const LLNotificationPtr pNotif);
|
||||
void load(const LLNotificationPtr pNotif);
|
||||
void cancel(LLNotificationPtr pNotif);
|
||||
void cancelByName(const std::string& name);
|
||||
void cancelByOwner(const LLUUID ownerId);
|
||||
|
|
@ -1139,6 +1127,11 @@ private:
|
|||
mHistory.push_back(p);
|
||||
}
|
||||
|
||||
void onLoad(LLNotificationPtr p)
|
||||
{
|
||||
mHistory.push_back(p);
|
||||
}
|
||||
|
||||
std::vector<LLNotificationPtr> mHistory;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,14 @@ const LLSD LLScrollListCell::getValue() const
|
|||
return LLStringUtil::null;
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
const LLSD LLScrollListCell::getAltValue() const
|
||||
{
|
||||
return LLStringUtil::null;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLScrollListIcon
|
||||
//
|
||||
|
|
@ -245,6 +253,7 @@ U32 LLScrollListText::sCount = 0;
|
|||
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
|
||||
: LLScrollListCell(p),
|
||||
mText(p.label.isProvided() ? p.label() : p.value().asString()),
|
||||
mAltText(p.alt_value().asString()),
|
||||
mFont(p.font),
|
||||
mColor(p.color),
|
||||
mUseColor(p.color.isProvided()),
|
||||
|
|
@ -347,10 +356,22 @@ void LLScrollListText::setValue(const LLSD& text)
|
|||
setText(text.asString());
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLScrollListText::setAltValue(const LLSD& text)
|
||||
{
|
||||
mAltText = text.asString();
|
||||
}
|
||||
|
||||
//virtual
|
||||
const LLSD LLScrollListText::getValue() const
|
||||
{
|
||||
return LLSD(mText.getString());
|
||||
return LLSD(mText.getString());
|
||||
}
|
||||
|
||||
//virtual
|
||||
const LLSD LLScrollListText::getAltValue() const
|
||||
{
|
||||
return LLSD(mAltText.getString());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
|
||||
Optional<void*> userdata;
|
||||
Optional<LLSD> value; // state of checkbox, icon id/name, date
|
||||
Optional<LLSD> alt_value;
|
||||
Optional<std::string> label; // description or text
|
||||
Optional<std::string> tool_tip;
|
||||
|
||||
|
|
@ -77,6 +78,7 @@ public:
|
|||
enabled("enabled", true),
|
||||
visible("visible", true),
|
||||
value("value"),
|
||||
alt_value("alt_value", ""),
|
||||
label("label"),
|
||||
tool_tip("tool_tip", ""),
|
||||
font("font", LLFontGL::getFontSansSerifSmall()),
|
||||
|
|
@ -99,7 +101,9 @@ public:
|
|||
virtual S32 getContentWidth() const { return 0; }
|
||||
virtual S32 getHeight() const { return 0; }
|
||||
virtual const LLSD getValue() const;
|
||||
virtual const LLSD getAltValue() const;
|
||||
virtual void setValue(const LLSD& value) { }
|
||||
virtual void setAltValue(const LLSD& value) { }
|
||||
virtual const std::string &getToolTip() const { return mToolTip; }
|
||||
virtual void setToolTip(const std::string &str) { mToolTip = str; }
|
||||
virtual BOOL getVisible() const { return TRUE; }
|
||||
|
|
@ -139,7 +143,9 @@ public:
|
|||
/*virtual*/ S32 getContentWidth() const;
|
||||
/*virtual*/ S32 getHeight() const;
|
||||
/*virtual*/ void setValue(const LLSD& value);
|
||||
/*virtual*/ void setAltValue(const LLSD& value);
|
||||
/*virtual*/ const LLSD getValue() const;
|
||||
/*virtual*/ const LLSD getAltValue() const;
|
||||
/*virtual*/ BOOL getVisible() const;
|
||||
/*virtual*/ void highlightText(S32 offset, S32 num_chars);
|
||||
|
||||
|
|
@ -158,6 +164,7 @@ public:
|
|||
|
||||
protected:
|
||||
LLUIString mText;
|
||||
LLUIString mAltText;
|
||||
S32 mTextWidth;
|
||||
const LLFontGL* mFont;
|
||||
LLColor4 mColor;
|
||||
|
|
|
|||
|
|
@ -68,9 +68,10 @@ static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
|
|||
// local structures & classes.
|
||||
struct SortScrollListItem
|
||||
{
|
||||
SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal)
|
||||
SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal, bool alternate_sort)
|
||||
: mSortOrders(sort_orders)
|
||||
, mSortSignal(sort_signal)
|
||||
, mAltSort(alternate_sort)
|
||||
{}
|
||||
|
||||
bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
|
||||
|
|
@ -95,7 +96,14 @@ struct SortScrollListItem
|
|||
}
|
||||
else
|
||||
{
|
||||
sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
|
||||
if (mAltSort && !cell1->getAltValue().asString().empty() && !cell2->getAltValue().asString().empty())
|
||||
{
|
||||
sort_result = order * LLStringUtil::compareDict(cell1->getAltValue().asString(), cell2->getAltValue().asString());
|
||||
}
|
||||
else
|
||||
{
|
||||
sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
|
||||
}
|
||||
}
|
||||
if (sort_result != 0)
|
||||
{
|
||||
|
|
@ -111,6 +119,7 @@ struct SortScrollListItem
|
|||
typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
|
||||
const LLScrollListCtrl::sort_signal_t* mSortSignal;
|
||||
const sort_order_t& mSortOrders;
|
||||
const bool mAltSort;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -219,6 +228,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
|
|||
mSearchColumn(p.search_column),
|
||||
mColumnPadding(p.column_padding),
|
||||
mRowPadding(p.row_padding),
|
||||
mAlternateSort(false),
|
||||
mContextMenuType(MENU_NONE),
|
||||
mIsFriendSignal(NULL),
|
||||
// <FS:Ansariel> Fix for FS-specific people list (radar)
|
||||
|
|
@ -400,8 +410,7 @@ LLScrollListCtrl::~LLScrollListCtrl()
|
|||
|
||||
std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
|
||||
mItemList.clear();
|
||||
std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer());
|
||||
mColumns.clear();
|
||||
clearColumns(); //clears columns and deletes headers
|
||||
delete mIsFriendSignal;
|
||||
}
|
||||
|
||||
|
|
@ -3098,7 +3107,7 @@ void LLScrollListCtrl::updateSort() const
|
|||
std::stable_sort(
|
||||
mItemList.begin(),
|
||||
mItemList.end(),
|
||||
SortScrollListItem(mSortColumns,mSortCallback));
|
||||
SortScrollListItem(mSortColumns,mSortCallback, mAlternateSort));
|
||||
|
||||
mSorted = true;
|
||||
}
|
||||
|
|
@ -3114,7 +3123,7 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending)
|
|||
std::stable_sort(
|
||||
mItemList.begin(),
|
||||
mItemList.end(),
|
||||
SortScrollListItem(sort_column,mSortCallback));
|
||||
SortScrollListItem(sort_column,mSortCallback,mAlternateSort));
|
||||
}
|
||||
|
||||
void LLScrollListCtrl::dirtyColumns()
|
||||
|
|
@ -3480,6 +3489,8 @@ void LLScrollListCtrl::clearColumns()
|
|||
|
||||
// <FS:Ansariel> Reset number of dynamic columns, too
|
||||
mNumDynamicWidthColumns = 0;
|
||||
|
||||
dirtyColumns(); // Clears mColumnsIndexed
|
||||
}
|
||||
|
||||
void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label)
|
||||
|
|
|
|||
|
|
@ -421,6 +421,8 @@ public:
|
|||
BOOL hasSortOrder() const;
|
||||
void clearSortOrder();
|
||||
|
||||
void setAlternateSort() { mAlternateSort = true; }
|
||||
|
||||
S32 selectMultiple( uuid_vec_t ids );
|
||||
// conceptually const, but mutates mItemList
|
||||
void updateSort() const;
|
||||
|
|
@ -519,6 +521,8 @@ private:
|
|||
bool mColumnsDirty;
|
||||
bool mColumnWidthsDirty;
|
||||
|
||||
bool mAlternateSort;
|
||||
|
||||
mutable item_list mItemList;
|
||||
|
||||
LLScrollListItem *mLastSelected;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ LLScrollListItem::LLScrollListItem( const Params& p )
|
|||
mSelectedIndex(-1),
|
||||
mEnabled(p.enabled),
|
||||
mUserdata(p.userdata),
|
||||
mItemValue(p.value)
|
||||
mItemValue(p.value),
|
||||
mItemAltValue(p.alt_value)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
Optional<bool> enabled;
|
||||
Optional<void*> userdata;
|
||||
Optional<LLSD> value;
|
||||
Optional<LLSD> alt_value;
|
||||
|
||||
Ignored name; // use for localization tools
|
||||
Ignored type;
|
||||
|
|
@ -65,6 +66,7 @@ public:
|
|||
Params()
|
||||
: enabled("enabled", true),
|
||||
value("value"),
|
||||
alt_value("alt_value"),
|
||||
name("name"),
|
||||
type("type"),
|
||||
length("length"),
|
||||
|
|
@ -97,6 +99,7 @@ public:
|
|||
|
||||
virtual LLUUID getUUID() const { return mItemValue.asUUID(); }
|
||||
LLSD getValue() const { return mItemValue; }
|
||||
LLSD getAltValue() const { return mItemAltValue; }
|
||||
|
||||
void setRect(LLRect rect) { mRectangle = rect; }
|
||||
LLRect getRect() const { return mRectangle; }
|
||||
|
|
@ -131,6 +134,7 @@ private:
|
|||
BOOL mEnabled;
|
||||
void* mUserdata;
|
||||
LLSD mItemValue;
|
||||
LLSD mItemAltValue;
|
||||
std::vector<LLScrollListCell *> mColumns;
|
||||
LLRect mRectangle;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1705,11 +1705,14 @@ void LLTextBase::reflow()
|
|||
{
|
||||
// find first element whose end comes after start_index
|
||||
line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
|
||||
line_start_index = iter->mDocIndexStart;
|
||||
line_count = iter->mLineNum;
|
||||
cur_top = iter->mRect.mTop;
|
||||
getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
|
||||
mLineInfoList.erase(iter, mLineInfoList.end());
|
||||
if (iter != mLineInfoList.end())
|
||||
{
|
||||
line_start_index = iter->mDocIndexStart;
|
||||
line_count = iter->mLineNum;
|
||||
cur_top = iter->mRect.mTop;
|
||||
getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
|
||||
mLineInfoList.erase(iter, mLineInfoList.end());
|
||||
}
|
||||
}
|
||||
|
||||
S32 line_height = 0;
|
||||
|
|
|
|||
|
|
@ -1177,7 +1177,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
|
|||
else
|
||||
{
|
||||
button->setFunctionName(commandp->executeFunctionName());
|
||||
LL_DEBUGS("UIUsage") << "button function name b -> " << commandp->executeFunctionName() << LL_ENDL; // <FS:Ansariel> Check enabled state of button before executing!
|
||||
LL_DEBUGS("UIUsage") << "button function name b -> " << commandp->executeFunctionName() << LL_ENDL;
|
||||
// <FS:Ansariel> Check enabled state of button before executing!
|
||||
//button->setCommitCallback(executeParam);
|
||||
LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam);
|
||||
button->setCommitCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2));
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ mHelpImpl(NULL)
|
|||
reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD()));
|
||||
reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD()));
|
||||
reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(), FALSE));
|
||||
reg.add("Floater.ShowOrBringToFront", boost::bind(&LLFloaterReg::showInstanceOrBringToFront, _2, LLSD()));
|
||||
reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD()));
|
||||
|
||||
// Button initialization callback for toggle buttons
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ if (LINUX)
|
|||
${LLXML_LIBRARIES}
|
||||
${UI_LIBRARIES} # for GTK
|
||||
${SDL_LIBRARY}
|
||||
fontconfig # For FCInit and other FC* functions.
|
||||
libfontconfig.a # For FCInit and other FC* functions.
|
||||
libfreetype.a
|
||||
)
|
||||
|
||||
list(APPEND viewer_SOURCE_FILES
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ ECursorType getCursorFromString(const std::string& cursor_string)
|
|||
cursor_string_table["UI_CURSOR_SIZENESW"] = UI_CURSOR_SIZENESW;
|
||||
cursor_string_table["UI_CURSOR_SIZEWE"] = UI_CURSOR_SIZEWE;
|
||||
cursor_string_table["UI_CURSOR_SIZENS"] = UI_CURSOR_SIZENS;
|
||||
cursor_string_table["UI_CURSOR_SIZEALL"] = UI_CURSOR_SIZEALL;
|
||||
cursor_string_table["UI_CURSOR_NO"] = UI_CURSOR_NO;
|
||||
cursor_string_table["UI_CURSOR_WORKING"] = UI_CURSOR_WORKING;
|
||||
cursor_string_table["UI_CURSOR_TOOLGRAB"] = UI_CURSOR_TOOLGRAB;
|
||||
|
|
@ -61,6 +62,7 @@ ECursorType getCursorFromString(const std::string& cursor_string)
|
|||
cursor_string_table["UI_CURSOR_TOOLCAMERA"] = UI_CURSOR_TOOLCAMERA;
|
||||
cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
|
||||
cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
|
||||
cursor_string_table["UI_CURSOR_TOOLZOOMOUT"] = UI_CURSOR_TOOLZOOMOUT;
|
||||
cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
|
||||
cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
|
||||
cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ enum ECursorType {
|
|||
UI_CURSOR_SIZENESW,
|
||||
UI_CURSOR_SIZEWE,
|
||||
UI_CURSOR_SIZENS,
|
||||
UI_CURSOR_SIZEALL,
|
||||
UI_CURSOR_NO,
|
||||
UI_CURSOR_WORKING,
|
||||
UI_CURSOR_TOOLGRAB,
|
||||
|
|
@ -57,6 +58,7 @@ enum ECursorType {
|
|||
UI_CURSOR_TOOLCAMERA,
|
||||
UI_CURSOR_TOOLPAN,
|
||||
UI_CURSOR_TOOLZOOMIN,
|
||||
UI_CURSOR_TOOLZOOMOUT,
|
||||
UI_CURSOR_TOOLPICKOBJECT3,
|
||||
UI_CURSOR_TOOLPLAY,
|
||||
UI_CURSOR_TOOLPAUSE,
|
||||
|
|
|
|||
|
|
@ -106,13 +106,13 @@ const unsigned short *copyFromPBoard()
|
|||
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
// extra retain on the NSCursor since we want it to live for the lifetime of the app.
|
||||
NSCursor *cursor =
|
||||
[[[NSCursor alloc]
|
||||
initWithImage:
|
||||
[[[NSImage alloc] initWithContentsOfFile:
|
||||
[NSString stringWithFormat:@"%s", fullpath]
|
||||
[NSString stringWithUTF8String:fullpath]
|
||||
]autorelease]
|
||||
hotSpot:NSMakePoint(hotspotX, hotspotY)
|
||||
]retain];
|
||||
|
|
|
|||
|
|
@ -1443,6 +1443,7 @@ const char* cursorIDToName(int id)
|
|||
case UI_CURSOR_SIZENESW: return "UI_CURSOR_SIZENESW";
|
||||
case UI_CURSOR_SIZEWE: return "UI_CURSOR_SIZEWE";
|
||||
case UI_CURSOR_SIZENS: return "UI_CURSOR_SIZENS";
|
||||
case UI_CURSOR_SIZEALL: return "UI_CURSOR_SIZEALL";
|
||||
case UI_CURSOR_NO: return "UI_CURSOR_NO";
|
||||
case UI_CURSOR_WORKING: return "UI_CURSOR_WORKING";
|
||||
case UI_CURSOR_TOOLGRAB: return "UI_CURSOR_TOOLGRAB";
|
||||
|
|
@ -1462,6 +1463,7 @@ const char* cursorIDToName(int id)
|
|||
case UI_CURSOR_TOOLCAMERA: return "UI_CURSOR_TOOLCAMERA";
|
||||
case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
|
||||
case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
|
||||
case UI_CURSOR_TOOLZOOMOUT: return "UI_CURSOR_TOOLZOOMOUT";
|
||||
case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
|
||||
case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
|
||||
case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
|
||||
|
|
@ -1640,6 +1642,7 @@ void LLWindowMacOSX::initCursors(BOOL useLegacyCursors)
|
|||
initPixmapCursor(UI_CURSOR_TOOLCAMERA, 7, 6);
|
||||
initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
|
||||
initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
|
||||
initPixmapCursor(UI_CURSOR_TOOLZOOMOUT, 7, 6);
|
||||
initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
|
||||
|
|
@ -1674,6 +1677,7 @@ void LLWindowMacOSX::initCursors(BOOL useLegacyCursors)
|
|||
initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
|
||||
initPixmapCursor(UI_CURSOR_SIZEWE, 10, 10);
|
||||
initPixmapCursor(UI_CURSOR_SIZENS, 10, 10);
|
||||
initPixmapCursor(UI_CURSOR_SIZEALL, 10, 10);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1708,7 +1712,7 @@ void LLWindowMacOSX::hideCursor()
|
|||
|
||||
void LLWindowMacOSX::showCursor()
|
||||
{
|
||||
if(mCursorHidden)
|
||||
if(mCursorHidden || !isCGCursorVisible())
|
||||
{
|
||||
// LL_INFOS() << "showCursor: showing" << LL_ENDL;
|
||||
mCursorHidden = FALSE;
|
||||
|
|
|
|||
|
|
@ -43,10 +43,15 @@
|
|||
#if LL_GTK
|
||||
extern "C" {
|
||||
# include "gtk/gtk.h"
|
||||
#error "Direct use of GTK is deprecated"
|
||||
}
|
||||
#include <locale.h>
|
||||
#endif // LL_GTK
|
||||
|
||||
#ifdef LL_GLIB
|
||||
#include <glib.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
# include "fontconfig/fontconfig.h"
|
||||
}
|
||||
|
|
@ -186,6 +191,248 @@ Display* LLWindowSDL::get_SDL_Display(void)
|
|||
}
|
||||
#endif // LL_X11
|
||||
|
||||
#if LL_X11
|
||||
|
||||
// Clipboard handing via native X11, base on the implementation in Cool VL by Henri Beauchamp
|
||||
|
||||
namespace
|
||||
{
|
||||
std::array<Atom, 3> gSupportedAtoms;
|
||||
|
||||
Atom XA_CLIPBOARD;
|
||||
Atom XA_TARGETS;
|
||||
Atom PVT_PASTE_BUFFER;
|
||||
long const MAX_PASTE_BUFFER_SIZE = 16383;
|
||||
|
||||
void filterSelectionRequest( XEvent aEvent )
|
||||
{
|
||||
auto *display = LLWindowSDL::getSDLDisplay();
|
||||
auto &request = aEvent.xselectionrequest;
|
||||
|
||||
XSelectionEvent reply { SelectionNotify, aEvent.xany.serial, aEvent.xany.send_event, display,
|
||||
request.requestor, request.selection, request.target,
|
||||
request.property,request.time };
|
||||
|
||||
if (request.target == XA_TARGETS)
|
||||
{
|
||||
XChangeProperty(display, request.requestor, request.property,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char *) &gSupportedAtoms.front(), gSupportedAtoms.size());
|
||||
}
|
||||
else if (std::find(gSupportedAtoms.begin(), gSupportedAtoms.end(), request.target) !=
|
||||
gSupportedAtoms.end())
|
||||
{
|
||||
std::string utf8;
|
||||
if (request.selection == XA_PRIMARY)
|
||||
utf8 = wstring_to_utf8str(gWindowImplementation->getPrimaryText());
|
||||
else
|
||||
utf8 = wstring_to_utf8str(gWindowImplementation->getSecondaryText());
|
||||
|
||||
XChangeProperty(display, request.requestor, request.property,
|
||||
request.target, 8, PropModeReplace,
|
||||
(unsigned char *) utf8.c_str(), utf8.length());
|
||||
}
|
||||
else if (request.selection == XA_CLIPBOARD)
|
||||
{
|
||||
// Did not have what they wanted, so no property set
|
||||
reply.property = None;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
XSendEvent(request.display, request.requestor, False, NoEventMask, (XEvent *) &reply);
|
||||
XSync(display, False);
|
||||
}
|
||||
|
||||
void filterSelectionClearRequest( XEvent aEvent )
|
||||
{
|
||||
auto &request = aEvent.xselectionrequest;
|
||||
if (request.selection == XA_PRIMARY)
|
||||
gWindowImplementation->clearPrimaryText();
|
||||
else if (request.selection == XA_CLIPBOARD)
|
||||
gWindowImplementation->clearSecondaryText();
|
||||
}
|
||||
|
||||
int x11_clipboard_filter(const SDL_Event *evt)
|
||||
{
|
||||
Display *display = LLWindowSDL::getSDLDisplay();
|
||||
if (!display)
|
||||
return 1;
|
||||
|
||||
if (evt->type != SDL_SYSWMEVENT)
|
||||
return 1;
|
||||
|
||||
auto xevent = evt->syswm.msg->event.xevent;
|
||||
|
||||
if (xevent.type == SelectionRequest)
|
||||
filterSelectionRequest( xevent );
|
||||
else if (xevent.type == SelectionClear)
|
||||
filterSelectionClearRequest( xevent );
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool grab_property(Display* display, Window window, Atom selection, Atom target)
|
||||
{
|
||||
if( !display )
|
||||
return false;
|
||||
|
||||
maybe_lock_display();
|
||||
|
||||
XDeleteProperty(display, window, PVT_PASTE_BUFFER);
|
||||
XFlush(display);
|
||||
|
||||
XConvertSelection(display, selection, target, PVT_PASTE_BUFFER, window, CurrentTime);
|
||||
|
||||
// Unlock the connection so that the SDL event loop may function
|
||||
maybe_unlock_display();
|
||||
|
||||
const auto start{ SDL_GetTicks() };
|
||||
const auto end{ start + 1000 };
|
||||
|
||||
XEvent xevent {};
|
||||
bool response = false;
|
||||
|
||||
do
|
||||
{
|
||||
SDL_Event event {};
|
||||
|
||||
// Wait for an event
|
||||
SDL_WaitEvent(&event);
|
||||
|
||||
// If the event is a window manager event
|
||||
if (event.type == SDL_SYSWMEVENT)
|
||||
{
|
||||
xevent = event.syswm.msg->event.xevent;
|
||||
|
||||
if (xevent.type == SelectionNotify && xevent.xselection.requestor == window)
|
||||
response = true;
|
||||
}
|
||||
} while (!response && SDL_GetTicks() < end );
|
||||
|
||||
return response && xevent.xselection.property != None;
|
||||
}
|
||||
}
|
||||
|
||||
void LLWindowSDL::initialiseX11Clipboard()
|
||||
{
|
||||
if (!mSDL_Display)
|
||||
return;
|
||||
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
|
||||
SDL_SetEventFilter(x11_clipboard_filter);
|
||||
|
||||
maybe_lock_display();
|
||||
|
||||
XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False);
|
||||
|
||||
gSupportedAtoms[0] = XA_STRING;
|
||||
|
||||
gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False);
|
||||
gSupportedAtoms[2] = XInternAtom(mSDL_Display, "UTF8_STRING", False);
|
||||
|
||||
// TARGETS atom
|
||||
XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False);
|
||||
|
||||
// SL_PASTE_BUFFER atom
|
||||
PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False);
|
||||
|
||||
maybe_unlock_display();
|
||||
}
|
||||
|
||||
bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text )
|
||||
{
|
||||
if( !mSDL_Display )
|
||||
return false;
|
||||
|
||||
if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) )
|
||||
return false;
|
||||
|
||||
maybe_lock_display();
|
||||
|
||||
Atom type;
|
||||
int format{};
|
||||
unsigned long len{},remaining {};
|
||||
unsigned char* data = nullptr;
|
||||
int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID,
|
||||
PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False,
|
||||
AnyPropertyType, &type, &format, &len,
|
||||
&remaining, &data);
|
||||
if (data && len)
|
||||
{
|
||||
text = LLWString(
|
||||
utf8str_to_wstring(reinterpret_cast< char const *>( data ) )
|
||||
);
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
maybe_unlock_display();
|
||||
return res == Success;
|
||||
}
|
||||
|
||||
bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text)
|
||||
{
|
||||
if (!mSDL_Display)
|
||||
return false;
|
||||
|
||||
maybe_lock_display();
|
||||
|
||||
Window owner = XGetSelectionOwner(mSDL_Display, selection);
|
||||
if (owner == None)
|
||||
{
|
||||
if (selection == XA_PRIMARY)
|
||||
{
|
||||
owner = DefaultRootWindow(mSDL_Display);
|
||||
selection = XA_CUT_BUFFER0;
|
||||
}
|
||||
else
|
||||
{
|
||||
maybe_unlock_display();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
maybe_unlock_display();
|
||||
|
||||
for( Atom atom : gSupportedAtoms )
|
||||
{
|
||||
if(getSelectionText(selection, atom, text ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text)
|
||||
{
|
||||
maybe_lock_display();
|
||||
|
||||
if (selection == XA_PRIMARY)
|
||||
{
|
||||
std::string utf8 = wstring_to_utf8str(text);
|
||||
XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1);
|
||||
mPrimaryClipboard = text;
|
||||
}
|
||||
else
|
||||
mSecondaryClipboard = text;
|
||||
|
||||
XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime);
|
||||
|
||||
auto owner = XGetSelectionOwner(mSDL_Display, selection);
|
||||
|
||||
maybe_unlock_display();
|
||||
|
||||
return owner == mSDL_XWindowID;
|
||||
}
|
||||
|
||||
Display* LLWindowSDL::getSDLDisplay()
|
||||
{
|
||||
if (gWindowImplementation)
|
||||
return gWindowImplementation->mSDL_Display;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, S32 x, S32 y, S32 width,
|
||||
|
|
@ -253,6 +500,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
|
|||
|
||||
#if LL_X11
|
||||
mFlashing = FALSE;
|
||||
initialiseX11Clipboard();
|
||||
#endif // LL_X11
|
||||
|
||||
mKeyScanCode = 0;
|
||||
|
|
@ -1356,33 +1604,34 @@ BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text)
|
|||
#else
|
||||
|
||||
BOOL LLWindowSDL::isClipboardTextAvailable()
|
||||
{
|
||||
return FALSE; // unsupported
|
||||
{
|
||||
return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None;
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
|
||||
{
|
||||
return FALSE; // unsupported
|
||||
return getSelectionText(XA_CLIPBOARD, dst);
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
|
||||
{
|
||||
return FALSE; // unsupported
|
||||
return setSelectionText(XA_CLIPBOARD, s);
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::isPrimaryTextAvailable()
|
||||
{
|
||||
return FALSE; // unsupported
|
||||
LLWString text;
|
||||
return getSelectionText(XA_PRIMARY, text) && !text.empty();
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
|
||||
{
|
||||
return FALSE; // unsupported
|
||||
return getSelectionText(XA_PRIMARY, dst);
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s)
|
||||
{
|
||||
return FALSE; // unsupported
|
||||
return setSelectionText(XA_PRIMARY, s);
|
||||
}
|
||||
|
||||
#endif // LL_GTK
|
||||
|
|
@ -1747,7 +1996,18 @@ void LLWindowSDL::processMiscNativeEvents()
|
|||
setlocale(LC_ALL, saved_locale.c_str() );
|
||||
}
|
||||
#endif // LL_GTK
|
||||
|
||||
#if LL_GLIB
|
||||
// Pump until we've nothing left to do or passed 1/15th of a
|
||||
// second pumping for this frame.
|
||||
static LLTimer pump_timer;
|
||||
pump_timer.reset();
|
||||
pump_timer.setTimerExpirySec(1.0f / 15.0f);
|
||||
do
|
||||
{
|
||||
g_main_context_iteration(g_main_context_default(), FALSE);
|
||||
} while( g_main_context_pending(g_main_context_default()) && !pump_timer.hasExpired());
|
||||
#endif
|
||||
|
||||
// hack - doesn't belong here - but this is just for debugging
|
||||
if (getenv("LL_DEBUG_BLOAT"))
|
||||
{
|
||||
|
|
@ -2109,6 +2369,7 @@ void LLWindowSDL::initCursors(BOOL useLegacyCursors) // <FS:LO> Legacy cursor se
|
|||
mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
|
||||
mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
|
||||
mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
|
||||
mSDLCursors[UI_CURSOR_SIZEALL] = makeSDLCursorFromBMP("sizeall.BMP", 17, 17);
|
||||
mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
|
||||
mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
|
||||
mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
|
||||
|
|
@ -2128,6 +2389,7 @@ void LLWindowSDL::initCursors(BOOL useLegacyCursors) // <FS:LO> Legacy cursor se
|
|||
mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromBMP("lltoolcamera.BMP",7,5);
|
||||
mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
|
||||
mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
|
||||
mSDLCursors[UI_CURSOR_TOOLZOOMOUT] = makeSDLCursorFromBMP("lltoolzoomout.BMP", 7, 5);
|
||||
mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
|
||||
mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0);
|
||||
mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0);
|
||||
|
|
@ -2396,39 +2658,6 @@ static void color_changed_callback(GtkWidget *widget,
|
|||
gtk_color_selection_get_current_color(colorsel, colorp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Make the raw keyboard data available - used to poke through to LLQtWebKit so
|
||||
that Qt/Webkit has access to the virtual keycodes etc. that it needs
|
||||
*/
|
||||
LLSD LLWindowSDL::getNativeKeyData()
|
||||
{
|
||||
LLSD result = LLSD::emptyMap();
|
||||
|
||||
U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave!
|
||||
|
||||
// we go through so many levels of device abstraction that I can't really guess
|
||||
// what a plugin under GDK under Qt under SL under SDL under X11 considers
|
||||
// a 'native' modifier mask. this has been sort of reverse-engineered... they *appear*
|
||||
// to match GDK consts, but that may be co-incidence.
|
||||
modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
|
||||
modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
|
||||
modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0;
|
||||
modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0;
|
||||
modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl
|
||||
modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested
|
||||
modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested
|
||||
// *todo: test ALTs - I don't have a case for testing these. Do you?
|
||||
// *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
|
||||
|
||||
result["scan_code"] = (S32)mKeyScanCode;
|
||||
result["virtual_key"] = (S32)mKeyVirtualKey;
|
||||
result["modifiers"] = (S32)modifiers;
|
||||
result[ "sdl_sym" ] = (S32)mSDLSym; // <FS:ND/> Store the SDL Keysym too.
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
|
||||
{
|
||||
BOOL rtn = FALSE;
|
||||
|
|
@ -2513,6 +2742,37 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
|
|||
}
|
||||
#endif // LL_GTK
|
||||
|
||||
/*
|
||||
Make the raw keyboard data available - used to poke through to LLQtWebKit so
|
||||
that Qt/Webkit has access to the virtual keycodes etc. that it needs
|
||||
*/
|
||||
LLSD LLWindowSDL::getNativeKeyData()
|
||||
{
|
||||
LLSD result = LLSD::emptyMap();
|
||||
|
||||
U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave!
|
||||
|
||||
// we go through so many levels of device abstraction that I can't really guess
|
||||
// what a plugin under GDK under Qt under SL under SDL under X11 considers
|
||||
// a 'native' modifier mask. this has been sort of reverse-engineered... they *appear*
|
||||
// to match GDK consts, but that may be co-incidence.
|
||||
modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
|
||||
modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
|
||||
modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0;
|
||||
modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0;
|
||||
modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl
|
||||
modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested
|
||||
modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested
|
||||
// *todo: test ALTs - I don't have a case for testing these. Do you?
|
||||
// *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
|
||||
|
||||
result["scan_code"] = (S32)mKeyScanCode;
|
||||
result["virtual_key"] = (S32)mKeyVirtualKey;
|
||||
result["modifiers"] = (S32)modifiers;
|
||||
result[ "sdl_sym" ] = (S32)mSDLSym; // <FS:ND/> Store the SDL Keysym too.
|
||||
return result;
|
||||
}
|
||||
|
||||
#if LL_LINUX
|
||||
// extracted from spawnWebBrowser for clarity and to eliminate
|
||||
// compiler confusion regarding close(int fd) vs. LLWindow::close()
|
||||
|
|
|
|||
|
|
@ -220,6 +220,24 @@ private:
|
|||
U32 mSDLSym; // <FS:ND/> Store the SDL Keysym too.
|
||||
|
||||
BOOL mUseLegacyCursors; // <FS:LO> Legacy cursor setting from main program
|
||||
|
||||
public:
|
||||
#if LL_X11
|
||||
static Display* getSDLDisplay();
|
||||
LLWString const& getPrimaryText() const { return mPrimaryClipboard; }
|
||||
LLWString const& getSecondaryText() const { return mSecondaryClipboard; }
|
||||
void clearPrimaryText() { mPrimaryClipboard.clear(); }
|
||||
void clearSecondaryText() { mSecondaryClipboard.clear(); }
|
||||
private:
|
||||
void initialiseX11Clipboard();
|
||||
|
||||
bool getSelectionText(Atom selection, LLWString& text);
|
||||
bool getSelectionText( Atom selection, Atom type, LLWString &text );
|
||||
|
||||
bool setSelectionText(Atom selection, const LLWString& text);
|
||||
#endif
|
||||
LLWString mPrimaryClipboard;
|
||||
LLWString mSecondaryClipboard;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1918,8 +1918,9 @@ void LLWindowWin32::initCursors(BOOL useLegacyCursors) // <FS:LO> Legacy cursor
|
|||
mCursor[ UI_CURSOR_CROSS ] = LoadCursor(NULL, IDC_CROSS);
|
||||
mCursor[ UI_CURSOR_SIZENWSE ] = LoadCursor(NULL, IDC_SIZENWSE);
|
||||
mCursor[ UI_CURSOR_SIZENESW ] = LoadCursor(NULL, IDC_SIZENESW);
|
||||
mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
|
||||
mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
|
||||
mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
|
||||
mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
|
||||
mCursor[ UI_CURSOR_SIZEALL ] = LoadCursor(NULL, IDC_SIZEALL);
|
||||
mCursor[ UI_CURSOR_NO ] = LoadCursor(NULL, IDC_NO);
|
||||
mCursor[ UI_CURSOR_WORKING ] = LoadCursor(NULL, IDC_APPSTARTING);
|
||||
|
||||
|
|
@ -1941,6 +1942,7 @@ void LLWindowWin32::initCursors(BOOL useLegacyCursors) // <FS:LO> Legacy cursor
|
|||
mCursor[ UI_CURSOR_TOOLCAMERA ] = LoadCursor(module, TEXT("TOOLCAMERA"));
|
||||
mCursor[ UI_CURSOR_TOOLPAN ] = LoadCursor(module, TEXT("TOOLPAN"));
|
||||
mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
|
||||
mCursor[ UI_CURSOR_TOOLZOOMOUT ] = LoadCursor(module, TEXT("TOOLZOOMOUT"));
|
||||
mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
|
||||
mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
|
||||
/*<FS:LO> Legacy cursor setting from main program
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
add_subdirectory(base)
|
||||
|
||||
if (LINUX)
|
||||
# add_subdirectory(gstreamer010)
|
||||
add_subdirectory(cef)
|
||||
add_subdirectory(libvlc)
|
||||
#add_subdirectory(example)
|
||||
add_subdirectory(gstreamer10)
|
||||
add_subdirectory(cef)
|
||||
#add_subdirectory(libvlc)
|
||||
endif (LINUX)
|
||||
|
||||
if (DARWIN)
|
||||
|
|
|
|||
|
|
@ -49,4 +49,3 @@ set(media_plugin_base_HEADER_FILES
|
|||
add_library(media_plugin_base
|
||||
${media_plugin_base_SOURCE_FILES}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ set (media_plugin_cef_LINK_LIBRARIES
|
|||
if (LINUX)
|
||||
# message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n"
|
||||
# " Please create a volume_catcher implementation for this platform.")
|
||||
list(APPEND media_plugin_cef_SOURCE_FILES dummy_volume_catcher.cpp)
|
||||
|
||||
list(APPEND media_plugin_cef_SOURCE_FILES ${LINUX_VOLUME_CATCHER})
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id -Wl,-rpath,'$ORIGIN:$ORIGIN/../../lib'")
|
||||
elseif (DARWIN)
|
||||
list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher_null.cpp)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ extern "C" {
|
|||
#include "apr_dso.h"
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
#define DEBUGMSG(...) do {} while(0)
|
||||
|
|
@ -81,7 +82,7 @@ bool grab_pa_syms(std::string pulse_dso_name)
|
|||
apr_status_t rv;
|
||||
apr_dso_handle_t *sSymPADSOHandle = NULL;
|
||||
|
||||
#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0)
|
||||
#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) { if (REQUIRED) sym_error = true;} } while(0);
|
||||
|
||||
//attempt to load the shared library
|
||||
apr_pool_create(&sSymPADSOMemoryPool, NULL);
|
||||
|
|
@ -216,17 +217,16 @@ void VolumeCatcherImpl::init()
|
|||
mGotSyms = loadsyms("libpulse-mainloop-glib.so.0");
|
||||
if (!mGotSyms) return;
|
||||
|
||||
// better make double-sure glib itself is initialized properly.
|
||||
if (!g_thread_supported ()) g_thread_init (NULL);
|
||||
g_type_init();
|
||||
|
||||
mMainloop = llpa_glib_mainloop_new(g_main_context_default());
|
||||
|
||||
if (mMainloop)
|
||||
{
|
||||
pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop);
|
||||
|
||||
if (api)
|
||||
{
|
||||
pa_proplist *proplist = llpa_proplist_new();
|
||||
|
||||
if (proplist)
|
||||
{
|
||||
llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player");
|
||||
|
|
@ -236,6 +236,7 @@ void VolumeCatcherImpl::init()
|
|||
|
||||
// plain old pa_context_new() is broken!
|
||||
mPAContext = llpa_context_new_with_proplist(api, NULL, proplist);
|
||||
|
||||
llpa_proplist_free(proplist);
|
||||
}
|
||||
}
|
||||
|
|
@ -350,6 +351,51 @@ void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume)
|
|||
}
|
||||
}
|
||||
|
||||
pid_t getParentPid( pid_t aPid )
|
||||
{
|
||||
std::stringstream strm;
|
||||
strm << "/proc/" << aPid << "/status";
|
||||
std::ifstream in{ strm.str() };
|
||||
|
||||
if( !in.is_open() )
|
||||
return 0;
|
||||
|
||||
pid_t res {0};
|
||||
while( !in.eof() && res == 0 )
|
||||
{
|
||||
std::string line;
|
||||
line.resize( 1024, 0 );
|
||||
in.getline( &line[0], line.length() );
|
||||
|
||||
auto i = line.find( "PPid:" );
|
||||
|
||||
if( i == std::string::npos )
|
||||
continue;
|
||||
|
||||
char const *pIn = line.c_str() + 5; // Skip over pid;
|
||||
while( *pIn != 0 && isspace( *pIn ) )
|
||||
++pIn;
|
||||
|
||||
if( *pIn )
|
||||
res = atoll( pIn );
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool isPluginPid( pid_t aPid )
|
||||
{
|
||||
auto myPid = getpid();
|
||||
|
||||
do
|
||||
{
|
||||
if( aPid == myPid )
|
||||
return true;
|
||||
aPid = getParentPid( aPid );
|
||||
} while( aPid > 1 );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata)
|
||||
{
|
||||
|
|
@ -360,11 +406,10 @@ void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info
|
|||
{
|
||||
pa_proplist *proplist = sii->proplist;
|
||||
pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID));
|
||||
|
||||
if (sinkpid == getpid()) // does the discovered sinkinput belong to this process?
|
||||
|
||||
if (isPluginPid( sinkpid )) // does the discovered sinkinput belong to this process?
|
||||
{
|
||||
bool is_new = (impl->mSinkInputIndices.find(sii->index) ==
|
||||
impl->mSinkInputIndices.end());
|
||||
bool is_new = (impl->mSinkInputIndices.find(sii->index) == impl->mSinkInputIndices.end());
|
||||
|
||||
impl->mSinkInputIndices.insert(sii->index);
|
||||
impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels;
|
||||
|
|
@ -387,32 +432,31 @@ void callback_subscription_alert(pa_context *context, pa_subscription_event_type
|
|||
VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
|
||||
llassert(impl);
|
||||
|
||||
switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
|
||||
switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)
|
||||
{
|
||||
case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
|
||||
PA_SUBSCRIPTION_EVENT_REMOVE)
|
||||
{
|
||||
// forget this sinkinput, if we were caring about it
|
||||
impl->mSinkInputIndices.erase(index);
|
||||
impl->mSinkInputNumChannels.erase(index);
|
||||
}
|
||||
else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
|
||||
PA_SUBSCRIPTION_EVENT_NEW)
|
||||
{
|
||||
// ask for more info about this new sinkinput
|
||||
pa_operation *op;
|
||||
if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl)))
|
||||
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
|
||||
{
|
||||
llpa_operation_unref(op);
|
||||
// forget this sinkinput, if we were caring about it
|
||||
impl->mSinkInputIndices.erase(index);
|
||||
impl->mSinkInputNumChannels.erase(index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// property change on this sinkinput - we don't care.
|
||||
}
|
||||
break;
|
||||
else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW)
|
||||
{
|
||||
// ask for more info about this new sinkinput
|
||||
pa_operation *op;
|
||||
if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl)))
|
||||
{
|
||||
llpa_operation_unref(op);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// property change on this sinkinput - we don't care.
|
||||
}
|
||||
break;
|
||||
|
||||
default:;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ private:
|
|||
bool mCookiesEnabled;
|
||||
bool mPluginsEnabled;
|
||||
bool mJavascriptEnabled;
|
||||
bool mProxyEnabled;
|
||||
std::string mProxyHost;
|
||||
int mProxyPort;
|
||||
bool mDisableGPU;
|
||||
bool mDisableNetworkService;
|
||||
bool mUseMockKeyChain;
|
||||
|
|
@ -124,6 +127,9 @@ MediaPluginBase(host_send_func, host_user_data)
|
|||
mCookiesEnabled = true;
|
||||
mPluginsEnabled = false;
|
||||
mJavascriptEnabled = true;
|
||||
mProxyEnabled = false;
|
||||
mProxyHost = "";
|
||||
mProxyPort = 0;
|
||||
mDisableGPU = false;
|
||||
mDisableNetworkService = true;
|
||||
mUseMockKeyChain = true;
|
||||
|
|
@ -397,21 +403,86 @@ void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type)
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case dullahan::CT_POINTER:
|
||||
name = "arrow";
|
||||
break;
|
||||
case dullahan::CT_POINTER:
|
||||
name = "UI_CURSOR_ARROW";
|
||||
break;
|
||||
case dullahan::CT_CROSS:
|
||||
name = "UI_CURSOR_CROSS";
|
||||
break;
|
||||
case dullahan::CT_HAND:
|
||||
name = "UI_CURSOR_HAND";
|
||||
break;
|
||||
case dullahan::CT_IBEAM:
|
||||
name = "ibeam";
|
||||
break;
|
||||
case dullahan::CT_NORTHSOUTHRESIZE:
|
||||
name = "splitv";
|
||||
break;
|
||||
case dullahan::CT_EASTWESTRESIZE:
|
||||
name = "splith";
|
||||
break;
|
||||
case dullahan::CT_HAND:
|
||||
name = "hand";
|
||||
name = "UI_CURSOR_IBEAM";
|
||||
break;
|
||||
case dullahan::CT_WAIT:
|
||||
name = "UI_CURSOR_WAIT";
|
||||
break;
|
||||
//case dullahan::CT_HELP:
|
||||
case dullahan::CT_ROWRESIZE:
|
||||
case dullahan::CT_NORTHRESIZE:
|
||||
case dullahan::CT_SOUTHRESIZE:
|
||||
case dullahan::CT_NORTHSOUTHRESIZE:
|
||||
name = "UI_CURSOR_SIZENS";
|
||||
break;
|
||||
case dullahan::CT_COLUMNRESIZE:
|
||||
case dullahan::CT_EASTRESIZE:
|
||||
case dullahan::CT_WESTRESIZE:
|
||||
case dullahan::CT_EASTWESTRESIZE:
|
||||
name = "UI_CURSOR_SIZEWE";
|
||||
break;
|
||||
case dullahan::CT_NORTHEASTRESIZE:
|
||||
case dullahan::CT_SOUTHWESTRESIZE:
|
||||
case dullahan::CT_NORTHEASTSOUTHWESTRESIZE:
|
||||
name = "UI_CURSOR_SIZENESW";
|
||||
break;
|
||||
case dullahan::CT_SOUTHEASTRESIZE:
|
||||
case dullahan::CT_NORTHWESTRESIZE:
|
||||
case dullahan::CT_NORTHWESTSOUTHEASTRESIZE:
|
||||
name = "UI_CURSOR_SIZENWSE";
|
||||
break;
|
||||
case dullahan::CT_MOVE:
|
||||
name = "UI_CURSOR_SIZEALL";
|
||||
break;
|
||||
//case dullahan::CT_MIDDLEPANNING:
|
||||
//case dullahan::CT_EASTPANNING:
|
||||
//case dullahan::CT_NORTHPANNING:
|
||||
//case dullahan::CT_NORTHEASTPANNING:
|
||||
//case dullahan::CT_NORTHWESTPANNING:
|
||||
//case dullahan::CT_SOUTHPANNING:
|
||||
//case dullahan::CT_SOUTHEASTPANNING:
|
||||
//case dullahan::CT_SOUTHWESTPANNING:
|
||||
//case dullahan::CT_WESTPANNING:
|
||||
//case dullahan::CT_VERTICALTEXT:
|
||||
//case dullahan::CT_CELL:
|
||||
//case dullahan::CT_CONTEXTMENU:
|
||||
case dullahan::CT_ALIAS:
|
||||
name = "UI_CURSOR_TOOLMEDIAOPEN";
|
||||
break;
|
||||
case dullahan::CT_PROGRESS:
|
||||
name = "UI_CURSOR_WORKING";
|
||||
break;
|
||||
case dullahan::CT_COPY:
|
||||
name = "UI_CURSOR_ARROWCOPY";
|
||||
break;
|
||||
case dullahan::CT_NONE:
|
||||
name = "UI_CURSOR_NO";
|
||||
break;
|
||||
case dullahan::CT_NODROP:
|
||||
case dullahan::CT_NOTALLOWED:
|
||||
name = "UI_CURSOR_NOLOCKED";
|
||||
break;
|
||||
case dullahan::CT_ZOOMIN:
|
||||
name = "UI_CURSOR_TOOLZOOMIN";
|
||||
break;
|
||||
case dullahan::CT_ZOOMOUT:
|
||||
name = "UI_CURSOR_TOOLZOOMOUT";
|
||||
break;
|
||||
case dullahan::CT_GRAB:
|
||||
name = "UI_CURSOR_TOOLGRAB";
|
||||
break;
|
||||
//case dullahan::CT_GRABING:
|
||||
//case dullahan::CT_CUSTOM:
|
||||
|
||||
default:
|
||||
LL_WARNS() << "Unknown cursor ID: " << (int)type << LL_ENDL;
|
||||
|
|
@ -518,50 +589,60 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
}
|
||||
else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
|
||||
{
|
||||
if (message_name == "init")
|
||||
{
|
||||
// event callbacks from Dullahan
|
||||
mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
mCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
|
||||
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
|
||||
mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
mCEFLib->setOnJSBeforeUnloadCallback(std::bind(&MediaPluginCEF::onJSBeforeUnloadCallback, this));
|
||||
|
||||
dullahan::dullahan_settings settings;
|
||||
if (message_name == "init")
|
||||
{
|
||||
// event callbacks from Dullahan
|
||||
mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
mCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
|
||||
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
|
||||
mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
|
||||
mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
mCEFLib->setOnJSBeforeUnloadCallback(std::bind(&MediaPluginCEF::onJSBeforeUnloadCallback, this));
|
||||
|
||||
dullahan::dullahan_settings settings;
|
||||
#if LL_WINDOWS
|
||||
// As of CEF version 83+, for Windows versions, we need to tell CEF
|
||||
// where the host helper process is since this DLL is not in the same
|
||||
// dir as the executable that loaded it (SLPlugin.exe). The code in
|
||||
// Dullahan that tried to figure out the location automatically uses
|
||||
// the location of the exe which isn't helpful so we tell it explicitly.
|
||||
char cur_dir_str[MAX_PATH];
|
||||
GetCurrentDirectoryA(MAX_PATH, cur_dir_str);
|
||||
settings.host_process_path = std::string(cur_dir_str);
|
||||
// As of CEF version 83+, for Windows versions, we need to tell CEF
|
||||
// where the host helper process is since this DLL is not in the same
|
||||
// dir as the executable that loaded it (SLPlugin.exe). The code in
|
||||
// Dullahan that tried to figure out the location automatically uses
|
||||
// the location of the exe which isn't helpful so we tell it explicitly.
|
||||
char cur_dir_str[MAX_PATH];
|
||||
GetCurrentDirectoryA(MAX_PATH, cur_dir_str);
|
||||
settings.host_process_path = std::string(cur_dir_str);
|
||||
#endif
|
||||
settings.accept_language_list = mHostLanguage;
|
||||
settings.accept_language_list = mHostLanguage;
|
||||
|
||||
// SL-15560: Product team overruled my change to set the default
|
||||
// embedded background color to match the floater background
|
||||
// and set it to white
|
||||
settings.background_color = 0xffffffff; // white
|
||||
// SL-15560: Product team overruled my change to set the default
|
||||
// embedded background color to match the floater background
|
||||
// and set it to white
|
||||
settings.background_color = 0xffffffff; // white
|
||||
|
||||
settings.cache_enabled = true;
|
||||
settings.root_cache_path = mRootCachePath;
|
||||
settings.cache_path = mCachePath;
|
||||
settings.context_cache_path = mContextCachePath;
|
||||
settings.cookies_enabled = mCookiesEnabled;
|
||||
settings.cache_enabled = true;
|
||||
settings.root_cache_path = mRootCachePath;
|
||||
settings.cache_path = mCachePath;
|
||||
settings.context_cache_path = mContextCachePath;
|
||||
settings.cookies_enabled = mCookiesEnabled;
|
||||
|
||||
#ifndef LL_LINUX
|
||||
// configure proxy argument if enabled and valid
|
||||
if (mProxyEnabled && mProxyHost.length())
|
||||
{
|
||||
std::ostringstream proxy_url;
|
||||
proxy_url << mProxyHost << ":" << mProxyPort;
|
||||
settings.proxy_host_port = proxy_url.str();
|
||||
}
|
||||
#endif
|
||||
settings.disable_gpu = mDisableGPU;
|
||||
#if LL_DARWIN
|
||||
settings.disable_network_service = mDisableNetworkService;
|
||||
|
|
@ -909,6 +990,12 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
{
|
||||
mDisableGPU = message_in.getValueBoolean("disable");
|
||||
}
|
||||
else if (message_name == "proxy_setup")
|
||||
{
|
||||
mProxyEnabled = message_in.getValueBoolean("enable");
|
||||
mProxyHost = message_in.getValue("host");
|
||||
mProxyPort = message_in.getValueS32("port");
|
||||
}
|
||||
else if (message_name == "web_security_disabled")
|
||||
{
|
||||
mDisableWebSecurity = message_in.getValueBoolean("disabled");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
project(media_plugin_gstreamer10)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLImage)
|
||||
include(LLPlugin)
|
||||
include(LLMath)
|
||||
include(LLRender)
|
||||
include(LLWindow)
|
||||
include(Linking)
|
||||
include(PluginAPI)
|
||||
include(MediaPluginBase)
|
||||
include(OpenGL)
|
||||
include(GLIB)
|
||||
|
||||
include(GStreamer10Plugin)
|
||||
|
||||
include_directories(
|
||||
${LLPLUGIN_INCLUDE_DIRS}
|
||||
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLRENDER_INCLUDE_DIRS}
|
||||
${LLWINDOW_INCLUDE_DIRS}
|
||||
${GSTREAMER10_INCLUDE_DIRS}
|
||||
${GSTREAMER10_PLUGINS_BASE_INCLUDE_DIRS}
|
||||
)
|
||||
include_directories(SYSTEM
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
### media_plugin_gstreamer10
|
||||
|
||||
if(NOT WORD_SIZE EQUAL 32)
|
||||
if(NOT WINDOWS) # not windows therefore gcc LINUX and DARWIN
|
||||
add_definitions(-fPIC)
|
||||
endif()
|
||||
endif(NOT WORD_SIZE EQUAL 32)
|
||||
|
||||
set(media_plugin_gstreamer10_SOURCE_FILES
|
||||
media_plugin_gstreamer10.cpp
|
||||
llmediaimplgstreamer_syms.cpp
|
||||
)
|
||||
|
||||
set(media_plugin_gstreamer10_HEADER_FILES
|
||||
llmediaimplgstreamer_syms.h
|
||||
llmediaimplgstreamertriviallogging.h
|
||||
)
|
||||
|
||||
add_library(media_plugin_gstreamer10
|
||||
SHARED
|
||||
${media_plugin_gstreamer10_SOURCE_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(media_plugin_gstreamer10
|
||||
${LLPLUGIN_LIBRARIES}
|
||||
${MEDIA_PLUGIN_BASE_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${PLUGIN_API_WINDOWS_LIBRARIES}
|
||||
${GSTREAMER10_LIBRARIES}
|
||||
)
|
||||
|
||||
#add_dependencies(media_plugin_gstreamer10
|
||||
# ${LLPLUGIN_LIBRARIES}
|
||||
# ${MEDIA_PLUGIN_BASE_LIBRARIES}
|
||||
# ${LLCOMMON_LIBRARIES}
|
||||
#)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(
|
||||
media_plugin_gstreamer10
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
/**
|
||||
* @file llappviewerlinux_api_dbus.h
|
||||
* @brief DBus-glib symbol handling
|
||||
* @file llmediaimplgstreamer.h
|
||||
* @author Tofu Linden
|
||||
* @brief implementation that supports media playback via GStreamer.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
|
|
@ -22,23 +24,30 @@
|
|||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
// header guard
|
||||
#ifndef llmediaimplgstreamer_h
|
||||
#define llmediaimplgstreamer_h
|
||||
|
||||
#if LL_DBUS_ENABLED
|
||||
#if LL_GSTREAMER010_ENABLED
|
||||
|
||||
extern "C" {
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <stdio.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "apr_pools.h"
|
||||
#include "apr_dso.h"
|
||||
}
|
||||
|
||||
#define DBUSGLIB_DYLIB_DEFAULT_NAME "libdbus-glib-1.so.2"
|
||||
|
||||
bool grab_dbus_syms(std::string dbus_dso_name);
|
||||
void ungrab_dbus_syms();
|
||||
extern "C" {
|
||||
gboolean llmediaimplgstreamer_bus_callback (GstBus *bus,
|
||||
GstMessage *message,
|
||||
gpointer data);
|
||||
}
|
||||
|
||||
#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) extern RTN (*ll##DBUSSYM)(__VA_ARGS__)
|
||||
#include "llappviewerlinux_api_dbus_syms_raw.inc"
|
||||
#undef LL_DBUS_SYM
|
||||
#endif // LL_GSTREAMER010_ENABLED
|
||||
|
||||
#endif // LL_DBUS_ENABLED
|
||||
#endif // llmediaimplgstreamer_h
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* @file llmediaimplgstreamer_syms.cpp
|
||||
* @brief dynamic GStreamer symbol-grabbing code
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0502
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
extern "C" {
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsink.h>
|
||||
}
|
||||
|
||||
#include "apr_pools.h"
|
||||
#include "apr_dso.h"
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
|
||||
#ifndef _M_AMD64
|
||||
#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86"
|
||||
#define GSTREAMER_DIR_SUFFIX "1.0\\x86\\bin\\"
|
||||
#else
|
||||
#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86_64"
|
||||
#define GSTREAMER_DIR_SUFFIX "1.0\\x86_64\\bin\\"
|
||||
#endif
|
||||
|
||||
bool openRegKey( HKEY &aKey )
|
||||
{
|
||||
// Try native (32 bit view/64 bit view) of registry first.
|
||||
if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE, &aKey ) )
|
||||
return true;
|
||||
|
||||
// If native view fails, use 32 bit view or registry.
|
||||
if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &aKey ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string getGStreamerDir()
|
||||
{
|
||||
std::string ret;
|
||||
HKEY hKey;
|
||||
|
||||
if( openRegKey( hKey ) )
|
||||
{
|
||||
DWORD dwLen(0);
|
||||
::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, nullptr, &dwLen );
|
||||
|
||||
if( dwLen > 0 )
|
||||
{
|
||||
std::vector< char > vctBuffer;
|
||||
vctBuffer.resize( dwLen );
|
||||
::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, reinterpret_cast< LPBYTE>(&vctBuffer[ 0 ]), &dwLen );
|
||||
ret = &vctBuffer[0];
|
||||
|
||||
if( ret[ dwLen-1 ] != '\\' )
|
||||
ret += "\\";
|
||||
ret += GSTREAMER_DIR_SUFFIX;
|
||||
|
||||
SetDllDirectoryA( ret.c_str() );
|
||||
}
|
||||
::RegCloseKey( hKey );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
std::string getGStreamerDir() { return ""; }
|
||||
#endif
|
||||
|
||||
#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL;
|
||||
#include "llmediaimplgstreamer_syms_raw.inc"
|
||||
#undef LL_GST_SYM
|
||||
|
||||
struct Symloader
|
||||
{
|
||||
bool mRequired;
|
||||
char const *mName;
|
||||
apr_dso_handle_sym_t *mPPFunc;
|
||||
};
|
||||
|
||||
#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) { REQ, #GSTSYM , (apr_dso_handle_sym_t*)&ll##GSTSYM},
|
||||
Symloader sSyms[] = {
|
||||
#include "llmediaimplgstreamer_syms_raw.inc"
|
||||
{ false, 0, 0 } };
|
||||
#undef LL_GST_SYM
|
||||
|
||||
// a couple of stubs for disgusting reasons
|
||||
GstDebugCategory*
|
||||
ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
|
||||
{
|
||||
static GstDebugCategory dummy;
|
||||
return &dummy;
|
||||
}
|
||||
void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
|
||||
{
|
||||
}
|
||||
|
||||
static bool sSymsGrabbed = false;
|
||||
static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
|
||||
|
||||
std::vector< apr_dso_handle_t* > sLoadedLibraries;
|
||||
|
||||
bool grab_gst_syms( std::vector< std::string > const &aDSONames )
|
||||
{
|
||||
if (sSymsGrabbed)
|
||||
return true;
|
||||
|
||||
//attempt to load the shared libraries
|
||||
apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
|
||||
|
||||
for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr )
|
||||
{
|
||||
apr_dso_handle_t *pDSO(NULL);
|
||||
std::string strDSO = getGStreamerDir() + *itr;
|
||||
if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymGSTDSOMemoryPool ))
|
||||
sLoadedLibraries.push_back( pDSO );
|
||||
|
||||
for( int i = 0; sSyms[ i ].mName; ++i )
|
||||
{
|
||||
if( !*sSyms[ i ].mPPFunc )
|
||||
{
|
||||
apr_dso_sym( sSyms[ i ].mPPFunc, pDSO, sSyms[ i ].mName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream strm;
|
||||
bool sym_error = false;
|
||||
for( int i = 0; sSyms[ i ].mName; ++i )
|
||||
{
|
||||
if( sSyms[ i ].mRequired && ! *sSyms[ i ].mPPFunc )
|
||||
{
|
||||
sym_error = true;
|
||||
strm << sSyms[ i ].mName << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
sSymsGrabbed = !sym_error;
|
||||
return sSymsGrabbed;
|
||||
}
|
||||
|
||||
|
||||
void ungrab_gst_syms()
|
||||
{
|
||||
// should be safe to call regardless of whether we've
|
||||
// actually grabbed syms.
|
||||
|
||||
for( std::vector< apr_dso_handle_t* >::iterator itr = sLoadedLibraries.begin(); itr != sLoadedLibraries.end(); ++itr )
|
||||
apr_dso_unload( *itr );
|
||||
|
||||
sLoadedLibraries.clear();
|
||||
|
||||
if ( sSymGSTDSOMemoryPool )
|
||||
{
|
||||
apr_pool_destroy(sSymGSTDSOMemoryPool);
|
||||
sSymGSTDSOMemoryPool = NULL;
|
||||
}
|
||||
|
||||
for( int i = 0; sSyms[ i ].mName; ++i )
|
||||
*sSyms[ i ].mPPFunc = NULL;
|
||||
|
||||
sSymsGrabbed = false;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* @file llmediaimplgstreamer_syms.h
|
||||
* @brief dynamic GStreamer symbol-grabbing code
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include <vector>
|
||||
extern "C" {
|
||||
#include <gst/gst.h>
|
||||
}
|
||||
|
||||
bool grab_gst_syms( std::vector< std::string > const&);
|
||||
void ungrab_gst_syms();
|
||||
|
||||
#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__);
|
||||
#include "llmediaimplgstreamer_syms_raw.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_VIDEO_SINK
|
||||
#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
|
||||
// more regrettable hacks to stub-out these .h-exposed GStreamer internals
|
||||
void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
|
||||
#undef _gst_debug_register_funcptr
|
||||
#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
|
||||
GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
|
||||
#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)))
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void)
|
||||
LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*)
|
||||
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_caps_from_string, GstCaps *, const gchar *string)
|
||||
LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index)
|
||||
LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type)
|
||||
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)
|
||||
LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64)
|
||||
|
||||
LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled)
|
||||
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, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug)
|
||||
LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur)
|
||||
LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano)
|
||||
|
||||
LL_GST_SYM( true, gst_message_parse_tag, void, GstMessage *, GstTagList **)
|
||||
LL_GST_SYM( true, gst_tag_list_foreach, void, const GstTagList *, GstTagForeachFunc, gpointer)
|
||||
LL_GST_SYM( true, gst_tag_list_get_tag_size, guint, const GstTagList *, const gchar *)
|
||||
LL_GST_SYM( true, gst_tag_list_get_value_index, const GValue *, const GstTagList *, const gchar *, guint)
|
||||
|
||||
LL_GST_SYM( true, gst_caps_new_simple, GstCaps*, const char *, const char*, ... )
|
||||
|
||||
LL_GST_SYM( true, gst_sample_get_caps, GstCaps*, GstSample* )
|
||||
LL_GST_SYM( true, gst_sample_get_buffer, GstBuffer*, GstSample* )
|
||||
LL_GST_SYM( true, gst_buffer_map, gboolean, GstBuffer*, GstMapInfo*, GstMapFlags )
|
||||
LL_GST_SYM( true, gst_buffer_unmap, void, GstBuffer*, GstMapInfo* )
|
||||
|
||||
LL_GST_SYM( true, gst_app_sink_set_caps, void, GstAppSink*, GstCaps const* )
|
||||
LL_GST_SYM( true, gst_app_sink_pull_sample, GstSample*, GstAppSink* )
|
||||
|
||||
LL_GST_SYM( true, g_free, void, gpointer )
|
||||
LL_GST_SYM( true, g_error_free, void, GError* )
|
||||
|
||||
LL_GST_SYM( true, g_main_context_pending, gboolean, GMainContext* )
|
||||
LL_GST_SYM( true, g_main_loop_get_context, GMainContext*, GMainLoop* )
|
||||
LL_GST_SYM( true, g_main_context_iteration, gboolean, GMainContext*, gboolean )
|
||||
LL_GST_SYM( true, g_main_loop_new, GMainLoop*, GMainContext*, gboolean )
|
||||
LL_GST_SYM( true, g_main_loop_quit, void, GMainLoop* )
|
||||
LL_GST_SYM( true, gst_mini_object_unref, void, GstMiniObject* )
|
||||
LL_GST_SYM( true, g_object_set, void, gpointer, gchar const*, ... )
|
||||
LL_GST_SYM( true, g_source_remove, gboolean, guint )
|
||||
LL_GST_SYM( true, g_value_get_string, gchar const*, GValue const* )
|
||||
|
||||
|
||||
LL_GST_SYM( true, gst_debug_set_active, void, gboolean )
|
||||
LL_GST_SYM( true, gst_debug_add_log_function, void, GstLogFunction, gpointer, GDestroyNotify )
|
||||
LL_GST_SYM( true, gst_debug_set_default_threshold, void, GstDebugLevel )
|
||||
LL_GST_SYM( true, gst_debug_message_get , gchar const*, GstDebugMessage * )
|
||||
|
|
@ -0,0 +1,980 @@
|
|||
/**
|
||||
* @file media_plugin_gstreamer10.cpp
|
||||
* @brief GStreamer-1.0 plugin for LLMedia API plugin system
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2016, Linden Research, Inc. / Nicky Dasmijn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#define FLIP_Y
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llgl.h"
|
||||
|
||||
#include "llplugininstance.h"
|
||||
#include "llpluginmessage.h"
|
||||
#include "llpluginmessageclasses.h"
|
||||
#include "media_plugin_base.h"
|
||||
|
||||
#define G_DISABLE_CAST_CHECKS
|
||||
extern "C" {
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsink.h>
|
||||
|
||||
}
|
||||
|
||||
#include "llmediaimplgstreamer.h"
|
||||
#include "llmediaimplgstreamer_syms.h"
|
||||
|
||||
static inline void llgst_caps_unref( GstCaps * caps )
|
||||
{
|
||||
llgst_mini_object_unref( GST_MINI_OBJECT_CAST( caps ) );
|
||||
}
|
||||
|
||||
static inline void llgst_sample_unref( GstSample *aSample )
|
||||
{
|
||||
llgst_mini_object_unref( GST_MINI_OBJECT_CAST( aSample ) );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class MediaPluginGStreamer10 : public MediaPluginBase
|
||||
{
|
||||
public:
|
||||
MediaPluginGStreamer10(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
|
||||
~MediaPluginGStreamer10();
|
||||
|
||||
/* virtual */ void receiveMessage(const char *message_string);
|
||||
|
||||
static bool startup();
|
||||
static bool closedown();
|
||||
|
||||
gboolean processGSTEvents(GstBus *bus, GstMessage *message);
|
||||
|
||||
private:
|
||||
std::string getVersion();
|
||||
bool navigateTo( const std::string urlIn );
|
||||
bool seek( double time_sec );
|
||||
bool setVolume( float volume );
|
||||
|
||||
// misc
|
||||
bool pause();
|
||||
bool stop();
|
||||
bool play(double rate);
|
||||
bool getTimePos(double &sec_out);
|
||||
|
||||
double MIN_LOOP_SEC = 1.0F;
|
||||
U32 INTERNAL_TEXTURE_SIZE = 1024;
|
||||
|
||||
bool mIsLooping;
|
||||
|
||||
enum ECommand {
|
||||
COMMAND_NONE,
|
||||
COMMAND_STOP,
|
||||
COMMAND_PLAY,
|
||||
COMMAND_FAST_FORWARD,
|
||||
COMMAND_FAST_REWIND,
|
||||
COMMAND_PAUSE,
|
||||
COMMAND_SEEK,
|
||||
};
|
||||
ECommand mCommand;
|
||||
|
||||
private:
|
||||
bool unload();
|
||||
bool load();
|
||||
|
||||
bool update(int milliseconds);
|
||||
void mouseDown( int x, int y );
|
||||
void mouseUp( int x, int y );
|
||||
void mouseMove( int x, int y );
|
||||
|
||||
static bool mDoneInit;
|
||||
|
||||
guint mBusWatchID;
|
||||
|
||||
float mVolume;
|
||||
|
||||
int mDepth;
|
||||
|
||||
// padded texture size we need to write into
|
||||
int mTextureWidth;
|
||||
int mTextureHeight;
|
||||
|
||||
bool mSeekWanted;
|
||||
double mSeekDestination;
|
||||
|
||||
// Very GStreamer-specific
|
||||
GMainLoop *mPump; // event pump for this media
|
||||
GstElement *mPlaybin;
|
||||
GstAppSink *mAppSink;
|
||||
};
|
||||
|
||||
//static
|
||||
bool MediaPluginGStreamer10::mDoneInit = false;
|
||||
|
||||
MediaPluginGStreamer10::MediaPluginGStreamer10( LLPluginInstance::sendMessageFunction host_send_func,
|
||||
void *host_user_data )
|
||||
: MediaPluginBase(host_send_func, host_user_data)
|
||||
, mBusWatchID ( 0 )
|
||||
, mSeekWanted(false)
|
||||
, mSeekDestination(0.0)
|
||||
, mPump ( NULL )
|
||||
, mPlaybin ( NULL )
|
||||
, mAppSink ( NULL )
|
||||
, mCommand ( COMMAND_NONE )
|
||||
{
|
||||
}
|
||||
|
||||
gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *message)
|
||||
{
|
||||
if (!message)
|
||||
return TRUE; // shield against GStreamer bug
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
switch (new_state)
|
||||
{
|
||||
case GST_STATE_VOID_PENDING:
|
||||
break;
|
||||
case GST_STATE_NULL:
|
||||
break;
|
||||
case GST_STATE_READY:
|
||||
setStatus(STATUS_LOADED);
|
||||
break;
|
||||
case GST_STATE_PAUSED:
|
||||
setStatus(STATUS_PAUSED);
|
||||
break;
|
||||
case GST_STATE_PLAYING:
|
||||
setStatus(STATUS_PLAYING);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar *debug = NULL;
|
||||
|
||||
llgst_message_parse_error (message, &err, &debug);
|
||||
if (err)
|
||||
llg_error_free (err);
|
||||
llg_free (debug);
|
||||
|
||||
mCommand = COMMAND_STOP;
|
||||
|
||||
setStatus(STATUS_ERROR);
|
||||
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_INFO:
|
||||
{
|
||||
if (llgst_message_parse_info)
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar *debug = NULL;
|
||||
|
||||
llgst_message_parse_info (message, &err, &debug);
|
||||
if (err)
|
||||
llg_error_free (err);
|
||||
llg_free (debug);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_WARNING:
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar *debug = NULL;
|
||||
|
||||
llgst_message_parse_warning (message, &err, &debug);
|
||||
if (err)
|
||||
llg_error_free (err);
|
||||
llg_free (debug);
|
||||
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_EOS:
|
||||
/* end-of-stream */
|
||||
if (mIsLooping)
|
||||
{
|
||||
double eos_pos_sec = 0.0F;
|
||||
bool got_eos_position = getTimePos(eos_pos_sec);
|
||||
|
||||
if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
|
||||
{
|
||||
// if we know that the movie is really short, don't
|
||||
// loop it else it can easily become a time-hog
|
||||
// because of GStreamer spin-up overhead
|
||||
// inject a COMMAND_PAUSE
|
||||
mCommand = COMMAND_PAUSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
stop();
|
||||
play(1.0);
|
||||
}
|
||||
}
|
||||
else // not a looping media
|
||||
{
|
||||
// inject a COMMAND_STOP
|
||||
mCommand = COMMAND_STOP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* unhandled message */
|
||||
break;
|
||||
}
|
||||
|
||||
/* we want to be notified again the next time there is a message
|
||||
* on the bus, so return true (false means we want to stop watching
|
||||
* for messages on the bus and our callback should not be called again)
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
gboolean llmediaimplgstreamer_bus_callback (GstBus *bus,
|
||||
GstMessage *message,
|
||||
gpointer data)
|
||||
{
|
||||
MediaPluginGStreamer10 *impl = (MediaPluginGStreamer10*)data;
|
||||
return impl->processGSTEvents(bus, message);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
|
||||
|
||||
bool MediaPluginGStreamer10::navigateTo ( const std::string urlIn )
|
||||
{
|
||||
if (!mDoneInit)
|
||||
return false; // error
|
||||
|
||||
setStatus(STATUS_LOADING);
|
||||
|
||||
mSeekWanted = false;
|
||||
|
||||
if (NULL == mPump || NULL == mPlaybin)
|
||||
{
|
||||
setStatus(STATUS_ERROR);
|
||||
return false; // error
|
||||
}
|
||||
|
||||
llg_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
|
||||
|
||||
// navigateTo implicitly plays, too.
|
||||
play(1.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
class GstSampleUnref
|
||||
{
|
||||
GstSample *mT;
|
||||
public:
|
||||
GstSampleUnref( GstSample *aT )
|
||||
: mT( aT )
|
||||
{ llassert_always( mT ); }
|
||||
|
||||
~GstSampleUnref( )
|
||||
{ llgst_sample_unref( mT ); }
|
||||
};
|
||||
|
||||
bool MediaPluginGStreamer10::update(int milliseconds)
|
||||
{
|
||||
if (!mDoneInit)
|
||||
return false; // error
|
||||
|
||||
// DEBUGMSG("updating media...");
|
||||
|
||||
// sanity check
|
||||
if (NULL == mPump || NULL == mPlaybin)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// see if there's an outstanding seek wanted
|
||||
if (mSeekWanted &&
|
||||
// bleh, GST has to be happy that the movie is really truly playing
|
||||
// or it may quietly ignore the seek (with rtsp:// at least).
|
||||
(GST_STATE(mPlaybin) == GST_STATE_PLAYING))
|
||||
{
|
||||
seek(mSeekDestination);
|
||||
mSeekWanted = false;
|
||||
}
|
||||
|
||||
// *TODO: time-limit - but there isn't a lot we can do here, most
|
||||
// time is spent in gstreamer's own opaque worker-threads. maybe
|
||||
// we can do something sneaky like only unlock the video object
|
||||
// for 'milliseconds' and otherwise hold the lock.
|
||||
while (llg_main_context_pending(llg_main_loop_get_context(mPump)))
|
||||
{
|
||||
llg_main_context_iteration(llg_main_loop_get_context(mPump), FALSE);
|
||||
}
|
||||
|
||||
// check for availability of a new frame
|
||||
|
||||
if( !mAppSink )
|
||||
return true;
|
||||
|
||||
if( GST_STATE(mPlaybin) != GST_STATE_PLAYING) // Do not try to pull a sample if not in playing state
|
||||
return true;
|
||||
|
||||
GstSample *pSample = llgst_app_sink_pull_sample( mAppSink );
|
||||
if(!pSample)
|
||||
return false; // Done playing
|
||||
|
||||
GstSampleUnref oSampleUnref( pSample );
|
||||
GstCaps *pCaps = llgst_sample_get_caps ( pSample );
|
||||
if (!pCaps)
|
||||
return false;
|
||||
|
||||
gint width, height;
|
||||
GstStructure *pStruct = llgst_caps_get_structure ( pCaps, 0);
|
||||
|
||||
int res = llgst_structure_get_int ( pStruct, "width", &width);
|
||||
res |= llgst_structure_get_int ( pStruct, "height", &height);
|
||||
|
||||
if( !mPixels )
|
||||
return true;
|
||||
|
||||
GstBuffer *pBuffer = llgst_sample_get_buffer ( pSample );
|
||||
GstMapInfo map;
|
||||
llgst_buffer_map ( pBuffer, &map, GST_MAP_READ);
|
||||
|
||||
// Our render buffer is always 1kx1k
|
||||
|
||||
U32 rowSkip = INTERNAL_TEXTURE_SIZE / mTextureHeight;
|
||||
U32 colSkip = INTERNAL_TEXTURE_SIZE / mTextureWidth;
|
||||
|
||||
for (int row = 0; row < mTextureHeight; ++row)
|
||||
{
|
||||
U8 const *pTexelIn = map.data + (row*rowSkip * width *3);
|
||||
#ifndef FLIP_Y
|
||||
U8 *pTexelOut = mPixels + (row * mTextureWidth * mDepth );
|
||||
#else
|
||||
U8 *pTexelOut = mPixels + ((mTextureHeight-row-1) * mTextureWidth * mDepth );
|
||||
#endif
|
||||
for( int col = 0; col < mTextureWidth; ++col )
|
||||
{
|
||||
pTexelOut[ 0 ] = pTexelIn[0];
|
||||
pTexelOut[ 1 ] = pTexelIn[1];
|
||||
pTexelOut[ 2 ] = pTexelIn[2];
|
||||
pTexelOut += mDepth;
|
||||
pTexelIn += colSkip*3;
|
||||
}
|
||||
}
|
||||
|
||||
llgst_buffer_unmap( pBuffer, &map );
|
||||
setDirty(0,0,mTextureWidth,mTextureHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MediaPluginGStreamer10::mouseDown( int x, int y )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void MediaPluginGStreamer10::mouseUp( int x, int y )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void MediaPluginGStreamer10::mouseMove( int x, int y )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
bool MediaPluginGStreamer10::pause()
|
||||
{
|
||||
// todo: error-check this?
|
||||
if (mDoneInit && mPlaybin)
|
||||
{
|
||||
llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::stop()
|
||||
{
|
||||
// todo: error-check this?
|
||||
if (mDoneInit && mPlaybin)
|
||||
{
|
||||
llgst_element_set_state(mPlaybin, GST_STATE_READY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::play(double rate)
|
||||
{
|
||||
// NOTE: we don't actually support non-natural rate.
|
||||
|
||||
// todo: error-check this?
|
||||
if (mDoneInit && mPlaybin)
|
||||
{
|
||||
llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::setVolume( float volume )
|
||||
{
|
||||
// we try to only update volume as conservatively as
|
||||
// possible, as many gst-plugins-base versions up to at least
|
||||
// November 2008 have critical race-conditions in setting volume - sigh
|
||||
if (mVolume == volume)
|
||||
return true; // nothing to do, everything's fine
|
||||
|
||||
mVolume = volume;
|
||||
if (mDoneInit && mPlaybin)
|
||||
{
|
||||
llg_object_set(mPlaybin, "volume", mVolume, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::seek(double time_sec)
|
||||
{
|
||||
bool success = false;
|
||||
if (mDoneInit && mPlaybin)
|
||||
{
|
||||
success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
|
||||
GstSeekFlags(GST_SEEK_FLAG_FLUSH |
|
||||
GST_SEEK_FLAG_KEY_UNIT),
|
||||
GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
|
||||
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::getTimePos(double &sec_out)
|
||||
{
|
||||
bool got_position = false;
|
||||
if (mDoneInit && mPlaybin)
|
||||
{
|
||||
gint64 pos(0);
|
||||
GstFormat timefmt = GST_FORMAT_TIME;
|
||||
got_position =
|
||||
llgst_element_query_position &&
|
||||
llgst_element_query_position(mPlaybin,
|
||||
&timefmt,
|
||||
&pos);
|
||||
got_position = got_position
|
||||
&& (timefmt == GST_FORMAT_TIME);
|
||||
// GStreamer may have other ideas, but we consider the current position
|
||||
// undefined if not PLAYING or PAUSED
|
||||
got_position = got_position &&
|
||||
(GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
|
||||
GST_STATE(mPlaybin) == GST_STATE_PAUSED);
|
||||
if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
|
||||
{
|
||||
if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
|
||||
{
|
||||
// if we're playing then we treat an invalid clock time
|
||||
// as 0, for complicated reasons (insert reason here)
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
got_position = false;
|
||||
}
|
||||
|
||||
}
|
||||
// If all the preconditions succeeded... we can trust the result.
|
||||
if (got_position)
|
||||
{
|
||||
sec_out = double(pos) / double(GST_SECOND); // gst to sec
|
||||
}
|
||||
}
|
||||
return got_position;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::load()
|
||||
{
|
||||
if (!mDoneInit)
|
||||
return false; // error
|
||||
|
||||
setStatus(STATUS_LOADING);
|
||||
|
||||
mIsLooping = false;
|
||||
mVolume = 0.1234567f; // minor hack to force an initial volume update
|
||||
|
||||
// Create a pumpable main-loop for this media
|
||||
mPump = llg_main_loop_new (NULL, FALSE);
|
||||
if (!mPump)
|
||||
{
|
||||
setStatus(STATUS_ERROR);
|
||||
return false; // error
|
||||
}
|
||||
|
||||
// instantiate a playbin element to do the hard work
|
||||
mPlaybin = llgst_element_factory_make ("playbin", "");
|
||||
if (!mPlaybin)
|
||||
{
|
||||
setStatus(STATUS_ERROR);
|
||||
return false; // error
|
||||
}
|
||||
|
||||
// get playbin's bus
|
||||
GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
|
||||
if (!bus)
|
||||
{
|
||||
setStatus(STATUS_ERROR);
|
||||
return false; // error
|
||||
}
|
||||
mBusWatchID = llgst_bus_add_watch (bus,
|
||||
llmediaimplgstreamer_bus_callback,
|
||||
this);
|
||||
llgst_object_unref (bus);
|
||||
|
||||
mAppSink = (GstAppSink*)(llgst_element_factory_make ("appsink", ""));
|
||||
|
||||
GstCaps* pCaps = llgst_caps_new_simple( "video/x-raw",
|
||||
"format", G_TYPE_STRING, "RGB",
|
||||
"width", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
|
||||
"height", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
|
||||
NULL );
|
||||
|
||||
llgst_app_sink_set_caps( mAppSink, pCaps );
|
||||
llgst_caps_unref( pCaps );
|
||||
|
||||
if (!mAppSink)
|
||||
{
|
||||
setStatus(STATUS_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
llg_object_set(mPlaybin, "video-sink", mAppSink, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MediaPluginGStreamer10::unload ()
|
||||
{
|
||||
if (!mDoneInit)
|
||||
return false; // error
|
||||
|
||||
// stop getting callbacks for this bus
|
||||
llg_source_remove(mBusWatchID);
|
||||
mBusWatchID = 0;
|
||||
|
||||
if (mPlaybin)
|
||||
{
|
||||
llgst_element_set_state (mPlaybin, GST_STATE_NULL);
|
||||
llgst_object_unref (GST_OBJECT (mPlaybin));
|
||||
mPlaybin = NULL;
|
||||
}
|
||||
|
||||
if (mPump)
|
||||
{
|
||||
llg_main_loop_quit(mPump);
|
||||
mPump = NULL;
|
||||
}
|
||||
|
||||
mAppSink = NULL;
|
||||
|
||||
setStatus(STATUS_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer user_data )
|
||||
#ifndef LL_LINUX // Docu says we need G_GNUC_NO_INSTRUMENT, but GCC says 'error'
|
||||
G_GNUC_NO_INSTRUMENT
|
||||
#endif
|
||||
{
|
||||
#ifdef LL_LINUX
|
||||
std::cerr << file << ":" << line << "(" << function << "): " << llgst_debug_message_get( message ) << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
bool MediaPluginGStreamer10::startup()
|
||||
{
|
||||
// first - check if GStreamer is explicitly disabled
|
||||
if (NULL != getenv("LL_DISABLE_GSTREAMER"))
|
||||
return false;
|
||||
|
||||
// only do global GStreamer initialization once.
|
||||
if (!mDoneInit)
|
||||
{
|
||||
ll_init_apr();
|
||||
|
||||
// Get symbols!
|
||||
std::vector< std::string > vctDSONames;
|
||||
#if LL_DARWIN
|
||||
#elif LL_WINDOWS
|
||||
vctDSONames.push_back( "libgstreamer-1.0-0.dll" );
|
||||
vctDSONames.push_back( "libgstapp-1.0-0.dll" );
|
||||
vctDSONames.push_back( "libglib-2.0-0.dll" );
|
||||
vctDSONames.push_back( "libgobject-2.0-0.dll" );
|
||||
#else // linux or other ELFy unixoid
|
||||
vctDSONames.push_back( "libgstreamer-1.0.so.0" );
|
||||
vctDSONames.push_back( "libgstapp-1.0.so.0" );
|
||||
vctDSONames.push_back( "libglib-2.0.so.0" );
|
||||
vctDSONames.push_back( "libgobject-2.0.so" );
|
||||
#endif
|
||||
if( !grab_gst_syms( vctDSONames ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (llgst_segtrap_set_enabled)
|
||||
{
|
||||
llgst_segtrap_set_enabled(FALSE);
|
||||
}
|
||||
#if LL_LINUX
|
||||
// Gstreamer tries a fork during init, waitpid-ing on it,
|
||||
// which conflicts with any installed SIGCHLD handler...
|
||||
struct sigaction tmpact, oldact;
|
||||
if (llgst_registry_fork_set_enabled ) {
|
||||
// if we can disable SIGCHLD-using forking behaviour,
|
||||
// do it.
|
||||
llgst_registry_fork_set_enabled(false);
|
||||
}
|
||||
else {
|
||||
// else temporarily install default SIGCHLD handler
|
||||
// while GStreamer initialises
|
||||
tmpact.sa_handler = SIG_DFL;
|
||||
sigemptyset( &tmpact.sa_mask );
|
||||
tmpact.sa_flags = SA_SIGINFO;
|
||||
sigaction(SIGCHLD, &tmpact, &oldact);
|
||||
}
|
||||
#endif // LL_LINUX
|
||||
// Protect against GStreamer resetting the locale, yuck.
|
||||
static std::string saved_locale;
|
||||
saved_locale = setlocale(LC_ALL, NULL);
|
||||
|
||||
// _putenv_s( "GST_PLUGIN_PATH", "E:\\gstreamer\\1.0\\x86\\lib\\gstreamer-1.0" );
|
||||
|
||||
llgst_debug_set_default_threshold( GST_LEVEL_WARNING );
|
||||
llgst_debug_add_log_function( LogFunction, NULL, NULL );
|
||||
llgst_debug_set_active( false );
|
||||
|
||||
// finally, try to initialize GStreamer!
|
||||
GError *err = NULL;
|
||||
gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
|
||||
|
||||
// restore old locale
|
||||
setlocale(LC_ALL, saved_locale.c_str() );
|
||||
|
||||
#if LL_LINUX
|
||||
// restore old SIGCHLD handler
|
||||
if (!llgst_registry_fork_set_enabled)
|
||||
sigaction(SIGCHLD, &oldact, NULL);
|
||||
#endif // LL_LINUX
|
||||
|
||||
if (!init_gst_success) // fail
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
llg_error_free(err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mDoneInit = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
bool MediaPluginGStreamer10::closedown()
|
||||
{
|
||||
if (!mDoneInit)
|
||||
return false; // error
|
||||
|
||||
ungrab_gst_syms();
|
||||
|
||||
mDoneInit = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MediaPluginGStreamer10::~MediaPluginGStreamer10()
|
||||
{
|
||||
closedown();
|
||||
}
|
||||
|
||||
|
||||
std::string MediaPluginGStreamer10::getVersion()
|
||||
{
|
||||
std::string plugin_version = "GStreamer10 media plugin, GStreamer version ";
|
||||
if (mDoneInit &&
|
||||
llgst_version)
|
||||
{
|
||||
guint major, minor, micro, nano;
|
||||
llgst_version(&major, &minor, µ, &nano);
|
||||
plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor,
|
||||
(unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR,
|
||||
(unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_version += "(unknown)";
|
||||
}
|
||||
return plugin_version;
|
||||
}
|
||||
|
||||
void MediaPluginGStreamer10::receiveMessage(const char *message_string)
|
||||
{
|
||||
LLPluginMessage message_in;
|
||||
|
||||
if(message_in.parse(message_string) >= 0)
|
||||
{
|
||||
std::string message_class = message_in.getClass();
|
||||
std::string message_name = message_in.getName();
|
||||
|
||||
if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
|
||||
{
|
||||
if(message_name == "init")
|
||||
{
|
||||
LLPluginMessage message("base", "init_response");
|
||||
LLSD versions = LLSD::emptyMap();
|
||||
versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
|
||||
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
|
||||
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
|
||||
message.setValueLLSD("versions", versions);
|
||||
|
||||
load();
|
||||
|
||||
message.setValue("plugin_version", getVersion());
|
||||
sendMessage(message);
|
||||
}
|
||||
else if(message_name == "idle")
|
||||
{
|
||||
// no response is necessary here.
|
||||
double time = message_in.getValueReal("time");
|
||||
|
||||
// Convert time to milliseconds for update()
|
||||
update((int)(time * 1000.0f));
|
||||
}
|
||||
else if(message_name == "cleanup")
|
||||
{
|
||||
unload();
|
||||
closedown();
|
||||
}
|
||||
else if(message_name == "shm_added")
|
||||
{
|
||||
SharedSegmentInfo info;
|
||||
info.mAddress = message_in.getValuePointer("address");
|
||||
info.mSize = (size_t)message_in.getValueS32("size");
|
||||
std::string name = message_in.getValue("name");
|
||||
|
||||
mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
|
||||
}
|
||||
else if(message_name == "shm_remove")
|
||||
{
|
||||
std::string name = message_in.getValue("name");
|
||||
|
||||
SharedSegmentMap::iterator iter = mSharedSegments.find(name);
|
||||
if(iter != mSharedSegments.end())
|
||||
{
|
||||
if(mPixels == iter->second.mAddress)
|
||||
{
|
||||
// This is the currently active pixel buffer. Make sure we stop drawing to it.
|
||||
mPixels = NULL;
|
||||
mTextureSegmentName.clear();
|
||||
}
|
||||
mSharedSegments.erase(iter);
|
||||
}
|
||||
|
||||
// Send the response so it can be cleaned up.
|
||||
LLPluginMessage message("base", "shm_remove_response");
|
||||
message.setValue("name", name);
|
||||
sendMessage(message);
|
||||
}
|
||||
}
|
||||
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
|
||||
{
|
||||
if(message_name == "init")
|
||||
{
|
||||
// Plugin gets to decide the texture parameters to use.
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
|
||||
// lame to have to decide this now, it depends on the movie. Oh well.
|
||||
mDepth = 4;
|
||||
|
||||
mTextureWidth = 1;
|
||||
mTextureHeight = 1;
|
||||
|
||||
message.setValueU32("format", GL_RGBA);
|
||||
message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
|
||||
|
||||
message.setValueS32("depth", mDepth);
|
||||
message.setValueS32("default_width", INTERNAL_TEXTURE_SIZE );
|
||||
message.setValueS32("default_height", INTERNAL_TEXTURE_SIZE );
|
||||
message.setValueU32("internalformat", GL_RGBA8);
|
||||
message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
|
||||
message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
|
||||
sendMessage(message);
|
||||
}
|
||||
else if(message_name == "size_change")
|
||||
{
|
||||
std::string name = message_in.getValue("name");
|
||||
S32 width = message_in.getValueS32("width");
|
||||
S32 height = message_in.getValueS32("height");
|
||||
S32 texture_width = message_in.getValueS32("texture_width");
|
||||
S32 texture_height = message_in.getValueS32("texture_height");
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
|
||||
message.setValue("name", name);
|
||||
message.setValueS32("width", width);
|
||||
message.setValueS32("height", height);
|
||||
message.setValueS32("texture_width", texture_width);
|
||||
message.setValueS32("texture_height", texture_height);
|
||||
sendMessage(message);
|
||||
|
||||
if(!name.empty())
|
||||
{
|
||||
// Find the shared memory region with this name
|
||||
SharedSegmentMap::iterator iter = mSharedSegments.find(name);
|
||||
if(iter != mSharedSegments.end())
|
||||
{
|
||||
mPixels = (unsigned char*)iter->second.mAddress;
|
||||
mTextureSegmentName = name;
|
||||
|
||||
mTextureWidth = texture_width;
|
||||
mTextureHeight = texture_height;
|
||||
memset( mPixels, 0, mTextureWidth*mTextureHeight*mDepth );
|
||||
}
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
|
||||
message.setValue("name", mTextureSegmentName);
|
||||
message.setValueS32("width", INTERNAL_TEXTURE_SIZE );
|
||||
message.setValueS32("height", INTERNAL_TEXTURE_SIZE );
|
||||
sendMessage(message);
|
||||
|
||||
}
|
||||
}
|
||||
else if(message_name == "load_uri")
|
||||
{
|
||||
std::string uri = message_in.getValue("uri");
|
||||
navigateTo( uri );
|
||||
sendStatus();
|
||||
}
|
||||
else if(message_name == "mouse_event")
|
||||
{
|
||||
std::string event = message_in.getValue("event");
|
||||
S32 x = message_in.getValueS32("x");
|
||||
S32 y = message_in.getValueS32("y");
|
||||
|
||||
if(event == "down")
|
||||
{
|
||||
mouseDown(x, y);
|
||||
}
|
||||
else if(event == "up")
|
||||
{
|
||||
mouseUp(x, y);
|
||||
}
|
||||
else if(event == "move")
|
||||
{
|
||||
mouseMove(x, y);
|
||||
};
|
||||
};
|
||||
}
|
||||
else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
|
||||
{
|
||||
if(message_name == "stop")
|
||||
{
|
||||
stop();
|
||||
}
|
||||
else if(message_name == "start")
|
||||
{
|
||||
double rate = 0.0;
|
||||
if(message_in.hasValue("rate"))
|
||||
{
|
||||
rate = message_in.getValueReal("rate");
|
||||
}
|
||||
// NOTE: we don't actually support rate.
|
||||
play(rate);
|
||||
}
|
||||
else if(message_name == "pause")
|
||||
{
|
||||
pause();
|
||||
}
|
||||
else if(message_name == "seek")
|
||||
{
|
||||
double time = message_in.getValueReal("time");
|
||||
// defer the actual seek in case we haven't
|
||||
// really truly started yet in which case there
|
||||
// is nothing to seek upon
|
||||
mSeekWanted = true;
|
||||
mSeekDestination = time;
|
||||
}
|
||||
else if(message_name == "set_loop")
|
||||
{
|
||||
bool loop = message_in.getValueBoolean("loop");
|
||||
mIsLooping = loop;
|
||||
}
|
||||
else if(message_name == "set_volume")
|
||||
{
|
||||
double volume = message_in.getValueReal("volume");
|
||||
setVolume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
|
||||
{
|
||||
if( MediaPluginGStreamer10::startup() )
|
||||
{
|
||||
MediaPluginGStreamer10 *self = new MediaPluginGStreamer10(host_send_func, host_user_data);
|
||||
*plugin_send_func = MediaPluginGStreamer10::staticReceiveMessage;
|
||||
*plugin_user_data = (void*)self;
|
||||
|
||||
return 0; // okay
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; // failed to init
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ include(BuildPackagesInfo)
|
|||
include(BuildVersion)
|
||||
include(CMakeCopyIfDifferent)
|
||||
include(CubemapToEquirectangularJS)
|
||||
include(DBusGlib)
|
||||
include(GLIB)
|
||||
include(DragDrop)
|
||||
include(EXPAT)
|
||||
include(FMODSTUDIO)
|
||||
|
|
@ -1797,7 +1797,6 @@ if (LINUX)
|
|||
# fsversionstrings.h with the right numbers in it.
|
||||
# COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
|
||||
)
|
||||
LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
|
||||
# [FS] Growl support
|
||||
LIST(APPEND viewer_HEADER_FILES desktopnotifierlinux.h growlmanager.h)
|
||||
LIST(APPEND viewer_SOURCE_FILES desktopnotifierlinux.cpp growlmanager.cpp)
|
||||
|
|
@ -1865,6 +1864,8 @@ if (WINDOWS)
|
|||
COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
|
||||
)
|
||||
|
||||
set_source_files_properties( llappviewer.cpp llviewermenu.cpp PROPERTIES COMPILE_FLAGS /bigobj )
|
||||
|
||||
list(APPEND viewer_HEADER_FILES
|
||||
llappviewerwin32.h
|
||||
llwindebug.h
|
||||
|
|
@ -2518,7 +2519,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${BOOST_WAVE_LIBRARY} #FS specific
|
||||
${BOOST_THREAD_LIBRARY} #FS specific
|
||||
${BOOST_CONTEXT_LIBRARY}
|
||||
${DBUSGLIB_LIBRARIES}
|
||||
${GLIB_LIBRARIES}
|
||||
${OPENGL_LIBRARIES}
|
||||
${FMODWRAPPER_LIBRARY} # must come after LLAudio
|
||||
${OPENAL_LIBRARIES}
|
||||
|
|
@ -2538,6 +2539,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${LLPHYSICSEXTENSIONS_LIBRARIES}
|
||||
${LLAPPEARANCE_LIBRARIES}
|
||||
${GROWL_LIBRARY}
|
||||
${GIO_LIBRARIES}
|
||||
)
|
||||
|
||||
target_link_libraries(${VIEWER_BINARY_NAME} ${DISCORD_LIBRARY} )
|
||||
|
|
@ -2565,26 +2567,30 @@ if (LINUX)
|
|||
set(product Firestorm-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION})
|
||||
|
||||
# These are the generated targets that are copied to package/
|
||||
if (NOT ENABLE_MEDIA_PLUGINS)
|
||||
set(COPY_INPUT_DEPENDENCIES
|
||||
${VIEWER_BINARY_NAME}
|
||||
SLPlugin
|
||||
media_plugin_cef
|
||||
#media_plugin_gstreamer010
|
||||
media_plugin_libvlc
|
||||
llcommon
|
||||
)
|
||||
else (NOT ENABLE_MEDIA_PLUGINS)
|
||||
set(COPY_INPUT_DEPENDENCIES
|
||||
${VIEWER_BINARY_NAME}
|
||||
#linux-crash-logger
|
||||
SLPlugin
|
||||
media_plugin_cef
|
||||
#media_plugin_gstreamer010
|
||||
llcommon
|
||||
)
|
||||
endif (NOT ENABLE_MEDIA_PLUGINS)
|
||||
if (NOT ENABLE_MEDIA_PLUGINS)
|
||||
set(COPY_INPUT_DEPENDENCIES
|
||||
${VIEWER_BINARY_NAME}
|
||||
SLPlugin
|
||||
media_plugin_cef
|
||||
media_plugin_gstreamer10
|
||||
#media_plugin_libvlc
|
||||
llcommon
|
||||
linux-crash-logger
|
||||
)
|
||||
else (NOT ENABLE_MEDIA_PLUGINS)
|
||||
set(COPY_INPUT_DEPENDENCIES
|
||||
${VIEWER_BINARY_NAME}
|
||||
#linux-crash-logger
|
||||
SLPlugin
|
||||
media_plugin_cef
|
||||
media_plugin_gstreamer10
|
||||
llcommon
|
||||
linux-crash-logger
|
||||
)
|
||||
endif (NOT ENABLE_MEDIA_PLUGINS)
|
||||
|
||||
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer10 media_plugin_cef linux-crash-logger)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${product}.tar.bz2
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
|
|
@ -2610,7 +2616,6 @@ endif (NOT ENABLE_MEDIA_PLUGINS)
|
|||
${COPY_INPUT_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
|
|
@ -2861,8 +2866,10 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
|
|||
endif (LINUX)
|
||||
endif (USE_BUGSPLAT)
|
||||
|
||||
# for both Bugsplat and Breakpad
|
||||
add_dependencies(llpackage generate_symbols)
|
||||
if (NOT LINUX) #Linux generates symbols via viewer_manifest.py/fs_viewer_manifest.py
|
||||
# for both Bugsplat and Breakpad
|
||||
add_dependencies(llpackage generate_symbols)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (LL_TESTS)
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@
|
|||
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
|
||||
<string key="NSFrameAutosaveName">Second Life</string>
|
||||
<int key="NSWindowCollectionBehavior">128</int>
|
||||
<bool key="NSWindowIsRestorable">YES</bool>
|
||||
<bool key="NSWindowIsRestorable">NO</bool>
|
||||
</object>
|
||||
<object class="NSWindowTemplate" id="979091056">
|
||||
<int key="NSWindowStyleMask">31</int>
|
||||
|
|
|
|||
|
|
@ -11123,7 +11123,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>PushToTalkToggle</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Should the push-to-talk button behave as a toggle</string>
|
||||
<string>Should the push-to-talk toolbar button behave as a toggle</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -11167,7 +11167,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>QAModeMetrics</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>"Enables QA features (logging, faster cycling) for metrics collector"</string>
|
||||
<string>Enables QA features (logging, faster cycling) for metrics collector</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -11177,8 +11177,18 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>QuitAfterSeconds</key>
|
||||
<key>QAModeFakeSystemFolderIssues</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Simulates system folder issues in inventory</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>QuitAfterSeconds</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The duration allowed before quitting.</string>
|
||||
|
|
@ -15699,6 +15709,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>TextureFetchMinTimeToLog</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>If texture fetching time exceeds this value, texture fetch tester will log info</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>2.0</real>
|
||||
</map>
|
||||
<key>TextureFetchFakeFailureRate</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -15801,6 +15822,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>TextureListFetchingThreshold</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>If the ratio between fetched and all textures in the list is greater than this threshold, which we assume that almost all textures are fetched</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.97</real>
|
||||
</map>
|
||||
<key>TextureLoadFullRes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -25914,6 +25946,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSAutoTuneLock</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When enabled the viewer will dynamically change settings until auto tune is explicitly turned off.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAllowSelfImpostor</key>
|
||||
|
|
@ -25993,6 +26036,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSUserTargetReflections</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Set by auto tune floater on build</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>4</integer>
|
||||
</map>
|
||||
<key>FSReportRegionRestartToChat</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ def munge_binding_redirect_version(src_manifest_name, src_config_name, dst_confi
|
|||
comment = config_dom.createComment("This file is automatically generated by the build. see indra/newview/build_win32_appConfig.py")
|
||||
config_dom.insertBefore(comment, config_dom.childNodes[0])
|
||||
|
||||
print "Writing: " + dst_config_name
|
||||
print("Writing: " + dst_config_name)
|
||||
f = open(dst_config_name, 'w')
|
||||
config_dom.writexml(f)
|
||||
f.close()
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -9,7 +9,7 @@ class FSViewerManifest:
|
|||
def fs_splice_grid_substitution_strings( self, subst_strings ):
|
||||
ret = subst_strings
|
||||
|
||||
if self.args.has_key( 'grid' ) and self.args['grid'] != None:
|
||||
if 'grid' in self.args and self.args['grid'] != None:
|
||||
ret[ 'grid' ] = self.args['grid']
|
||||
ret[ 'grid_caps' ] = self.args['grid'].upper()
|
||||
else:
|
||||
|
|
@ -51,15 +51,15 @@ class FSViewerManifest:
|
|||
stderr=subprocess.PIPE,stdout=subprocess.PIPE)
|
||||
subprocess.check_call(["signtool.exe","sign","/n","Phoenix","/d","Firestorm","/du","http://www.phoenixviewer.com","/t","http://timestamp.verisign.com/scripts/timstamp.dll",self.args['configuration']+"\\"+self.final_exe()],
|
||||
stderr=subprocess.PIPE,stdout=subprocess.PIPE)
|
||||
except Exception, e:
|
||||
print "Couldn't sign final binary. Tried to sign %s" % self.args['configuration']+"\\"+self.final_exe()
|
||||
except Exception as e:
|
||||
print("Couldn't sign final binary. Tried to sign %s" % self.args['configuration']+"\\"+self.final_exe())
|
||||
|
||||
def fs_sign_win_installer( self, substitution_strings ):
|
||||
try:
|
||||
subprocess.check_call(["signtool.exe","sign","/n","Phoenix","/d","Firestorm","/du","http://www.phoenixviewer.com",self.args['configuration']+"\\"+substitution_strings['installer_file']],stderr=subprocess.PIPE,stdout=subprocess.PIPE)
|
||||
except Exception, e:
|
||||
print "Working directory: %s" % os.getcwd()
|
||||
print "Couldn't sign windows installer. Tried to sign %s" % self.args['configuration']+"\\"+substitution_strings['installer_file']
|
||||
except Exception as e:
|
||||
print("Working directory: %s" % os.getcwd())
|
||||
print("Couldn't sign windows installer. Tried to sign %s" % self.args['configuration']+"\\"+substitution_strings['installer_file'])
|
||||
|
||||
def fs_delete_linux_symbols( self ):
|
||||
debugDir = os.path.join( self.get_dst_prefix(), "bin", ".debug" )
|
||||
|
|
@ -76,7 +76,7 @@ class FSViewerManifest:
|
|||
def fs_save_linux_symbols( self ):
|
||||
#AO: Try to package up symbols
|
||||
# New Method, for reading cross platform stack traces on a linux/mac host
|
||||
print( "Packaging symbols" )
|
||||
print("Packaging symbols")
|
||||
|
||||
self.fs_save_symbols("linux")
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ class FSViewerManifest:
|
|||
], stderr=subprocess.PIPE,stdout=subprocess.PIPE )
|
||||
pdbName = "firestorm-bin-public.pdb"
|
||||
except:
|
||||
print( "Cannot run pdbcopy, packaging private symbols" )
|
||||
print("Cannot run pdbcopy, packaging private symbols")
|
||||
|
||||
# Store windows symbols we want to keep for debugging in a tar file, this will be later compressed with xz (lzma)
|
||||
# Using tat+xz gives far superior compression than zip (~half the size of the zip archive).
|
||||
|
|
@ -162,3 +162,63 @@ class FSViewerManifest:
|
|||
if self.path( src,dst ) == 0:
|
||||
self.missing.pop()
|
||||
|
||||
def fs_generate_breakpad_symbols_for_file( self, aFile ):
|
||||
from os import makedirs, remove
|
||||
from os.path import join, isfile
|
||||
import subprocess
|
||||
from shutil import move
|
||||
|
||||
dumpSym = join( self.args["build"], "..", "packages", "bin", "dump_syms" )
|
||||
if not isfile( dumpSym ):
|
||||
return
|
||||
|
||||
symbolFile = aFile +".sym"
|
||||
|
||||
with open( symbolFile, "w") as outfile:
|
||||
subprocess.call( [dumpSym, aFile ], stdout=outfile )
|
||||
|
||||
firstline = open( symbolFile ).readline().strip()
|
||||
|
||||
if firstline != "":
|
||||
module, os, bitness, hash, filename = firstline.split(" ")
|
||||
symbolDir = join( "symbols", filename, hash )
|
||||
try:
|
||||
makedirs( symbolDir )
|
||||
except:
|
||||
pass
|
||||
move( symbolFile, symbolDir )
|
||||
|
||||
if isfile( symbolFile ):
|
||||
remove( symbolFile )
|
||||
|
||||
def fs_save_breakpad_symbols(self, osname):
|
||||
from glob import glob
|
||||
import sys
|
||||
from os.path import isdir
|
||||
from shutil import rmtree
|
||||
import tarfile
|
||||
|
||||
if isdir( "symbols" ):
|
||||
rmtree( "symbols" )
|
||||
|
||||
files = glob( "%s/bin/*" % self.args['dest'] )
|
||||
for f in files:
|
||||
self.fs_generate_breakpad_symbols_for_file( f )
|
||||
|
||||
files = glob( "%s/lib/*.so" % self.args['dest'] )
|
||||
for f in files:
|
||||
if f.find( "libcef.so" ) == -1:
|
||||
self.fs_generate_breakpad_symbols_for_file( f )
|
||||
|
||||
if isdir( "symbols" ):
|
||||
for a in self.args:
|
||||
print("%s: %s" % (a, self.args[a]))
|
||||
symbolsName = "%s/Phoenix_%s_%s_%s_symbols-%s-%d.tar.bz2" % (self.args['configuration'].lower(),
|
||||
self.fs_channel_legacy_oneword(),
|
||||
'-'.join( self.args['version'] ),
|
||||
self.args['viewer_flavor'],
|
||||
osname,
|
||||
self.address_size)
|
||||
|
||||
fTar = tarfile.open( symbolsName, "w:bz2")
|
||||
fTar.add("symbols", arcname=".")
|
||||
|
|
|
|||
|
|
@ -51,8 +51,12 @@
|
|||
#include "pipeline.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "fsavatarrenderpersistence.h"
|
||||
#include "llpresetsmanager.h"
|
||||
#include "fsperfstats.h" // <FS:Beq> performance stats support
|
||||
#include "fslslbridge.h"
|
||||
#include <llbutton.h>
|
||||
|
||||
extern F32 gSavedDrawDistance;
|
||||
|
||||
const F32 REFRESH_INTERVAL = 1.0f;
|
||||
const S32 BAR_LEFT_PAD = 2;
|
||||
|
|
@ -119,8 +123,11 @@ BOOL FSFloaterPerformance::postBuild()
|
|||
auto tgt_panel = findChild<LLPanel>("target_subpanel");
|
||||
if (tgt_panel)
|
||||
{
|
||||
tgt_panel->getChild<LLButton>("target_btn")->setCommitCallback(boost::bind(&FSFloaterPerformance::showSelectedPanel, this, mAutoTunePanel));
|
||||
tgt_panel->getChild<LLComboBox>("FSTuningFPSStrategy")->setCurrentByIndex(gSavedSettings.getU32("FSTuningFPSStrategy"));
|
||||
tgt_panel->getChild<LLButton>("target_btn")->setCommitCallback(boost::bind(&FSFloaterPerformance::showSelectedPanel, this, mAutoTunePanel));
|
||||
tgt_panel->getChild<LLComboBox>("FSTuningFPSStrategy")->setCurrentByIndex(gSavedSettings.getU32("FSTuningFPSStrategy"));
|
||||
tgt_panel->getChild<LLButton>("PrefSaveButton")->setCommitCallback(boost::bind(&FSFloaterPerformance::savePreset, this));
|
||||
tgt_panel->getChild<LLButton>("PrefLoadButton")->setCommitCallback(boost::bind(&FSFloaterPerformance::loadPreset, this));
|
||||
tgt_panel->getChild<LLButton>("Defaults")->setCommitCallback(boost::bind(&FSFloaterPerformance::setHardwareDefaults, this));
|
||||
}
|
||||
|
||||
initBackBtn(mNearbyPanel);
|
||||
|
|
@ -139,13 +146,14 @@ BOOL FSFloaterPerformance::postBuild()
|
|||
mObjectList->setHoverIconName("StopReload_Off");
|
||||
mObjectList->setIconClickedCallback(boost::bind(&FSFloaterPerformance::detachItem, this, _1));
|
||||
|
||||
mSettingsPanel->getChild<LLRadioGroup>("graphics_quality")->setCommitCallback(boost::bind(&FSFloaterPerformance::onChangeQuality, this, _2));
|
||||
mSettingsPanel->getChild<LLSliderCtrl>("quality_vs_perf_selection")->setCommitCallback(boost::bind(&FSFloaterPerformance::onChangeQuality, this, _2));
|
||||
|
||||
mNearbyPanel->getChild<LLButton>("exceptions_btn")->setCommitCallback(boost::bind(&FSFloaterPerformance::onClickExceptions, this));
|
||||
mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->setCommitCallback(boost::bind(&FSFloaterPerformance::onClickHideAvatars, this));
|
||||
mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR));
|
||||
mNearbyList = mNearbyPanel->getChild<LLNameListCtrl>("nearby_list");
|
||||
mNearbyList->setRightMouseDownCallback(boost::bind(&FSFloaterPerformance::onAvatarListRightClick, this, _1, _2, _3));
|
||||
|
||||
|
||||
updateComplexityText();
|
||||
mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&FSFloaterPerformance::updateComplexityText, this));
|
||||
|
|
@ -155,10 +163,53 @@ BOOL FSFloaterPerformance::postBuild()
|
|||
mNearbyPanel->getChild<LLSliderCtrl>("FSRenderAvatarMaxART")->setCommitCallback(boost::bind(&FSFloaterPerformance::updateMaxRenderTime, this));
|
||||
|
||||
LLAvatarComplexityControls::setIndirectMaxArc();
|
||||
// store the current setting as the users desired reflection detail and DD
|
||||
gSavedSettings.setS32("FSUserTargetReflections", LLPipeline::RenderReflectionDetail);
|
||||
if(!FSPerfStats::tunables.userAutoTuneEnabled)
|
||||
{
|
||||
if (gSavedDrawDistance)
|
||||
{
|
||||
gSavedSettings.setF32("FSAutoTuneRenderFarClipTarget", gSavedDrawDistance);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setF32("FSAutoTuneRenderFarClipTarget", LLPipeline::RenderFarClip);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void FSFloaterPerformance::resetMaxArtSlider()
|
||||
{
|
||||
FSPerfStats::renderAvatarMaxART_ns = 0;
|
||||
FSPerfStats::tunables.updateSettingsFromRenderCostLimit();
|
||||
FSPerfStats::tunables.applyUpdates();
|
||||
updateMaxRenderTime();
|
||||
}
|
||||
|
||||
void FSFloaterPerformance::savePreset()
|
||||
{
|
||||
LLFloaterReg::showInstance("save_pref_preset", "graphic" );
|
||||
}
|
||||
|
||||
void FSFloaterPerformance::loadPreset()
|
||||
{
|
||||
LLFloaterReg::showInstance("load_pref_preset", "graphic");
|
||||
resetMaxArtSlider();
|
||||
}
|
||||
|
||||
void FSFloaterPerformance::setHardwareDefaults()
|
||||
{
|
||||
LLFeatureManager::getInstance()->applyRecommendedSettings();
|
||||
// reset indirects before refresh because we may have changed what they control
|
||||
LLAvatarComplexityControls::setIndirectControls();
|
||||
gSavedSettings.setString("PresetGraphicActive", "");
|
||||
LLPresetsManager::getInstance()->triggerChangeSignal();
|
||||
resetMaxArtSlider();
|
||||
}
|
||||
|
||||
|
||||
void FSFloaterPerformance::showSelectedPanel(LLPanel* selected_panel)
|
||||
{
|
||||
hidePanels();
|
||||
|
|
@ -240,104 +291,111 @@ void FSFloaterPerformance::draw()
|
|||
// tot_frame_time_ns -= tot_limit_time_ns;
|
||||
// tot_frame_time_ns -= tot_sleep_time_ns;
|
||||
|
||||
if(tot_frame_time_ns == 0)
|
||||
if(tot_frame_time_ns != 0)
|
||||
{
|
||||
LL_WARNS("performance") << "things went wrong, quit while we can." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
auto pct_avatar_time = (tot_avatar_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_huds_time = (tot_huds_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_ui_time = (tot_ui_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_idle_time = (tot_idle_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_swap_time = (tot_swap_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_scene_render_time = (tot_scene_time_ns * 100)/tot_frame_time_ns;
|
||||
pct_avatar_time = llclamp(pct_avatar_time,0.,100.);
|
||||
pct_huds_time = llclamp(pct_huds_time,0.,100.);
|
||||
pct_ui_time = llclamp(pct_ui_time,0.,100.);
|
||||
pct_idle_time = llclamp(pct_idle_time,0.,100.);
|
||||
pct_swap_time = llclamp(pct_swap_time,0.,100.);
|
||||
pct_scene_render_time = llclamp(pct_scene_render_time,0.,100.);
|
||||
auto pct_avatar_time = (tot_avatar_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_huds_time = (tot_huds_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_ui_time = (tot_ui_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_idle_time = (tot_idle_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_swap_time = (tot_swap_time_ns * 100)/tot_frame_time_ns;
|
||||
auto pct_scene_render_time = (tot_scene_time_ns * 100)/tot_frame_time_ns;
|
||||
pct_avatar_time = llclamp(pct_avatar_time,0.,100.);
|
||||
pct_huds_time = llclamp(pct_huds_time,0.,100.);
|
||||
pct_ui_time = llclamp(pct_ui_time,0.,100.);
|
||||
pct_idle_time = llclamp(pct_idle_time,0.,100.);
|
||||
pct_swap_time = llclamp(pct_swap_time,0.,100.);
|
||||
pct_scene_render_time = llclamp(pct_scene_render_time,0.,100.);
|
||||
|
||||
args["AV_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_avatar_time));
|
||||
args["HUDS_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_huds_time));
|
||||
args["UI_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_ui_time));
|
||||
args["IDLE_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_idle_time));
|
||||
args["SWAP_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_swap_time));
|
||||
args["SCENERY_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_scene_render_time));
|
||||
args["TOT_FRAME_TIME"] = llformat("%02u", (U32)llround(tot_frame_time_ns/1000000));
|
||||
args["FPSCAP"] = llformat("%02u", (U32)fpsCap);
|
||||
args["FPSTARGET"] = llformat("%02u", (U32)targetFPS);
|
||||
args["AV_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_avatar_time));
|
||||
args["HUDS_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_huds_time));
|
||||
args["UI_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_ui_time));
|
||||
args["IDLE_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_idle_time));
|
||||
args["SWAP_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_swap_time));
|
||||
args["SCENERY_FRAME_PCT"] = llformat("%02u", (U32)llround(pct_scene_render_time));
|
||||
args["TOT_FRAME_TIME"] = llformat("%02u", (U32)llround(tot_frame_time_ns/1000000));
|
||||
args["FPSCAP"] = llformat("%02u", (U32)fpsCap);
|
||||
args["FPSTARGET"] = llformat("%02u", (U32)targetFPS);
|
||||
|
||||
getChild<LLTextBox>("av_frame_stats")->setText(getString("av_frame_pct", args));
|
||||
getChild<LLTextBox>("huds_frame_stats")->setText(getString("huds_frame_pct", args));
|
||||
getChild<LLTextBox>("frame_breakdown")->setText(getString("frame_stats", args));
|
||||
|
||||
auto textbox = getChild<LLTextBox>("fps_warning");
|
||||
if (tot_sleep_time_raw > 0) // We are sleeping because view is not focussed
|
||||
{
|
||||
textbox->setVisible(true);
|
||||
textbox->setText(getString("focus_fps"));
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("DrYellow"));
|
||||
unreliable = true;
|
||||
}
|
||||
else if (tot_limit_time_raw > 0)
|
||||
{
|
||||
textbox->setVisible(true);
|
||||
textbox->setText(getString("limit_fps", args));
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("DrYellow"));
|
||||
unreliable = true;
|
||||
}
|
||||
else if (FSPerfStats::autoTune)
|
||||
{
|
||||
textbox->setVisible(true);
|
||||
textbox->setText(getString("tuning_fps", args));
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("green"));
|
||||
getChild<LLTextBox>("av_frame_stats")->setText(getString("av_frame_pct", args));
|
||||
getChild<LLTextBox>("huds_frame_stats")->setText(getString("huds_frame_pct", args));
|
||||
getChild<LLTextBox>("frame_breakdown")->setText(getString("frame_stats", args));
|
||||
|
||||
auto textbox = getChild<LLTextBox>("fps_warning");
|
||||
if (tot_sleep_time_raw > 0) // We are sleeping because view is not focussed
|
||||
{
|
||||
textbox->setVisible(true);
|
||||
textbox->setText(getString("focus_fps"));
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("DrYellow"));
|
||||
unreliable = true;
|
||||
}
|
||||
else if (tot_limit_time_raw > 0)
|
||||
{
|
||||
textbox->setVisible(true);
|
||||
textbox->setText(getString("limit_fps", args));
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("DrYellow"));
|
||||
unreliable = true;
|
||||
}
|
||||
else if (FSPerfStats::tunables.userAutoTuneEnabled)
|
||||
{
|
||||
textbox->setVisible(true);
|
||||
textbox->setText(getString("tuning_fps", args));
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("green"));
|
||||
}
|
||||
else
|
||||
{
|
||||
textbox->setVisible(false);
|
||||
}
|
||||
|
||||
auto button = getChild<LLButton>("AutoTuneFPS");
|
||||
if((bool)button->getToggleState() != FSPerfStats::tunables.userAutoTuneEnabled)
|
||||
{
|
||||
button->toggleState();
|
||||
}
|
||||
if (FSPerfStats::tunables.userAutoTuneEnabled && !unreliable )
|
||||
{
|
||||
// the tuning itself is managed from another thread but we can report progress here
|
||||
|
||||
// Is our target frame time lower than current? If so we need to take action to reduce draw overheads.
|
||||
if (target_frame_time_ns <= tot_frame_time_ns)
|
||||
{
|
||||
U32 non_avatar_time_ns = tot_frame_time_ns - tot_avatar_time_ns;
|
||||
// If the target frame time < non avatar frame time then we can pototentially reach it.
|
||||
if (non_avatar_time_ns < target_frame_time_ns)
|
||||
{
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("orange"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Beq): Set advisory text for further actions
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("red"));
|
||||
}
|
||||
}
|
||||
else if (target_frame_time_ns > (tot_frame_time_ns + FSPerfStats::renderAvatarMaxART_ns))
|
||||
{
|
||||
// if we have more time to spare. Display this (the service will update things)
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("green"));
|
||||
}
|
||||
}
|
||||
|
||||
if (mHUDsPanel->getVisible())
|
||||
{
|
||||
populateHUDList();
|
||||
}
|
||||
else if (mNearbyPanel->getVisible())
|
||||
{
|
||||
populateNearbyList();
|
||||
mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR));
|
||||
}
|
||||
else if (mComplexityPanel->getVisible())
|
||||
{
|
||||
populateObjectList();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textbox->setVisible(false);
|
||||
LL_WARNS("performance") << "Scene time 0. Skipping til we have data." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (FSPerfStats::autoTune && !unreliable )
|
||||
{
|
||||
// the tuning itself is managed from another thread but we can report progress here
|
||||
|
||||
// Is our target frame time lower than current? If so we need to take action to reduce draw overheads.
|
||||
if (target_frame_time_ns <= tot_frame_time_ns)
|
||||
{
|
||||
U32 non_avatar_time_ns = tot_frame_time_ns - tot_avatar_time_ns;
|
||||
// If the target frame time < non avatar frame time then we can pototentially reach it.
|
||||
if (non_avatar_time_ns < target_frame_time_ns)
|
||||
{
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("orange"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Beq): Set advisory text for further actions
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("red"));
|
||||
}
|
||||
}
|
||||
else if (target_frame_time_ns > (tot_frame_time_ns + FSPerfStats::renderAvatarMaxART_ns))
|
||||
{
|
||||
// if we have more time to spare. Display this (the service will update things)
|
||||
textbox->setColor(LLUIColorTable::instance().getColor("green"));
|
||||
}
|
||||
}
|
||||
|
||||
if (mHUDsPanel->getVisible())
|
||||
{
|
||||
populateHUDList();
|
||||
}
|
||||
else if (mNearbyPanel->getVisible())
|
||||
{
|
||||
populateNearbyList();
|
||||
mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR));
|
||||
}
|
||||
else if (mComplexityPanel->getVisible())
|
||||
{
|
||||
populateObjectList();
|
||||
}
|
||||
|
||||
|
||||
mUpdateTimer->setTimerExpirySec(REFRESH_INTERVAL);
|
||||
}
|
||||
LLFloater::draw();
|
||||
|
|
@ -732,11 +790,9 @@ void FSFloaterPerformance::detachItem(const LLUUID& item_id)
|
|||
|
||||
void FSFloaterPerformance::onChangeQuality(const LLSD& data)
|
||||
{
|
||||
LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences");
|
||||
if (instance)
|
||||
{
|
||||
instance->onChangeQuality(data);
|
||||
}
|
||||
U32 level = (U32)(data.asReal());
|
||||
LLFeatureManager::getInstance()->setGraphicsLevel(level, true);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void FSFloaterPerformance::onClickHideAvatars()
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue